diff --git a/.changeset/eleven-plants-grow.md b/.changeset/eleven-plants-grow.md new file mode 100644 index 00000000000..b08e57e1660 --- /dev/null +++ b/.changeset/eleven-plants-grow.md @@ -0,0 +1,5 @@ +--- +"@spectrum-css/generator": patch +--- + +Update story templates to include the cssprops imports diff --git a/.changeset/new-bulldogs-add.md b/.changeset/new-bulldogs-add.md new file mode 100644 index 00000000000..a5328a1d0ac --- /dev/null +++ b/.changeset/new-bulldogs-add.md @@ -0,0 +1,5 @@ +--- +"@spectrum-css/preview": minor +--- + +New feature: Custom properties panel added to the development preview showing a list of modifiable custom properties as loaded from the metadata/metadata.json resource in each component. diff --git a/.eslintrc b/.eslintrc index f422aa9e96a..90621e80f66 100644 --- a/.eslintrc +++ b/.eslintrc @@ -8,6 +8,11 @@ "parserOptions": { "sourceType": "module" }, + "settings": { + "react": { + "version": "detect" + } + }, "extends": "eslint:recommended", "rules": { "brace-style": ["warn", "stroustrup", { "allowSingleLine": true }], @@ -17,7 +22,8 @@ "no-console": ["warn", { "allow": ["warn", "error"] }], "quotes": ["warn", "double"], "semi": ["warn", "always"], - "space-before-blocks": ["warn", "always"] + "space-before-blocks": ["warn", "always"], + "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }] }, "overrides": [ { @@ -172,8 +178,10 @@ "files": [ "components/*/stories/*.js", ".storybook/*.js", - ".storybook/**/*.js" + ".storybook/**/*.js", + "plugins/storybook-addon-*/*.js" ], + "extends": ["plugin:react/recommended", "plugin:react/jsx-runtime"], "parserOptions": { "ecmaVersion": "latest", "sourceType": "module", diff --git a/.storybook/decorators/utilities.js b/.storybook/decorators/utilities.js index f6722ae79ea..bd22ac68401 100644 --- a/.storybook/decorators/utilities.js +++ b/.storybook/decorators/utilities.js @@ -556,12 +556,12 @@ export const renderContent = (content = [], { if (content.length === 0) return nothing; return html` - ${content.map((c) => { + ${content.map((c, idx) => { if (typeof c === "undefined") return nothing; /* If the content is an object (but not a lit object), we need to merge the object with the template */ if (typeof c !== "string" && (typeof c === "object" && !c._$litType$)) { - return callback({ ...args, ...c }, context); + return callback({ ...args, ...c, idx }, context); } if (typeof c === "function") { diff --git a/.storybook/main.js b/.storybook/main.js index ccd00e2f45e..93e1f9f8f53 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -63,11 +63,13 @@ export default { name: "@storybook/addon-actions", options: {}, }, - // https://www.npmjs.com/package/@whitespace/storybook-addon-html - "@whitespace/storybook-addon-html", + // Local: plugins/storybook-addon-custom-properties + "@spectrum-tools/storybook-addon-custom-properties", // https://github.com/storybookjs/storybook/tree/next/code/addons/a11y - "@storybook/addon-a11y", + "@whitespace/storybook-addon-html", // https://storybook.js.org/addons/@etchteam/storybook-addon-status + "@storybook/addon-a11y", + // https://www.npmjs.com/package/@whitespace/storybook-addon-html "@etchteam/storybook-addon-status", // https://github.com/storybookjs/storybook/tree/next/code/addons/interactions "@storybook/addon-interactions", diff --git a/.storybook/package.json b/.storybook/package.json index 30ab7f9cddf..5ae48b7784c 100644 --- a/.storybook/package.json +++ b/.storybook/package.json @@ -46,9 +46,10 @@ "@spectrum-css/ui-icons": "1.1.2" }, "devDependencies": { - "@babel/core": "^7.26.0", + "@babel/core": "^7.26.10", "@chromatic-com/storybook": "^3.2.3", "@etchteam/storybook-addon-status": "^5.0.0", + "@spectrum-tools/storybook-addon-custom-properties": "0.0.0", "@storybook/addon-a11y": "8.4.7", "@storybook/addon-actions": "8.4.7", "@storybook/addon-designs": "^8.2.1", @@ -65,7 +66,7 @@ "@storybook/theming": "8.4.7", "@storybook/web-components-vite": "8.4.7", "@whitespace/storybook-addon-html": "^6.1.1", - "chromatic": "^11.22.2", + "chromatic": "^11.27.0", "lit": "^3.2.1", "lodash-es": "^4.17.21", "npm-registry-fetch": "^18.0.2", @@ -77,7 +78,7 @@ "remark-gfm": "^4.0.0", "rollup-plugin-postcss-lit": "^2.1.0", "storybook": "8.4.7", - "vite": "^5.4.11" + "vite": "^5.4.14" }, "keywords": [ "design-system", diff --git a/components/accordion/index.css b/components/accordion/index.css index 2e0a7616455..5efc16a6419 100644 --- a/components/accordion/index.css +++ b/components/accordion/index.css @@ -72,6 +72,7 @@ &:lang(ja), &:lang(zh), &:lang(ko) { + /* @description When the language is CJK, update line-height values to prevent cut off diacritics */ --spectrum-accordion-item-header-line-height: var(--spectrum-cjk-line-height-100); --spectrum-accordion-item-content-line-height: var(--spectrum-cjk-line-height-100); } diff --git a/components/accordion/stories/accordion.stories.js b/components/accordion/stories/accordion.stories.js index 3709e75871f..b3aae204bf5 100644 --- a/components/accordion/stories/accordion.stories.js +++ b/components/accordion/stories/accordion.stories.js @@ -3,11 +3,14 @@ import { Sizes } from "@spectrum-css/preview/decorators"; import { disableDefaultModes } from "@spectrum-css/preview/modes"; import { size } from "@spectrum-css/preview/types"; import { Template as Typography } from "@spectrum-css/typography/stories/template.js"; -import metadata from "../dist/metadata.json"; -import packageJson from "../package.json"; import { AccordionGroup } from "./accordion.test.js"; import { Template } from "./template.js"; +// Local assets to render the component styles and structure +import styles from "../index.css?inline"; +import metadata from "../dist/metadata.json"; +import packageJson from "../package.json"; + /** * The accordion element contains a list of items that can be expanded or collapsed to reveal additional content or information associated with each item. There can be zero expanded items, exactly one expanded item, or more than one item expanded at a time, depending on the configuration. This list of items is defined by child accordion item elements. * @@ -68,6 +71,7 @@ export default { }, packageJson, metadata, + cssprops: { styles }, }, }; diff --git a/components/actionbar/stories/actionbar.stories.js b/components/actionbar/stories/actionbar.stories.js index aa2e867ea09..1c5706fbd1d 100644 --- a/components/actionbar/stories/actionbar.stories.js +++ b/components/actionbar/stories/actionbar.stories.js @@ -3,11 +3,14 @@ import { default as CloseButton } from "@spectrum-css/closebutton/stories/closeb import { default as Popover } from "@spectrum-css/popover/stories/popover.stories.js"; import { disableDefaultModes } from "@spectrum-css/preview/modes"; import { isEmphasized, isOpen } from "@spectrum-css/preview/types"; -import metadata from "../dist/metadata.json"; -import packageJson from "../package.json"; import { ActionBarGroup } from "./actionbar.test.js"; import { BehavioralTemplate } from "./template.js"; +// Local assets to render the component styles and structure +import styles from "../index.css?inline"; +import metadata from "../dist/metadata.json"; +import packageJson from "../package.json"; + /** * The action bar component is a floating full width bar that appears upon selection. Action bars are used for single and bulk selection patterns, when a user needs to perform actions on either a single or multiple items at the same time. * @@ -72,6 +75,7 @@ export default { }, packageJson, metadata, + cssprops: { styles }, }, }; diff --git a/components/actionbar/stories/template.js b/components/actionbar/stories/template.js index 8b134157bd2..d1b9125cfcc 100644 --- a/components/actionbar/stories/template.js +++ b/components/actionbar/stories/template.js @@ -1,10 +1,11 @@ -import { Container } from "@spectrum-css/preview/decorators"; import { Template as ActionGroup } from "@spectrum-css/actiongroup/stories/template.js"; import { Template as CloseButton } from "@spectrum-css/closebutton/stories/template.js"; import { Template as FieldLabel } from "@spectrum-css/fieldlabel/stories/template.js"; import { Template as Popover } from "@spectrum-css/popover/stories/template.js"; +import { Container, getRandomId } from "@spectrum-css/preview/decorators"; import { html } from "lit"; import { classMap } from "lit/directives/class-map.js"; +import { ifDefined } from "lit/directives/if-defined.js"; import { styleMap } from "lit/directives/style-map.js"; import "../index.css"; @@ -14,6 +15,7 @@ import "../themes/express.css"; export const Template = ({ rootClass = "spectrum-ActionBar", + id = getRandomId("action-bar"), size = "m", isOpen = true, isEmphasized = false, @@ -36,6 +38,7 @@ export const Template = ({ "is-open": isOpen, ...customClasses.reduce((a, c) => ({ ...a, [c]: true }), {}), })} + id=${ifDefined(id)} style=${styleMap(customStyles)} > ${Popover({ diff --git a/components/actionbutton/stories/actionbutton.stories.js b/components/actionbutton/stories/actionbutton.stories.js index a08f0f7bbfc..db2ab14815a 100644 --- a/components/actionbutton/stories/actionbutton.stories.js +++ b/components/actionbutton/stories/actionbutton.stories.js @@ -2,11 +2,14 @@ import { default as IconStories } from "@spectrum-css/icon/stories/icon.stories. import { Sizes } from "@spectrum-css/preview/decorators"; import { disableDefaultModes } from "@spectrum-css/preview/modes"; import { isActive, isDisabled, isEmphasized, isFocused, isHovered, isQuiet, isSelected, size, staticColor } from "@spectrum-css/preview/types"; -import metadata from "../dist/metadata.json"; -import packageJson from "../package.json"; import { ActionButtonGroup } from "./actionbutton.test.js"; import { ActionButtonsWithIconOptions, IconOnlyOption, TreatmentTemplate } from "./template.js"; +// Local assets to render the component styles and structure +import styles from "../index.css?inline"; +import metadata from "../dist/metadata.json"; +import packageJson from "../package.json"; + /** * The action button component represents an action a user can take. * @@ -90,6 +93,7 @@ export default { }, packageJson, metadata, + cssprops: { styles }, docs: { story: { height: "auto", diff --git a/components/actionbutton/stories/template.js b/components/actionbutton/stories/template.js index 425b7e4115c..8fe3fb96d59 100644 --- a/components/actionbutton/stories/template.js +++ b/components/actionbutton/stories/template.js @@ -46,6 +46,7 @@ import { Template as Icon } from "@spectrum-css/icon/stories/template.js"; */ export const Template = ({ rootClass = "spectrum-ActionButton", + id = getRandomId("action-button"), size = "m", iconName, iconSet = "workflow", @@ -65,7 +66,6 @@ export const Template = ({ customStyles = {}, customIconClasses = [], onclick, - id = getRandomId("actionbutton"), testId, role = "button", } = {}, context = {}) => { diff --git a/components/actiongroup/stories/actiongroup.stories.js b/components/actiongroup/stories/actiongroup.stories.js index a83857b9e54..f1de7f56585 100644 --- a/components/actiongroup/stories/actiongroup.stories.js +++ b/components/actiongroup/stories/actiongroup.stories.js @@ -2,11 +2,14 @@ import { default as ActionButton } from "@spectrum-css/actionbutton/stories/acti import { Sizes } from "@spectrum-css/preview/decorators"; import { disableDefaultModes } from "@spectrum-css/preview/modes"; import { size } from "@spectrum-css/preview/types"; -import metadata from "../dist/metadata.json"; -import packageJson from "../package.json"; import { ActionGroups } from "./actiongroup.test.js"; import { OverflowOption, TreatmentTemplate } from "./template.js"; +// Local assets to render the component styles and structure +import styles from "../index.css?inline"; +import metadata from "../dist/metadata.json"; +import packageJson from "../package.json"; + /** * An action group is a grouping of [action buttons](/docs/components-action-button--docs) that are related to each other. */ @@ -99,6 +102,7 @@ export default { }, packageJson, metadata, + cssprops: { styles }, }, }; diff --git a/components/actiongroup/stories/template.js b/components/actiongroup/stories/template.js index d13cdac64aa..29bf8f1af7c 100644 --- a/components/actiongroup/stories/template.js +++ b/components/actiongroup/stories/template.js @@ -1,7 +1,8 @@ import { Template as ActionButton } from "@spectrum-css/actionbutton/stories/template.js"; -import { Container, renderContent } from "@spectrum-css/preview/decorators"; +import { Container, getRandomId, renderContent } from "@spectrum-css/preview/decorators"; import { html } from "lit"; import { classMap } from "lit/directives/class-map.js"; +import { ifDefined } from "lit/directives/if-defined.js"; import { styleMap } from "lit/directives/style-map.js"; import { capitalize } from "lodash-es"; @@ -12,6 +13,7 @@ import "../themes/express.css"; export const Template = ({ rootClass = "spectrum-ActionGroup", + id = getRandomId("accordion-group"), size = "m", areQuiet = false, areEmphasized = false, @@ -41,6 +43,7 @@ export const Template = ({ ...customClasses.reduce((a, c) => ({ ...a, [c]: true }), {}), })} style=${styleMap(customStyles)} + id=${ifDefined(id)} > ${renderContent(content, { callback: ActionButton, diff --git a/components/actionmenu/stories/actionmenu.stories.js b/components/actionmenu/stories/actionmenu.stories.js index e9cdd3b8a14..44bc6cc0f6c 100644 --- a/components/actionmenu/stories/actionmenu.stories.js +++ b/components/actionmenu/stories/actionmenu.stories.js @@ -4,9 +4,11 @@ import { default as Menu } from "@spectrum-css/menu/stories/menu.stories.js"; import { default as Popover } from "@spectrum-css/popover/stories/popover.stories.js"; import { disableDefaultModes } from "@spectrum-css/preview/modes"; import { isOpen } from "@spectrum-css/preview/types"; -import packageJson from "../package.json"; import { ActionMenuGroup } from "./actionmenu.test.js"; +// Local assets to render the component styles and structure +import packageJson from "../package.json"; + /** * The action menu component is an action button with a popover. The `is-selected` class should be applied to the button when the menu is open. Note that the accessibility roles are different for an action menu compared to a normal menu. */ @@ -49,6 +51,7 @@ export default { ], }, packageJson, + cssprops: false, docs: { story: { height: "200px", diff --git a/components/actionmenu/stories/template.js b/components/actionmenu/stories/template.js index c4bc29768d9..19b6e722612 100644 --- a/components/actionmenu/stories/template.js +++ b/components/actionmenu/stories/template.js @@ -4,7 +4,7 @@ import { Template as Popover } from "@spectrum-css/popover/stories/template.js"; import { getRandomId } from "@spectrum-css/preview/decorators"; export const Template = ({ - id = getRandomId("actionmenu"), + id = getRandomId("action-menu"), testId, triggerId = getRandomId("actionmenu-trigger"), customClasses = [], diff --git a/components/alertbanner/stories/alertbanner.stories.js b/components/alertbanner/stories/alertbanner.stories.js index cd49c21a70e..581607409be 100644 --- a/components/alertbanner/stories/alertbanner.stories.js +++ b/components/alertbanner/stories/alertbanner.stories.js @@ -5,6 +5,9 @@ import packageJson from "../package.json"; import { AlertBannerGroup } from "./alertbanner.test.js"; import { ActionableOptionsTemplate, Template, TextOverflowTemplate } from "./template.js"; +// Local assets to render the component styles and structure +import styles from "../index.css?inline"; + /** * The alert banner shows pressing and high-signal messages, such as system alerts. It is meant to be noticed and prompt users to take action. * It should occupy all of the available horizontal space until it reaches its maximum allowed width. @@ -75,6 +78,7 @@ export default { }, packageJson, metadata, + cssprops: { styles }, }, }; diff --git a/components/alertbanner/stories/template.js b/components/alertbanner/stories/template.js index 3eb719c0612..11134f2a311 100644 --- a/components/alertbanner/stories/template.js +++ b/components/alertbanner/stories/template.js @@ -16,7 +16,7 @@ import "../themes/express.css"; export const Template = ({ rootClass = "spectrum-AlertBanner", - id = getRandomId("alertbanner"), + id = getRandomId("alert-banner"), testId, isOpen = true, text, @@ -35,7 +35,7 @@ export const Template = ({ ...customClasses.reduce((a, c) => ({ ...a, [c]: true }), {}), })} style=${styleMap(customStyles)} - id=${id} + id=${ifDefined(id)} data-testid=${ifDefined(testId)} >