diff --git a/.env.example b/.env.example index 6078e98f666..9ec88088577 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,8 @@ CHROMATIC_PROJECT_TOKEN=1234abcd CHROMATIC_PROJECT_ID="Project:64762974a45b8bc5ca1705a2" -CHROMATIC_BUILD_SCRIPT_NAME="ci:storybook" +# Note: the build script here should be defined in .storybook/package.json +# this is used by the chromatic storybook addon to build the storybook on the fly +CHROMATIC_BUILD_SCRIPT_NAME="build" # NX settings NX_PREFER_TS_NODE=true diff --git a/.github/actions/file-diff/README.md b/.github/actions/file-diff/README.md index fe5565bb829..69ee1c91426 100644 --- a/.github/actions/file-diff/README.md +++ b/.github/actions/file-diff/README.md @@ -4,11 +4,11 @@ A GitHub Action for comparing compiled assets between branches. ## Inputs -### `path` +### `head-path` **Required** Path to file or directory for file sizes analysis. -### `diff-path` +### `base-path` **Optional** Path to another directory against which to perform file comparisons. @@ -44,8 +44,8 @@ Total size of all files for this branch in bytes. name: Compare compiled output file size uses: "spectrum-tools/gh-action-file-diff" with: - path: ${{ github.workspace }}/pull-request - diff-path: ${{ github.workspace }}/base-branch + head-path: ${{ github.workspace }}/pull-request + base-path: ${{ github.workspace }}/base-branch file-glob-pattern: | components/*/dist/*.{css,json} components/*/dist/themes/*.css diff --git a/.github/actions/file-diff/action.yml b/.github/actions/file-diff/action.yml index ec3f7a8e407..66e30f6c2b3 100644 --- a/.github/actions/file-diff/action.yml +++ b/.github/actions/file-diff/action.yml @@ -2,11 +2,11 @@ name: "File comparisons" description: "Compares files between branches." author: "spectrum-tools" inputs: - path: + head-path: description: "Path to file or directory for file sizes analysis." required: false default: ${{ github.workspace }} - diff-path: + base-path: description: "Optional path to another directory to perform file size diff against the provided path." required: false token: diff --git a/.github/actions/file-diff/index.js b/.github/actions/file-diff/index.js index a94122b5a5e..b1b8b5b0b5a 100644 --- a/.github/actions/file-diff/index.js +++ b/.github/actions/file-diff/index.js @@ -26,8 +26,8 @@ async function run() { try { // --------------- Fetch user input values --------------- const token = core.getInput("token"); - const path = core.getInput("path"); - const diffPath = core.getInput("diff-path"); + const headPath = core.getInput("head-path"); + const basePath = core.getInput("base-path"); const fileGlobPattern = core.getMultilineInput("file-glob-pattern", { trimWhitespace: true, }); @@ -37,14 +37,14 @@ async function run() { // --------------- Evaluate compiled assets --------------- /** @type Map */ - const pathOutput = await fetchFilesAndSizes(path, fileGlobPattern, { + const headOutput = await fetchFilesAndSizes(headPath, fileGlobPattern, { core, }); /** * If a diff path is provided, get the diff files and their sizes * @type Map **/ - const diffOutput = await fetchFilesAndSizes(diffPath, fileGlobPattern, { + const baseOutput = await fetchFilesAndSizes(basePath, fileGlobPattern, { core, }); /** @@ -52,24 +52,28 @@ async function run() { * and not just reporting on the overall size of the compiled assets * @type boolean */ - const hasDiff = diffOutput.size > 0; + const hasDiff = baseOutput.size > 0; // --------------- End evaluation --------------- /** Split the data by component package */ - const { filePath, PACKAGES } = splitDataByPackage(pathOutput, path, diffOutput); - const sections = makeTable(PACKAGES, filePath, path); + const { filePath, PACKAGES } = splitDataByPackage(headOutput, headPath, baseOutput); + const sections = makeTable(PACKAGES, filePath, headPath); - const overallSize = [...pathOutput.values()].reduce( + /** Calculate the total size of the pull request's assets */ + const overallHeadSize = [...headOutput.values()].reduce( (acc, size) => acc + size, 0 ); - /** Calculate the overall size of the updated assets */ - const overallDiffSize = hasDiff - ? [...diffOutput.values()].reduce((acc, size) => acc + size, 0) + /** Calculate the overall size of the base branch's assets */ + const overallBaseSize = hasDiff + ? [...baseOutput.values()].reduce((acc, size) => acc + size, 0) : undefined; + const hasChange = overallHeadSize !== overallBaseSize; + /** If no diff map data provided, we're going to report on the overall size */ + /** * If the updated assets are the same as the original, * report no change @@ -78,89 +82,98 @@ async function run() { const markdown = []; const summary = [ "### Summary", - `**Total size**: ${bytesToSize(overallDiffSize)}*` + `**Total size**: ${bytesToSize(overallHeadSize)}*`, ]; - const summaryTable = []; + + let summaryTable = []; if (sections.length === 0) { summary.push(...["", " 🎉 No changes detected in any packages"]); } else { - if (diffOutput.size > 0 && hasDiff) { - let changeSummary = `**Total change (Δ)**: ${printChange( - overallDiffSize - overallSize - )}`; - - if (overallSize === overallDiffSize) changeSummary += " 🎉"; - else - changeSummary += ` (${printPercentChange( - (overallDiffSize - overallSize) / overallSize - )})`; - - summary.push(...[changeSummary, ""]); + /** + * Calculate the change in size + * PR - base / base = change + */ + let changeSummary = ""; + if (baseOutput.size > 0 && hasDiff && hasChange) { + changeSummary = `**Total change (Δ)**: ${printChange(overallHeadSize, overallBaseSize)} (${printPercentChange(overallHeadSize, overallBaseSize)})`; + } else if (baseOutput.size > 0 && hasDiff && !hasChange) { + changeSummary = `No change in file sizes`; } - summaryTable.push( - ["Package", "Size", ...(hasDiff ? ["Δ"] : [])], - ["-", "-", ...(hasDiff ? ["-"] : [])] - ); + if (changeSummary !== "") { + summary.push(...[ + changeSummary, + "Table reports on changes to a package's main file. Other changes can be found in the collapsed \"Details\" below.", + "" + ]); + } markdown.push(`
`, `Details`, ""); - sections.map(({ name, filePath, totalSize, totalDiffSize, hasChange, fileMap }) => { - const md = ["", `#### ${name}`, ""]; - const data = [name, bytesToSize(totalDiffSize)]; - + sections.map(({ name, filePath, headMainSize, baseMainSize, hasChange, mainFile, fileMap }) => { if (!hasChange) return; + const data = []; + + /** We only evaluate changes if there is a diff branch being used and this is the main file for the package */ if (hasDiff) { - // If a diff path was provided and the component folder doesn't exist, - // report that the compiled assets were removed + /** + * If: the component folder exists in the original branch but not the PR + * Or: the pull request file size is 0 or empty but the original branch has a size + * Then: report that it was removed, moved, or renamed + * + * Else if: the component folder exists in the PR but not the original branch + * Or: the pull request file has size but the original branch does not + * Then: report that it's new + * + * Else if: the difference between the two sizes is not 0 (i.e. there is a change) + * Then: report the change + * + * Else: report that there is no change + */ if ( - !existsSync(join(diffPath, filePath, name)) || - (totalSize === 0 && totalDiffSize > 0) + (existsSync(join(basePath, filePath, name)) && !existsSync(join(headPath, filePath, name))) ) { data.push("🚨 deleted, moved, or renamed"); - summaryTable.push(data); - } else if (totalSize > 0 && totalDiffSize === 0) { + } else if ( + (existsSync(join(headPath, filePath, name)) && !existsSync(join(basePath, filePath, name))) + ) { data.push("🎉 new"); - summaryTable.push(data); - } else if (bytesToSize(Math.abs(totalDiffSize - totalSize)) !== "< 0.01 KB") { - data.push(printChange(totalDiffSize - totalSize)); - summaryTable.push(data); + } else if ( + ((Math.abs(difference(headMainSize, baseMainSize))) / 1000) >= 0.001 + ) { + data.push(printChange(headMainSize, baseMainSize)); + } + + if (data.length > 0) { + summaryTable.push([name, bytesToSize(headMainSize), data]); } } + + const md = ["", `#### ${name}`, ""]; md.push( ...[ - ["File", "Size", ...(hasDiff ? ["Base", "Δ"] : [])], + ["File", "Head", ...(hasDiff ? ["Base", "Δ"] : [])], [" - ", " - ", ...(hasDiff ? [" - ", " - "] : [])], - [ - "**Total**", - bytesToSize(totalSize), - ...(hasDiff - ? [ - bytesToSize(totalDiffSize), - `${printChange(totalDiffSize - totalSize)}${totalDiffSize - totalSize !== 0 ? ` (${printPercentChange((totalDiffSize - totalSize) / totalSize)})` : ""}`, - ] - : []), - ], ].map((row) => `| ${row.join(" | ")} |`), ...[...fileMap.entries()] .reduce( ( - table, - [readableFilename, { byteSize = 0, diffByteSize = 0 }] + table, // accumulator + [readableFilename, { headByteSize = 0, baseByteSize = 0 }] // deconstructed filemap entry; i.e., Map = [key, { ...values }] ) => { // @todo readable filename can be linked to html diff of the file? // https://github.com/adobe/spectrum-css/pull/2093/files#diff-6badd53e481452b5af234953767029ef2e364427dd84cdeed25f5778b6fca2e6 return [ ...table, [ - readableFilename, - byteSize === 0 && diffByteSize > 0 ? "**removed**" : bytesToSize(byteSize), + readableFilename === mainFile ? `**${readableFilename}**` : readableFilename, + isRemoved(headByteSize, baseByteSize) ? "**removed**" : isNew(headByteSize, baseByteSize) ? "**new**" : bytesToSize(headByteSize), ...(hasDiff ? [ - bytesToSize(diffByteSize), - `${printChange(diffByteSize - byteSize)}${diffByteSize - byteSize !== 0 ? ` (${printPercentChange((diffByteSize - byteSize) / byteSize)})` : ""}`, + bytesToSize(baseByteSize), + `${printChange(headByteSize, baseByteSize)}${difference(headByteSize, baseByteSize) !== 0 ? ` (${printPercentChange(headByteSize , baseByteSize)})` : ""}`, ] : []), ] ]; @@ -176,7 +189,14 @@ async function run() { markdown.push("", `
`); } - if (summaryTable.length > 1) { + if (summaryTable.length > 0) { + // Add the headings to the summary table if it contains data + summaryTable = [ + ["Package", "Size", ...(hasDiff ? ["Δ"] : [])], + ["-", "-", ...(hasDiff ? ["-"] : [])], + ...summaryTable, + ]; + summary.push(...summaryTable.map((row) => `| ${row.join(" | ")} |`)); } @@ -210,22 +230,22 @@ async function run() { core.summary = summary.join("\n"); // --------------- Set output variables --------------- - if (pathOutput.size > 0) { - const totalSize = [...pathOutput.entries()].reduce( + if (headOutput.size > 0) { + const headMainSize = [...headOutput.entries()].reduce( (acc, [_, size]) => acc + size, 0 ); - core.setOutput("total-size", totalSize); + core.setOutput("total-size", headMainSize); if (hasDiff) { - const totalDiffSize = [...diffOutput.entries()].reduce( + const baseMainSize = [...baseOutput.entries()].reduce( (acc, [_, size]) => acc + size, 0 ); core.setOutput( "has-changed", - hasDiff && totalSize !== totalDiffSize ? "true" : "false" + hasDiff && headMainSize !== baseMainSize ? "true" : "false" ); } } else { @@ -239,16 +259,23 @@ async function run() { run(); +/** A few helpful utility functions; v1 == PR (change); v0 == base (initial) */ +const difference = (v1, v0) => v1 - v0; +const isRemoved = (v1, v0) => (!v1 || v1 === 0) && (v0 && v0 > 0); +const isNew = (v1, v0) => (v1 && v1 > 0) && (!v0 || v0 === 0); + /** * Convert the provided difference between file sizes into a human * readable representation of the change. * @param {number} difference * @returns {string} */ -const printChange = function (difference) { - return difference === 0 +const printChange = function (v1, v0) { + /** Calculate the change in size: v1 - v0 = change */ + const d = difference(v1, v0); + return d === 0 ? `-` - : `${difference > 0 ? "⬆" : "⬇"} ${bytesToSize(Math.abs(difference))}`; + : `${d > 0 ? "⬆" : "⬇"} ${bytesToSize(Math.abs(d))}`; }; /** @@ -258,17 +285,18 @@ const printChange = function (difference) { * @param {number} original * @returns {string} */ -const printPercentChange = function (delta) { +const printPercentChange = function (v1, v0) { + const delta = ((v1 - v0) / v0) * 100; if (delta === 0) return `no change`; - return `${Math.abs(delta * 100).toFixed(2)}%`; + return `${delta.toFixed(2)}%`; }; /** * - * @param {Map>} PACKAGES + * @param {Map>} PACKAGES * @param {string} filePath - The path to the component's dist folder from the root of the repo * @param {string} path - The path from the github workspace to the root of the repo - * @returns {Array<{ name: string, filePath: string, totalSize: number, totalDiffSize: number, hasChange: boolean, fileMap: Map}>} + * @returns {Array<{ name: string, filePath: string, headMainSize: number, baseMainSize: number, hasChange: boolean, fileMap: Map}>} */ const makeTable = function (PACKAGES, filePath, path) { const sections = []; @@ -280,38 +308,41 @@ const makeTable = function (PACKAGES, filePath, path) { let mainFile = "index.css"; if (existsSync(packagePath)) { - mainFile = require(join(path, filePath, packageName, "package.json"))?.main; + const { main } = require(packagePath) ?? {}; + if (main) mainFile = main.replace(/^.*\/dist\//, ""); } const mainFileOnly = [...fileMap.keys()].filter((file) => file.endsWith(mainFile)); - const totalSize = mainFileOnly.reduce( + const headMainSize = mainFileOnly.reduce( (acc, filename) => { - const { byteSize = 0 } = fileMap.get(filename); - return acc + byteSize; + const { headByteSize = 0 } = fileMap.get(filename); + return acc + headByteSize; }, 0 ); - const totalDiffSize = mainFileOnly.reduce( + + const baseMainSize = mainFileOnly.reduce( (acc, filename) => { - const { diffByteSize = 0 } = fileMap.get(filename); - return acc + diffByteSize; + const { baseByteSize = 0 } = fileMap.get(filename); + return acc + baseByteSize; }, 0 ); - const hasChange = fileMap.size > 0 && [...fileMap.values()].some(({ byteSize, diffByteSize }) => byteSize !== diffByteSize); + const hasChange = fileMap.size > 0 && [...fileMap.values()].some(({ headByteSize, baseByteSize }) => headByteSize !== baseByteSize); /** * We don't need to report on components that haven't changed unless they're new or removed */ - if (totalSize === totalDiffSize) return; + if (headMainSize === baseMainSize) return; sections.push({ name: packageName, filePath, - totalSize, - totalDiffSize, + headMainSize, + baseMainSize, hasChange, + mainFile: mainFileOnly?.[0], fileMap }); }); @@ -323,14 +354,14 @@ const makeTable = function (PACKAGES, filePath, path) { * Split out the data indexed by filename into groups by component * @param {Map} dataMap * @param {string} path - * @param {Map} diffMap - * @returns {{ filePath: string, PACKAGES: Map>}} + * @param {Map} baseMap + * @returns {{ filePath: string, PACKAGES: Map>}} */ -const splitDataByPackage = function (dataMap, path, diffMap = new Map()) { +const splitDataByPackage = function (dataMap, path, baseMap = new Map()) { const PACKAGES = new Map(); let filePath; - [...dataMap.entries()].forEach(([file, byteSize]) => { + [...dataMap.entries()].forEach(([file, headByteSize]) => { // Determine the name of the component const parts = file.split(sep); const componentIdx = parts.findIndex((part) => part === "dist") - 1; @@ -348,8 +379,8 @@ const splitDataByPackage = function (dataMap, path, diffMap = new Map()) { if (!fileMap.has(readableFilename)) { fileMap.set(readableFilename, { - byteSize, - diffByteSize: diffMap.get(file), + headByteSize: headByteSize, + baseByteSize: baseMap.get(file), }); } else { throw new Error(`The file ${file} was found twice in the dataset`); diff --git a/.github/workflows/compare-results.yml b/.github/workflows/compare-results.yml index 6799cf9b3e9..a13fc88cf04 100644 --- a/.github/workflows/compare-results.yml +++ b/.github/workflows/compare-results.yml @@ -90,8 +90,8 @@ jobs: uses: ./.github/actions/file-diff # uses: spectrum-tools/gh-action-file-diff@v1 with: - path: ${{ github.workspace }}/${{ inputs.head-sha }}/ - diff-path: ${{ github.workspace }}/${{ inputs.base-sha }}/ + head-path: ${{ github.workspace }}/${{ inputs.head-sha }}/ + base-path: ${{ github.workspace }}/${{ inputs.base-sha }}/ file-glob-pattern: | components/*/dist/** tokens/dist/** diff --git a/.storybook/README.md b/.storybook/README.md index 58df51a9c3d..903be2ff4c6 100644 --- a/.storybook/README.md +++ b/.storybook/README.md @@ -120,7 +120,7 @@ argTypes: { _Note:_ In your story, be sure to include the `if: false` override otherwise the control will only show up if you have a `setName` arg and it is equal to `workflow`. -Want to load UI icons instead? Use the following variable import instead: +Want to load UI icons instead? Use the following variable import instead of the above: ```js argTypes: { @@ -205,6 +205,75 @@ label: { }, ``` +### args + +In a story, the args object contains all the default values for the component. These values will be used to render the component in the storybook preview. The values can be overridden by the user via the controls or by setting a custom args object in a specific story. + +The default story should _almost_ always have any empty args object because it is, by nature, using all the default settings. + +```js +export const Default = Template.bind({}); +Default.args = {}; +``` + +Subsequent stories can override the default args object by setting a new value for the desired property. i.e., + +```js +export const Express = Template.bind({}); +Express.args = { + express: true +}; +``` + +Try to focus stories on a single property or set of properties. This will make it easier for users to find the story they are looking for and will help in debugging issues. + +#### customStorybookStyles + +All stories are wrapped in a custom decorator that applies a few standard display properties to the preview. If you need to override these styles, you can do so by adding a `customStorybookStyles` property to your args object. This should be a string of CSS rules. i.e., + +```js +args: { + customStorybookStyles: { + flexDirection: "column", + alignItems: "flex-start", + }, +}, +``` + +The following properties are set on `#root-inner` by default: + +```css +display: flex; +gap: 10px; +``` + +If the display property is updated to something other than `*flex` or `*grid`, the gap property will be removed (`*flex` can equal `flex` or `inline-flex`). As long as the display property is not `contents`, the gap value will be assigned to `padding` instead. + +For example, if the display value is set to `block`, the following styles will be applied: + +```css +display: block; +padding: 10px; +``` + +Leveraging an argType in your component that matches `staticColor` with allowed values of `white` or `black` will automatically set the background color of the preview to an appropriate value (white will use `rgb(15, 121, 125)`; black will use `rgb(181, 209, 211)`). If you need to override this value, you can do so by setting the `customStorybookStyles` property to an object with a `backgroundColor` property. i.e., + +```js +args: { + customStorybookStyles: { + backgroundColor: "rgb(238, 14, 189)", + }, +}, +``` + +Any settings added by the story will override these values. You can unset a value completely using undefined, i.e.: + +```js +customStorybookStyles: { + display: undefined, +}, +``` + ## Templates The goal of the template files is to create a definition for this component to enforce and demonstrate the allowed semantics and required classNames and settings to achieve the desired output (based on the user's selected controls). @@ -240,6 +309,7 @@ All return values for Template functions should be outputting TemplateResults. S import { html } from "lit"; import { classMap } from "lit/directives/class-map.js"; import { ifDefined } from "lit/directives/if-defined.js"; +import { when } from "lit/directives/when.js"; import { Template as Icon } from "@spectrum-css/icon/stories/template.js"; import { Template as Avatar } from "@spectrum-css/avatar/stories/template.js"; @@ -247,7 +317,6 @@ import { Template as ClearButton } from "@spectrum-css/clearbutton/stories/templ import "../index.css"; -// More on component templates: https://storybook.js.org/docs/web-components/writing-stories/introduction#using-args export const Template = ({ rootClass = "spectrum-Tag", size = "m", @@ -272,37 +341,32 @@ export const Template = ({ console.warn(e); } - return html` -
({ ...a, [c]: true }), {}), - })} - id=${ifDefined(id)} - tabindex="0" + return html`
({ ...a, [c]: true }), {}), + })} + id=${ifDefined(id)} + tabindex="0" > - ${avatarUrl && !iconName - ? Avatar({ + ${when(avatarUrl && !iconName, () => Avatar({ ...globals, image: avatarUrl, size: "50", - }) - : ""} ${iconName - ? Icon({ + }))} + ${when(iconName, () => Icon({ ...globals, iconName, customClasses: [`${rootClass}s-itemIcon`], - }) - : ""} + }))}} ${label} - ${hasClearButton - ? ClearButton({ + ${when(hasClearButton, () => ClearButton({ ...globals, customClasses: [`${rootClass}-clearButton`], onclick: (evt) => { @@ -312,10 +376,8 @@ export const Template = ({ const wrapper = el.closest(rootClass); wrapper.parentNode.removeChild(wrapper); }, - }) - : ""} -
- `; + }))} +
`; }; ``` @@ -339,142 +401,5 @@ Runs will generate a JUnit XML file with build results (`chromatic-build-{buildN Running without publishing to Chromatic? Add the `--dry-run` flag. Need more information to debug a run? Try the `--diagnostics` flag (writes process context information to `chromatic-diagnostics.json`). -# Migration to Storybook 7.0(Draft) - -## Updates - ---- -`*` Added support for handler actions with ```withActions``` on each stories which have action handlers. - -Example: - -```js -import globalThis from 'global'; -+ import { withActions } from '@storybook/addon-actions/decorator'; - -export default { - component: globalThis.Components.Button, - args: { - label: 'Click Me!', - }, - parameters: { - chromatic: { disable: true }, - }, -}; -export const Basic = { - parameters: { - handles: [{ click: 'clicked', contextmenu: 'right clicked' }], - }, -+ decorators: [withActions], -}; -``` - -`*` Upgraded to ```Webpack 5``` for improved bundling and performance from ```webpack 4``` - -`*` @storybook addons dependencies are upgraded to v7 from v6 - -```js -"@storybook/addon-docs": "^7.0.12", -"@storybook/addon-essentials": "^7.0.12", -"@storybook/api": "^7.0.12", -"@storybook/client-api": "^7.0.12", -"@storybook/components": "^7.0.12", -"@storybook/core-events": "^7.0.12", -"@storybook/manager-api": "^7.0.12", -"@storybook/preview-api": "^7.0.12", -"@storybook/theming": "^7.0.12", -"@storybook/web-components-webpack5": "^7.0.12", -"@whitespace/storybook-addon-html": "^5.1.4", -``` - -`*` Added a new "Controls" addon for interactive component props editing. - -`*` Introduced a new "Docs-only" mode for isolating component documentation. - -`*` Improved the addon ecosystem with new and updated addons. - -

- -## Breaking Changes - ---- -`*` client-api is deperacted and preview-api is introduced - -```js - - import { useEffect } from '@storybook/client-api'; - + import { useEffect } from '@storybook/preview-api'; -``` - -`*` @storybook/addons is deperacted and replaced with @storybook/manager-api - -```js - - import { addons } from '@storybook/addons'; - + import { addons } from '@storybook/manager-api'; -``` - -`*` ```@storybook-webcomponents``` is deprecated. ```@storybook/web-components-webpack'``` is added with webpack 5 support. - -```js - - framework: '@storybook/web-components', - + framework: { - name: '@storybook/web-components-webpack5', - options: { - fastRefresh: true, - builder: { lazyCompilation: true }, - }, - }, - -``` - -`*` Docs is now added to every component on the sidebar with the below code in Storybook 7 - -```js - docs: { - autodocs: true, - defaultName: 'Docs', - }, -``` - -`*` preview.js is exported as default in Storybook 7 - -```js -- export const parameters = { -- actions: { argTypesRegex: '^on[A-Z].*' }, -- }; - -+ export default { -+ parameters: { -+ actions: { argTypesRegex: '^on[A-Z].*' }, -+ }, -+ }; -``` - -## Deprecations(Addons) - ---- - -`*` ```"@storybook/client-api"``` is deprecated - -`*` ```"@storybook/addons"``` is deprecated - -## Bug Fixes - ---- -`*` Fixed various issues related to performance, rendering, and compatibility. - -`*` Resolved problems with the Storybook UI, including layout glitches and navigation bugs. - -`*` Fixed bugs in calender storybook - -## Improvements - ---- -`*` Improved the overall performance and stability of the Storybook development environment. - -`*` Enhanced the documentation with updated examples and guides. - -`*` Optimized the build process for faster bundling and reduced file sizes. - -`*` Upgraded dependencies to their latest versions for improved compatibility and security. - ---- + + diff --git a/.storybook/assets/base.css b/.storybook/assets/base.css index 069c2d9e47b..6a6dfaefaa4 100644 --- a/.storybook/assets/base.css +++ b/.storybook/assets/base.css @@ -1,3 +1,8 @@ +html, +body { + min-block-size: 100%; +} + body { margin: 0; font-size: 10px; @@ -31,7 +36,7 @@ nav .spectrum-Site-logo { .docblock-argstable-body td > span:has(select), .docblock-argstable-body td textarea { - max-width: 280px !important; + max-inline-size: 280px !important; } #storybook-explorer-tree { @@ -51,7 +56,7 @@ button.sidebar-item { font-weight: 400 !important; font-size: 14px !important; line-height: 1.4em !important; - height: 32px !important; + block-size: 32px !important; border-radius: 4px !important; padding-inline-start: 24px !important; padding-inline-end: 12px !important; @@ -122,7 +127,7 @@ select:focus, } [role="main"] > div > div:first-child .os-content > div > div > * { - margin-top: 0 !important; + margin-block-start: 0 !important; } [role="main"] > div > div:first-child .os-content > div > div > div > a { @@ -161,8 +166,8 @@ select:focus, button::after { content: "◢"; position: absolute; - bottom: -3px; - right: -1px; + inset-block-end: -3px; + inset-inline-end: -1px; display: inline-block; transform: scale(0.5); color: rgb(177, 177, 177); @@ -190,7 +195,7 @@ select:focus, > div > div :is(button, a:not(:has(button)), span) { - height: 32px; + block-size: 32px; } [role="main"] @@ -202,3 +207,14 @@ select:focus, :is(button:hover, a:hover:not(:has(button))) { background-color: rgb(230, 230, 230) !important; } + +.docs-story { + background-color: var(--spectrum-background-base-color, var( + --spectrum-alias-background-color-default, + var(--spectrum-global-color-gray-100) + )); +} + +.docs-story #root-inner { + margin: 10px; +} diff --git a/.storybook/decorators/index.js b/.storybook/decorators/index.js index 9a2ffade320..35c7bb363fd 100644 --- a/.storybook/decorators/index.js +++ b/.storybook/decorators/index.js @@ -1,142 +1,5 @@ -import { useEffect, makeDecorator } from "@storybook/preview-api"; -import { html } from "lit"; - -export { withContextWrapper } from "./contextsWrapper.js"; - -/** - * @type import('@storybook/csf').DecoratorFunction - * @description Rendered as controls; these properties are assigned to the document root element - **/ -export const withTextDirectionWrapper = makeDecorator({ - name: "withTextDirectionWrapper", - parameterName: "textDecoration", - wrapper: (StoryFn, context) => { - const { globals, parameters } = context; - const defaultDirection = "ltr" - const textDirection = parameters.textDirection || globals.textDirection || defaultDirection; - - // Shortkeys for the global types - document.addEventListener("keydown", (e) => { - switch (e.key || e.keyCode) { - case "r": - document.documentElement.dir = "rtl"; - break; - case "n": - document.documentElement.dir = defaultDirection; - break; - } - }); - - useEffect(() => { - if (textDirection) document.documentElement.dir = textDirection; - }, [textDirection]); - - return StoryFn(context); - }, -}); - -/** - * @type import('@storybook/csf').DecoratorFunction - **/ -export const withReducedMotionWrapper = makeDecorator({ - name: "withReducedMotionWrapper", - parameterName: "context", - wrapper: (StoryFn, context) => { - const { args } = context; - const reducedMotion = args.reducedMotion; - - return html` - ${reducedMotion - ? html` - - ` - : ""} - ${StoryFn(context)} - `; - }, -}); - -/** - * @type import('@storybook/csf').DecoratorFunction - **/ -export const withLanguageWrapper = makeDecorator({ - name: "withLanguageWrapper", - parameterName: "context", - wrapper: (StoryFn, context) => { - const { globals } = context; - const lang = globals.lang; - - useEffect(() => { - if (lang) document.documentElement.lang = lang; - }, [lang]); - - return StoryFn(context); - }, -}); - -/** - * @type import('@storybook/csf').DecoratorFunction - **/ -export const withSizingWrapper = makeDecorator({ - name: "withSizingWrapper", - parameterName: "context", - wrapper: (StoryFn, context) => { - const { argTypes, parameters } = context; - const sizes = argTypes?.size?.options || []; - const sizeVariants = - typeof parameters?.sizeVariants === "undefined" - ? true - : parameters.sizeVariants; - - /** To suppress the sizing wrapper, add `sizeVariants: false` to the parameters of a story */ - if (sizes.length === 0 || !sizeVariants) return StoryFn(context); - const printSize = (size) => { - if (size === "xs") return "Extra-small"; - if (size === "s") return "Small"; - if (size === "m") return "Medium"; - if (size === "l") return "Large"; - if (size === "xl") return "Extra-large"; - if (size === "xxl") return "Extra-extra-large"; - return size; - }; - - context.parameters.html.root = - '.spectrum-Examples-item[data-value="m"] #scoped-root'; - context.argTypes.size.table = { - ...context.argTypes.size.table, - disable: true, - }; - - return html`
- ${sizes.map((size) => { - context.args.size = size; - return html`
-
- ${StoryFn(context)} -
-

- ${printSize(size)} -

-
`; - })} -
`; - }, -}); +export { withContextWrapper } from "./withContextWrapper.js"; +export { withLanguageWrapper } from "./withLanguageWrapper.js"; +export { withPreviewStyles } from "./withPreviewStyles.js"; +export { withReducedMotionWrapper } from "./withReducedMotionWrapper.js"; +export { withTextDirectionWrapper } from "./withTextDirectionWrapper.js"; diff --git a/.storybook/decorators/contextsWrapper.js b/.storybook/decorators/withContextWrapper.js similarity index 100% rename from .storybook/decorators/contextsWrapper.js rename to .storybook/decorators/withContextWrapper.js diff --git a/.storybook/decorators/withLanguageWrapper.js b/.storybook/decorators/withLanguageWrapper.js new file mode 100644 index 00000000000..110716bcfea --- /dev/null +++ b/.storybook/decorators/withLanguageWrapper.js @@ -0,0 +1,19 @@ +import { makeDecorator, useEffect } from "@storybook/preview-api"; + +/** + * @type import('@storybook/csf').DecoratorFunction + **/ +export const withLanguageWrapper = makeDecorator({ + name: "withLanguageWrapper", + parameterName: "context", + wrapper: (StoryFn, context) => { + const { globals } = context; + const lang = globals.lang; + + useEffect(() => { + if (lang) document.documentElement.lang = lang; + }, [lang]); + + return StoryFn(context); + }, +}); diff --git a/.storybook/decorators/withPreviewStyles.js b/.storybook/decorators/withPreviewStyles.js new file mode 100644 index 00000000000..86544f37b05 --- /dev/null +++ b/.storybook/decorators/withPreviewStyles.js @@ -0,0 +1,68 @@ +import { makeDecorator, useEffect } from "@storybook/preview-api"; + +/** + * @type import('@storybook/csf').DecoratorFunction + **/ +export const withPreviewStyles = makeDecorator({ + name: "withPreviewStyles", + parameterName: "customStyles", + wrapper: (StoryFn, context) => { + const { args } = context; + const staticColor = args.staticColor; + let { + /** @todo: do we really want flex as our default display type? does this make development harder b/c we have to consider how it impacts a component or is it helpful so we can stack components in a view easily? */ + display = "flex", + // Gap is only supported for flex and grid so we don't need to set it for other display types + gap = "10px", + padding = "10px", + position = "relative", + ...customStyles + } = args.customStorybookStyles ?? {}; + + const hasSetting = (setting) => Object.keys(args.customStorybookStyles ?? {}).includes(setting); + + if ( + hasSetting("display") && + ["flex", "grid"].every(d => !display.endsWith(d)) + ) { + gap = undefined; + if (display !== "contents") padding = "10px 0"; + } + + // Always prefer the customStorybookStyles over the default styles + ["display", "gap", "position", "padding"].forEach(setting => { + if (!hasSetting(setting)) return; + customStyles[setting] = args.customStorybookStyles[setting]; + }); + + + const customStorybookStyles = { + display, + gap, + padding, + position, + ...customStyles, + }; + + useEffect(() => { + const root = document.querySelector("#root-inner"); + + // Start with a clean slate + root.removeAttribute("style"); + + Object.entries(customStorybookStyles).forEach(([key, value]) => { + if (value) root.style[key] = value; + }); + + // automatically set the background color for static color settings + if (staticColor) { + document.body.style.backgroundColor = staticColor === "white" ? "rgb(15, 121, 125)" : staticColor === "black" ? "rgb(181, 209, 211)" : undefined; + } else { + document.body.style.backgroundColor = customStorybookStyles.backgroundColor ?? undefined; + } + + }, [customStorybookStyles, staticColor]); + + return StoryFn(context); + } +}); diff --git a/.storybook/decorators/withReducedMotionWrapper.js b/.storybook/decorators/withReducedMotionWrapper.js new file mode 100644 index 00000000000..f564e9e7b13 --- /dev/null +++ b/.storybook/decorators/withReducedMotionWrapper.js @@ -0,0 +1,39 @@ +import { makeDecorator } from "@storybook/preview-api"; + +import { html } from "lit"; +/** + * @type import('@storybook/csf').DecoratorFunction + **/ +export const withReducedMotionWrapper = makeDecorator({ + name: "withReducedMotionWrapper", + parameterName: "context", + wrapper: (StoryFn, context) => { + const { args } = context; + const reducedMotion = args.reducedMotion; + + return html` + ${reducedMotion + ? html` + + ` + : ""} + ${StoryFn(context)} + `; + }, +}); diff --git a/.storybook/decorators/withTextDirectionWrapper.js b/.storybook/decorators/withTextDirectionWrapper.js new file mode 100644 index 00000000000..fd4363a2e48 --- /dev/null +++ b/.storybook/decorators/withTextDirectionWrapper.js @@ -0,0 +1,33 @@ +import { makeDecorator, useEffect } from "@storybook/preview-api"; + +/** + * @type import('@storybook/csf').DecoratorFunction + * @description Rendered as controls; these properties are assigned to the document root element + **/ +export const withTextDirectionWrapper = makeDecorator({ + name: "withTextDirectionWrapper", + parameterName: "textDecoration", + wrapper: (StoryFn, context) => { + const { globals, parameters } = context; + const defaultDirection = "ltr" + const textDirection = parameters.textDirection || globals.textDirection || defaultDirection; + + // Shortkeys for the global types + document.addEventListener("keydown", (e) => { + switch (e.key || e.keyCode) { + case "r": + document.documentElement.dir = "rtl"; + break; + case "n": + document.documentElement.dir = defaultDirection; + break; + } + }); + + useEffect(() => { + if (textDirection) document.documentElement.dir = textDirection; + }, [textDirection]); + + return StoryFn(context); + }, +}); diff --git a/.storybook/main.js b/.storybook/main.js index 97e42365255..9eef9ae0484 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,6 +1,6 @@ -const { resolve } = require("path"); -const { readdirSync } = require("fs"); -const componentsPath = resolve(__dirname, "../components"); +const { join } = require("path"); +const { existsSync, readdirSync } = require("fs"); +const componentsPath = join(__dirname, "../components"); const componentPkgs = readdirSync(componentsPath, { withFileTypes: true, }) @@ -28,13 +28,16 @@ module.exports = { }, // https://github.com/storybookjs/storybook/tree/next/code/addons/a11y "@storybook/addon-a11y", + // https://github.com/storybookjs/storybook/tree/next/code/addons/actions + "@storybook/addon-actions", + // https://github.com/storybookjs/storybook/tree/next/code/addons/interactions + "@storybook/addon-interactions", // https://www.npmjs.com/package/@whitespace/storybook-addon-html "@whitespace/storybook-addon-html", // https://storybook.js.org/addons/@etchteam/storybook-addon-status "@etchteam/storybook-addon-status", + // https://storybook.js.org/addons/storybook-addon-pseudo-states "storybook-addon-pseudo-states", - // https://github.com/storybookjs/storybook/tree/next/code/addons/interactions - "@storybook/addon-interactions", // https://www.chromatic.com/docs/visual-testing-addon/ "@chromaui/addon-visual-tests", ], @@ -43,14 +46,30 @@ module.exports = { }, env: { MIGRATED_PACKAGES: componentPkgs.filter((dir) => { - const pkg = require(resolve(componentsPath, dir, "package.json")); + if (!existsSync(join(componentsPath, dir, "package.json"))) { + return false; + } + + const { + peerDependencies = {}, + devDependencies = {}, + dependencies = {} + } = require(join(componentsPath, dir, "package.json")); + + const allDeps = [...new Set([ + ...Object.keys(dependencies), + ...Object.keys(devDependencies), + ...Object.keys(peerDependencies), + ])]; + if ( - pkg.devDependencies && - pkg.devDependencies["@spectrum-css/component-builder-simple"] + allDeps.length > 0 && + allDeps.includes("@spectrum-css/vars") ) { - return true; + return false; } - return false; + + return true; }), }, webpackFinal: function (config) { @@ -74,13 +93,13 @@ module.exports = { ...(config.resolve ? config.resolve : {}), modules: [ ...(config.resolve ? config.resolve.modules : []), - resolve(__dirname, "../node_modules"), + join(__dirname, "../node_modules"), ], alias: { ...(config.resolve ? config.resolve.alias : {}), ...componentPkgs.reduce((pkgs, dir) => { - const pkg = require(resolve(componentsPath, dir, "package.json")); - pkgs[pkg.name] = resolve(componentsPath, dir); + const pkg = require(join(componentsPath, dir, "package.json")); + pkgs[pkg.name] = join(componentsPath, dir); return pkgs; }, {}), }, @@ -133,8 +152,9 @@ module.exports = { options: { implementation: require("postcss"), postcssOptions: { - config: resolve(__dirname, "postcss.config.js"), + config: join(__dirname, "postcss.config.js"), }, + sourceMap: true, }, }, ], @@ -154,7 +174,6 @@ module.exports = { }, framework: { name: "@storybook/web-components-webpack5", - options: {}, }, features: { /* Code splitting flag; load stories on-demand */ @@ -162,13 +181,6 @@ module.exports = { /* Builds stories.json to help with on-demand loading */ buildStoriesJson: true, }, - // refs: { - // 'swc': { - // title: 'Spectrum Web Components', - // url: 'https://opensource.adobe.com/spectrum-web-components/storybook/', - // expanded: false, - // }, - // }, docs: { autodocs: true, // see below for alternatives defaultName: "Docs", // set to change the name of generated docs entries diff --git a/.storybook/package.json b/.storybook/package.json index 8a71e77e2e8..0ba21df19d6 100644 --- a/.storybook/package.json +++ b/.storybook/package.json @@ -7,7 +7,7 @@ "homepage": "https://opensource.adobe.com/spectrum-css/preview", "main": "main.js", "scripts": { - "build": "storybook build --config-dir . --output-dir ./storybook-static" + "build": "storybook build --config-dir ." }, "dependencies": { "@adobe/spectrum-css-workflow-icons": "^1.5.4", @@ -18,29 +18,28 @@ "@spectrum-css/vars": "^9.0.8" }, "devDependencies": { - "@babel/core": "^7.22.1", + "@babel/core": "^7.23.7", "@chromaui/addon-visual-tests": "^0.0.124", "@etchteam/storybook-addon-status": "^4.2.4", - "@spectrum-css/component-builder": "^4.0.19", - "@storybook/addon-a11y": "^7.5.1", - "@storybook/addon-actions": "^7.5.1", + "@storybook/addon-a11y": "^7.6.7", + "@storybook/addon-actions": "~7.5", "@storybook/addon-console": "^1.2.3", - "@storybook/addon-docs": "^7.5.1", - "@storybook/addon-essentials": "^7.0.20", - "@storybook/addon-interactions": "^7.5.1", - "@storybook/api": "^7.5.1", - "@storybook/blocks": "^7.0.20", - "@storybook/client-api": "^7.5.1", - "@storybook/components": "^7.0.20", - "@storybook/core-events": "^7.0.20", - "@storybook/jest": "^0.2.3", - "@storybook/manager-api": "^7.0.20", - "@storybook/preview-api": "^7.0.20", + "@storybook/addon-essentials": "^7.6.7", + "@storybook/addon-interactions": "^7.6.7", + "@storybook/addons": "^7.6.7", + "@storybook/api": "^7.6.7", + "@storybook/blocks": "^7.6.7", + "@storybook/client-logger": "^7.6.7", + "@storybook/components": "^7.6.7", + "@storybook/core-events": "^7.6.7", + "@storybook/manager-api": "^7.6.7", + "@storybook/preview-api": "^7.6.7", "@storybook/testing-library": "^0.2.2", - "@storybook/theming": "^7.0.20", - "@storybook/web-components-webpack5": "^7.5.1", + "@storybook/theming": "^7.6.7", + "@storybook/types": "^7.6.7", + "@storybook/web-components-webpack5": "^7.6.7", "@whitespace/storybook-addon-html": "^5.1.6", - "chromatic": "^7.0.0", + "chromatic": "^10.2.0", "file-loader": "6.2.0", "lit": "^2.8.0", "lodash-es": "^4.17.21", @@ -56,8 +55,8 @@ "react-dom": "^18.0.0", "react-syntax-highlighter": "^15.5.0", "source-map-loader": "^4.0.1", - "storybook": "^7.5.1", - "storybook-addon-pseudo-states": "^2.1.0", + "storybook": "^7.6.7", + "storybook-addon-pseudo-states": "^2.1.2", "style-loader": "3.3.3", "webpack": "^5.83.1" } diff --git a/.storybook/preview.js b/.storybook/preview.js index d7de377910c..7bbbaa7e44f 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,16 +1,16 @@ -import isChromatic from "chromatic/isChromatic"; - import { withActions } from "@storybook/addon-actions/decorator"; + import DocumentationTemplate from './DocumentationTemplate.mdx'; + import { withContextWrapper, withLanguageWrapper, + withPreviewStyles, withReducedMotionWrapper, withTextDirectionWrapper, } from "./decorators/index.js"; // https://github.com/storybookjs/storybook-addon-console -import "@storybook/addon-console"; import { setConsoleOptions } from "@storybook/addon-console"; const panelExclude = setConsoleOptions({}).panelExclude || []; @@ -40,6 +40,10 @@ import "@spectrum-css/tokens"; import "./global.js"; +// Imports the full raw sets of icons +import "!!raw-loader!@adobe/spectrum-css-workflow-icons/dist/spectrum-icons.svg?raw"; +import "!!raw-loader!@spectrum-css/ui-icons/dist/spectrum-css-icons.svg?raw"; + // Rendered as controls; these properties are assigned // to the document root element // @todo: resolve errors on 'name' and 'title' in console @@ -159,6 +163,12 @@ export const argTypes = { table: { disable: true }, control: "object", }, + customStorybookStyles: { + name: "Custom styles specific to Storybook", + type: { name: "string", required: false }, + table: { disable: true }, + control: "object", + }, id: { name: "Element ID", type: { name: "string", required: false }, @@ -190,14 +200,12 @@ export const parameters = { panelPosition: "bottom", showToolbar: true, isFullscreen: false, - //👇 Defines a list of viewport widths for a single story to be captured in Chromatic. - chromatic: isChromatic() - ? { - // viewports: [320, 1200], - // forcedColors: 'active', - // prefersReducedMotion: 'reduce', - } - : {}, + chromatic: { + delay: 100, + // viewports: [320, 1200], + // forcedColors: 'active', + // prefersReducedMotion: 'reduce', + }, controls: { expanded: true, hideNoControlsWarning: true, @@ -220,7 +228,7 @@ export const parameters = { page: DocumentationTemplate, story: { inline: true, - iframeHeight: "200px", + height: "200px", }, source: { type: "dynamic", @@ -230,21 +238,31 @@ export const parameters = { status: { statuses: { migrated: { - background: "#f0f0f0", - color: "#444", + background: "rgb(0,122,77)", + color: "#fff", description: "Migrated to the latest tokens.", }, + legacy: { + background: "rgb(246,133,17)", + color: "#fff", + description: "Not yet migrated to the latest tokens.", + }, + deprecated: { + background: "rgb(211,21,16)", + color: "#fff", + description: "Should not be used and will not receive updates.", + }, }, }, }; export const decorators = [ + withActions, withTextDirectionWrapper, withLanguageWrapper, withReducedMotionWrapper, withContextWrapper, - withActions, - // ...[isChromatic() ? withSizingWrapper : false].filter(Boolean), + withPreviewStyles, ]; export default { diff --git a/.storybook/project.json b/.storybook/project.json index 1c46a77138f..c22ea306fd2 100644 --- a/.storybook/project.json +++ b/.storybook/project.json @@ -10,7 +10,6 @@ "implicitDependencies": [ "@spectrum-css/*", "!@spectrum-css/generator", - "!@spectrum-css/bundle-builder", "!@spectrum-css/component-builder", "!@spectrum-css/component-builder-simple" ], diff --git a/.vscode/settings.json b/.vscode/settings.json index 632a24480b7..494c76bd271 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,7 +5,7 @@ }, "[javascript]": { "editor.codeActionsOnSave": { - "source.organizeImports": true + "source.organizeImports": "explicit" }, "editor.colorDecorators": true, "editor.defaultFormatter": "dbaeumer.vscode-eslint" diff --git a/components/accordion/metadata/mods.md b/components/accordion/metadata/mods.md index 18ce230e5b1..412286413ea 100644 --- a/components/accordion/metadata/mods.md +++ b/components/accordion/metadata/mods.md @@ -1,4 +1,4 @@ -| Modifiable Custom Properties | +| Modifiable custom properties | | ----------------------------------------------------- | | `--mod-accordion-background-color-default` | | `--mod-accordion-background-color-down` | diff --git a/components/accordion/stories/accordion.stories.js b/components/accordion/stories/accordion.stories.js index cb1473ad5aa..8b1eec8d04c 100644 --- a/components/accordion/stories/accordion.stories.js +++ b/components/accordion/stories/accordion.stories.js @@ -1,7 +1,6 @@ -// Import the component markup template -import { Template } from "./template"; -import { html } from "lit"; import isChromatic from "chromatic/isChromatic"; +import { html } from "lit"; +import { Template } from "./template"; export default { title: "Components/Accordion", @@ -9,6 +8,8 @@ export default { "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.", component: "Accordion", argTypes: { + /* No theme styles for express available */ + express: { table: { disable: true } }, items: { table: { disable: true } }, size: { name: "Size", @@ -44,6 +45,44 @@ export default { rootClass: "spectrum-Accordion", size: "m", density: "regular", + items: new Map([ + [ + "Recent", + { + content: "Item 1", + isOpen: true, + isDisabled: false, + }, + ], + [ + "Architecture", + { + content: "Item 2", + isOpen: false, + isDisabled: true, + }, + ], + [ + "Nature", + { + content: "Item 3", + isOpen: false, + isDisabled: false, + }, + ], + [ + "Really long accordion item that should wrap", + { + content: "Really long content that should wrap when component has a max or fixed width", + isOpen: true, + isDisabled: false, + }, + ], + ]), + customStorybookStyles: { + padding: undefined, + gap: undefined, + }, }, parameters: { actions: { @@ -52,95 +91,20 @@ export default { status: { type: process.env.MIGRATED_PACKAGES.includes("accordion") ? "migrated" - : undefined, + : "legacy", }, }, }; -const AccordianGroup = ({ - customStyles = {}, - ...args -}) => { - return html` -
- ${Template({ - items: new Map([ - [ - "Recent", - { - content: "Item 1", - isOpen: true, - isDisabled: false, - }, - ], - [ - "Architecture", - { - content: "Item 2", - isOpen: false, - isDisabled: true, - }, - ], - [ - "Nature", - { - content: "Item 3", - isOpen: false, - isDisabled: false, - }, - ], - [ - "Really Long Accordion Item that should wrap", - { - content: "Really long content that should wrap when component has a max or fixed width", - isOpen: true, - isDisabled: false, - }, - ], - ]), - })} - ${isChromatic() ? - Template({ - customStyles: { "max-inline-size": "300px"}, - items: new Map([ - [ - "Recent", - { - content: "Item 1", - isOpen: true, - isDisabled: false, - }, - ], - [ - "Architecture", - { - content: "Item 2", - isOpen: false, - isDisabled: true, - }, - ], - [ - "Nature", - { - content: "Item 3", - isOpen: false, - isDisabled: false, - }, - ], - [ - "Really Long Accordion Item that should wrap", - { - content: "Really long content that should wrap when component has a max or fixed width", - isOpen: true, - isDisabled: false, - }, - ], - ]), - }) - : null } -
- `; -}; +const AccordionGroup = (args) => html` + ${Template(args)} + ${isChromatic() ? Template({ + ...args, + customStyles: { + ...args.customStyles ?? {}, + maxInlineSize: "300px" + }, + }) : "" }`; -export const Default = AccordianGroup.bind({}); +export const Default = AccordionGroup.bind({}); Default.args = {}; diff --git a/components/accordion/stories/template.js b/components/accordion/stories/template.js index 7fc5afb387b..676938d2e1b 100644 --- a/components/accordion/stories/template.js +++ b/components/accordion/stories/template.js @@ -1,8 +1,10 @@ import { html } from "lit"; import { classMap } from "lit/directives/class-map.js"; -import { styleMap } from "lit/directives/style-map.js"; -import { repeat } from "lit/directives/repeat.js"; import { ifDefined } from "lit/directives/if-defined.js"; +import { repeat } from "lit/directives/repeat.js"; +import { styleMap } from "lit/directives/style-map.js"; + +import { useArgs } from "@storybook/client-api"; import { Template as Icon } from "@spectrum-css/icon/stories/template.js"; @@ -20,6 +22,7 @@ export const AccordionItem = ({ disableAll = false, customStyles = {}, // customClasses = [], + onclick, ...globals }) => { return html` @@ -32,12 +35,7 @@ export const AccordionItem = ({ id=${ifDefined(id)} style=${ifDefined(styleMap(customStyles))} role="presentation" - @click=${(evt) => { - if (isDisabled || !evt || !evt.target) return; - const closest = evt.target.closest(`.${rootClass}`); - if (!closest) return; - closest.classList.toggle("is-open"); - }} + @click=${onclick} >

@@ -54,7 +52,7 @@ export const AccordionItem = ({ ${Icon({ - iconName: "ChevronRight", + uiIconName: !isOpen ? "ChevronRight" : "ChevronDown", size: iconSize, customClasses: [`${rootClass}Indicator`], ...globals, @@ -81,8 +79,11 @@ export const Template = ({ items, id, customClasses = [], + customStyles = {}, ...globals }) => { + const [_, updateArgs] = useArgs(); + if (!items || !items.size) return html``; return html` @@ -97,16 +98,26 @@ export const Template = ({ })}" id=${ifDefined(id)} role="region" + style=${ifDefined(styleMap(customStyles))} > ${repeat(Array.from(items.keys()), (heading, idx) => { const item = items.get(heading); return AccordionItem({ + ...globals, rootClass: `${rootClass}-item`, heading, idx, iconSize: `${size}`, ...item, - ...globals, + onclick: () => { + // Update the args + const newItems = new Map(items); + newItems.set(heading, { + ...item, + isOpen: !item.isOpen, + }); + updateArgs({ items: newItems }); + }, }); })} diff --git a/components/accordion/themes/express.css b/components/accordion/themes/express.css deleted file mode 100644 index 1140b43629c..00000000000 --- a/components/accordion/themes/express.css +++ /dev/null @@ -1,16 +0,0 @@ -/* -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -@container (--system: express) { - .spectrum-Accordion { - } -} diff --git a/components/accordion/themes/spectrum.css b/components/accordion/themes/spectrum.css deleted file mode 100644 index 5f16da776e0..00000000000 --- a/components/accordion/themes/spectrum.css +++ /dev/null @@ -1,16 +0,0 @@ -/* -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -@container (--system: spectrum) { - .spectrum-Accordion { - } -} diff --git a/components/actionbar/metadata/mods.md b/components/actionbar/metadata/mods.md index eee556c11ae..c66fd46ead9 100644 --- a/components/actionbar/metadata/mods.md +++ b/components/actionbar/metadata/mods.md @@ -1,4 +1,4 @@ -| Modifiable Custom Properties | +| Modifiable custom properties | | ----------------------------------------------- | | `--mod-actionbar-corner-radius` | | `--mod-actionbar-emphasized-background-color` | diff --git a/components/actionbar/stories/actionbar.stories.js b/components/actionbar/stories/actionbar.stories.js index 2edd0cda045..3910b65e8b9 100644 --- a/components/actionbar/stories/actionbar.stories.js +++ b/components/actionbar/stories/actionbar.stories.js @@ -1,15 +1,16 @@ -// Import the component markup template import { Template } from "./template"; -import { default as Popover } from "@spectrum-css/popover/stories/popover.stories.js"; -import { default as CloseButton } from "@spectrum-css/closebutton/stories/closebutton.stories.js"; import { default as ActionButton } from "@spectrum-css/actionbutton/stories/actionbutton.stories.js"; +import { default as CloseButton } from "@spectrum-css/closebutton/stories/closebutton.stories.js"; +import { default as Popover } from "@spectrum-css/popover/stories/popover.stories.js"; export default { title: "Components/Action bar", description: "The Action bar component is a floating full width bar that appears upon selection", - component: "Actionbar", + component: "ActionBar", argTypes: { + /* No theme styles for express available */ + express: { table: { disable: true } }, isOpen: { name: "Open", type: { name: "boolean" }, @@ -63,6 +64,9 @@ export default { isSticky: false, isFixed: false, isFlexible: false, + customStorybookStyles: { + display: "block", + } }, parameters: { actions: { @@ -75,7 +79,7 @@ export default { status: { type: process.env.MIGRATED_PACKAGES.includes("actionbar") ? "migrated" - : undefined, + : "legacy", }, }, }; diff --git a/components/actionbar/stories/template.js b/components/actionbar/stories/template.js index 081ac60fda0..ea1eda15449 100644 --- a/components/actionbar/stories/template.js +++ b/components/actionbar/stories/template.js @@ -18,67 +18,56 @@ export const Template = ({ isFlexible = false, customClasses = [], ...globals -}) => { - const { express } = globals; - - try { - if (!express) import(/* webpackPrefetch: true */ "../themes/spectrum.css"); - else import(/* webpackPrefetch: true */ "../themes/express.css"); - } catch (e) { - console.warn(e); - } - - return html` -
({ ...a, [c]: true }), {}), - })} - > - ${Popover({ - ...globals, - customClasses: [`${rootClass}-popover`], - isOpen, - content: [ - CloseButton({ - ...globals, - label: "Clear selection", - staticColor: isEmphasized ? "white" : undefined, - }), - FieldLabel({ - ...globals, - size: "s", - label: "2 Selected", - }), - ActionGroup({ - ...globals, - size: "m", - areQuiet: true, - staticColors: isEmphasized ? "white" : undefined, - content: [ - { - iconName: "Edit", - label: "Edit", - }, - { - iconName: "Copy", - label: "Copy", - }, - { - iconName: "Delete", - label: "Delete", - }, - ], - }), - ], - })} -
- `; -}; +}) => html` +
({ ...a, [c]: true }), {}), + })} + > + ${Popover({ + ...globals, + customClasses: [`${rootClass}-popover`], + isOpen, + content: [ + CloseButton({ + ...globals, + label: "Clear selection", + staticColor: isEmphasized ? "white" : undefined, + }), + FieldLabel({ + ...globals, + size: "s", + label: "2 Selected", + }), + ActionGroup({ + ...globals, + size: "m", + areQuiet: true, + staticColors: isEmphasized ? "white" : undefined, + content: [ + { + iconName: "Edit", + label: "Edit", + }, + { + iconName: "Copy", + label: "Copy", + }, + { + iconName: "Delete", + label: "Delete", + }, + ], + }), + ], + })} +
+`; diff --git a/components/actionbar/themes/express.css b/components/actionbar/themes/express.css deleted file mode 100644 index 0d46a651874..00000000000 --- a/components/actionbar/themes/express.css +++ /dev/null @@ -1,15 +0,0 @@ -/*! -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -@container (--system: express) { - -} diff --git a/components/actionbar/themes/spectrum.css b/components/actionbar/themes/spectrum.css deleted file mode 100644 index 17611eaa41f..00000000000 --- a/components/actionbar/themes/spectrum.css +++ /dev/null @@ -1,15 +0,0 @@ -/*! -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -@container (--system: spectrum) { - -} diff --git a/components/actionbutton/index.css b/components/actionbutton/index.css index 86e5b280246..37bd575e628 100644 --- a/components/actionbutton/index.css +++ b/components/actionbutton/index.css @@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -@import "../commons/basebutton-coretokens.css"; +@import "@spectrum-css/commons/basebutton-coretokens.css"; .spectrum-ActionButton { --spectrum-actionbutton-animation-duration: var(--spectrum-animation-duration-100); @@ -26,13 +26,13 @@ governing permissions and limitations under the License. --spectrum-actionbutton-focus-indicator-thickness: var(--spectrum-focus-indicator-thickness); --spectrum-actionbutton-focus-indicator-color: var(--spectrum-focus-indicator-color); --spectrum-actionbutton-focus-indicator-border-radius: calc(var(--spectrum-actionbutton-border-radius) + var(--spectrum-actionbutton-focus-indicator-gap)); - + &.is-selected { --mod-actionbutton-background-color-default: var(--mod-actionbutton-background-color-default-selected, var(--spectrum-neutral-background-color-selected-default)); --mod-actionbutton-background-color-hover: var(--mod-actionbutton-background-color-hover-selected, var(--spectrum-neutral-background-color-selected-hover)); --mod-actionbutton-background-color-down: var(--mod-actionbutton-background-color-down-selected, var(--spectrum-neutral-background-color-selected-down)); --mod-actionbutton-background-color-focus: var(--mod-actionbutton-background-color-focus-selected, var(--spectrum-neutral-background-color-selected-key-focus)); - + --mod-actionbutton-content-color-default: var(--mod-actionbutton-content-color-default-selected, var(--spectrum-gray-50)); --mod-actionbutton-content-color-hover: var(--mod-actionbutton-content-color-hover-selected, var(--spectrum-gray-50)); --mod-actionbutton-content-color-down: var(--mod-actionbutton-content-color-down-selected, var(--spectrum-gray-50)); @@ -43,7 +43,7 @@ governing permissions and limitations under the License. --mod-actionbutton-background-color-hover: var(--mod-actionbutton-background-color-hover-selected-emphasized, var(--spectrum-accent-background-color-hover)); --mod-actionbutton-background-color-down: var(--mod-actionbutton-background-color-down-selected-emphasized, var(--spectrum-accent-background-color-down)); --mod-actionbutton-background-color-focus: var(--mod-actionbutton-background-color-focus-selected-emphasized, var(--spectrum-accent-background-color-key-focus)); - + --mod-actionbutton-content-color-default: var(--mod-actionbutton-content-color-default-selected-emphasized, var(--spectrum-white)); --mod-actionbutton-content-color-hover: var(--mod-actionbutton-content-color-hover-selected-emphasized, var(--spectrum-white)); --mod-actionbutton-content-color-down: var(--mod-actionbutton-content-color-down-selected-emphasized, var(--spectrum-white)); @@ -159,7 +159,6 @@ governing permissions and limitations under the License. .spectrum-ActionButton { @inherit: %spectrum-BaseButton; - position: relative; min-inline-size: var(--mod-actionbutton-min-width, var(--spectrum-actionbutton-min-width)); block-size: var(--mod-actionbutton-height, var(--spectrum-actionbutton-height)); @@ -258,20 +257,19 @@ a.spectrum-ActionButton { /* special cases for focus-ring */ .spectrum-ActionButton { + @inherit: %spectrum-ButtonWithFocusRing; transition: border-color var(--mod-actionbutton-animation-duration, var(--spectrum-actionbutton-animation-duration)) ease-in-out; &::after { - position: absolute; - inset: 0; - margin: calc((var(--mod-actionbutton-focus-indicator-gap, var(--spectrum-actionbutton-focus-indicator-gap)) + var(--mod-actionbutton-border-width, var(--spectrum-actionbutton-border-width))) * -1); border-radius: var(--mod-actionbutton-focus-indicator-border-radius, var(--spectrum-actionbutton-focus-indicator-border-radius)); - transition: box-shadow var(--mod-actionbutton-animation-duration, var(--spectrum-actionbutton-animation-duration)) ease-in-out; + transition: opacity var(--mod-animation-duration-100, var(--spectrum-animation-duration-100)) ease-out, + margin var(--mod-animation-duration-100, var(--spectrum-animation-duration-100)) ease-out, + box-shadow var(--mod-actionbutton-animation-duration, var(--spectrum-actionbutton-animation-duration)) ease-in-out; pointer-events: none; - content: ''; } &:focus-visible { diff --git a/components/actionbutton/metadata/mods.md b/components/actionbutton/metadata/mods.md index 2d0ca509bf2..974f9f27c1b 100644 --- a/components/actionbutton/metadata/mods.md +++ b/components/actionbutton/metadata/mods.md @@ -1,4 +1,4 @@ -| Modifiable Custom Properties | +| Modifiable custom properties | | ----------------------------------------------------------------- | | `--mod-actionbutton-animation-duration` | | `--mod-actionbutton-background-color-default` | @@ -50,5 +50,6 @@ | `--mod-actionbutton-static-content-color` | | `--mod-actionbutton-text-to-visual` | | `--mod-animation-duration-100` | +| `--mod-focus-indicator-gap` | | `--mod-line-height-100` | | `--mod-sans-font-family-stack` | diff --git a/components/actionbutton/stories/actionbutton-quiet.stories.js b/components/actionbutton/stories/actionbutton-quiet.stories.js index 15a55671983..3a91366ec67 100644 --- a/components/actionbutton/stories/actionbutton-quiet.stories.js +++ b/components/actionbutton/stories/actionbutton-quiet.stories.js @@ -1,4 +1,4 @@ -import { argTypes, ActionButtons } from "./index"; +import { ActionButtons, argTypes } from "./index"; export default { title: "Components/Action button/Quiet", @@ -21,7 +21,7 @@ export default { status: { type: process.env.MIGRATED_PACKAGES.includes("actionbutton") ? "migrated" - : undefined, + : "legacy", }, }, }; diff --git a/components/actionbutton/stories/actionbutton-staticblack.stories.js b/components/actionbutton/stories/actionbutton-staticblack.stories.js index d047ed2bacc..4bffaf08bef 100644 --- a/components/actionbutton/stories/actionbutton-staticblack.stories.js +++ b/components/actionbutton/stories/actionbutton-staticblack.stories.js @@ -22,7 +22,7 @@ export default { status: { type: process.env.MIGRATED_PACKAGES.includes("actionbutton") ? "migrated" - : undefined, + : "legacy", }, }, }; diff --git a/components/actionbutton/stories/actionbutton-staticwhite.stories.js b/components/actionbutton/stories/actionbutton-staticwhite.stories.js index 0a05cb747e6..700910f2417 100644 --- a/components/actionbutton/stories/actionbutton-staticwhite.stories.js +++ b/components/actionbutton/stories/actionbutton-staticwhite.stories.js @@ -22,7 +22,7 @@ export default { status: { type: process.env.MIGRATED_PACKAGES.includes("actionbutton") ? "migrated" - : undefined, + : "legacy", }, }, }; diff --git a/components/actionbutton/stories/actionbutton.stories.js b/components/actionbutton/stories/actionbutton.stories.js index 65c48394201..2eef494765f 100644 --- a/components/actionbutton/stories/actionbutton.stories.js +++ b/components/actionbutton/stories/actionbutton.stories.js @@ -1,4 +1,4 @@ -import { argTypes, ActionButtons } from "./index"; +import { ActionButtons, argTypes } from "./index"; export default { title: "Components/Action button", @@ -21,7 +21,7 @@ export default { status: { type: process.env.MIGRATED_PACKAGES.includes("actionbutton") ? "migrated" - : undefined, + : "legacy", }, }, }; @@ -45,6 +45,11 @@ SelectedDisabled.args = { isDisabled: true }; +export const Express = ActionButtons.bind({}); +Express.args = { + express: true +}; + export const Emphasized = ActionButtons.bind({}); Emphasized.args = { isEmphasized: true diff --git a/components/actionbutton/stories/index.js b/components/actionbutton/stories/index.js index 7bb13a29493..3020663fc94 100644 --- a/components/actionbutton/stories/index.js +++ b/components/actionbutton/stories/index.js @@ -1,6 +1,4 @@ import { html } from "lit"; -import { ifDefined } from "lit/directives/if-defined.js"; -import { styleMap } from "lit/directives/style-map.js"; import { Template } from "./template"; @@ -97,43 +95,23 @@ export const argTypes = { }, }; -export const ActionButtons = ({ - staticColor, - ...args -}) => { - return html` -
- ${Template({ - ...args, - staticColor, - label: "More", - iconName: undefined, - })} - ${Template({ - ...args, - staticColor, - label: "More", - })} - ${Template({ - ...args, - staticColor, - })} - ${Template({ - ...args, - staticColor, - hasPopup: true, - })} - ${Template({ - ...args, - staticColor, - label: "More and this text should truncate", - customStyles: { "max-inline-size": "100px"}, - })} -
- `; -}; +export const ActionButtons = (args) => html` + ${Template({ + ...args, + label: "More", + iconName: undefined, + })} + ${Template({ + ...args, + label: "More", + })} + ${Template(args)} + ${Template({ + ...args, + hasPopup: true, + })} + ${Template({ + ...args, + label: "More and this text should truncate", + customStyles: { maxInlineSize: "100px" }, + })}`; diff --git a/components/actionbutton/stories/template.js b/components/actionbutton/stories/template.js index ed7d08c43b2..f1134c6e1b7 100644 --- a/components/actionbutton/stories/template.js +++ b/components/actionbutton/stories/template.js @@ -69,7 +69,7 @@ export const Template = ({ Icon({ ...globals, size, - iconName: "CornerTriangle100", + uiIconName: "CornerTriangle", customClasses: [`${rootClass}-hold`], }) )} diff --git a/components/actiongroup/metadata/mods.md b/components/actiongroup/metadata/mods.md index 5a103defdb1..2fcc384c89f 100644 --- a/components/actiongroup/metadata/mods.md +++ b/components/actiongroup/metadata/mods.md @@ -1,4 +1,4 @@ -| Modifiable Custom Properties | +| Modifiable custom properties | | ---------------------------------------------- | | `--mod-actiongroup-border-radius` | | `--mod-actiongroup-border-radius-reset` | diff --git a/components/actiongroup/stories/actiongroup.stories.js b/components/actiongroup/stories/actiongroup.stories.js index d967fb38bf2..6ba55c669c2 100644 --- a/components/actiongroup/stories/actiongroup.stories.js +++ b/components/actiongroup/stories/actiongroup.stories.js @@ -1,4 +1,3 @@ -// Import the component markup template import { Template } from "./template"; import { default as ActionButton } from "@spectrum-css/actionbutton/stories/actionbutton.stories.js"; @@ -59,6 +58,21 @@ export default { vertical: false, compact: false, justified: false, + content: [ + { + iconName: "Edit", + label: "Edit", + }, + { + iconName: "Copy", + label: "Copy", + }, + { + iconName: "Delete", + label: "Delete", + isSelected: true, + }, + ], }, parameters: { actions: { @@ -67,60 +81,44 @@ export default { status: { type: process.env.MIGRATED_PACKAGES.includes("actiongroup") ? "migrated" - : undefined, + : "legacy", }, }, }; -const items = [ - { - iconName: "Edit", - label: "Edit", - }, - { - iconName: "Copy", - label: "Copy", - }, - { - iconName: "Delete", - label: "Delete", - isSelected: true, - }, -]; - export const Default = Template.bind({}); -Default.args = { - content: items -}; - +Default.args = {}; export const Compact = Template.bind({}); Compact.args = { compact: true, - content: items }; export const Vertical = Template.bind({}); Vertical.args = { vertical: true, - content: items }; export const VerticalCompact = Template.bind({}); VerticalCompact.args = { vertical: true, compact: true, - content: items }; export const Justified = Template.bind({}); Justified.args = { justified: true, - content: items + customStorybookStyles: { + display: "block" + } }; export const Quiet = Template.bind({}); Quiet.args = { areQuiet: true, - content: items +}; + +export const Express = Template.bind({}); +Express.args = { + express: true }; diff --git a/components/actionmenu/stories/actionmenu.stories.js b/components/actionmenu/stories/actionmenu.stories.js index 1ef2b13cf23..327fe3dee03 100644 --- a/components/actionmenu/stories/actionmenu.stories.js +++ b/components/actionmenu/stories/actionmenu.stories.js @@ -1,20 +1,21 @@ -import { within, userEvent } from '@storybook/testing-library'; -import { html } from "lit"; +import { userEvent, within } from '@storybook/testing-library'; -// Import the component markup template import { Template } from "./template"; import { default as ActionButton } from "@spectrum-css/actionbutton/stories/actionbutton.stories.js"; +import { default as IconStories } from "@spectrum-css/icon/stories/icon.stories.js"; 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 { default as IconStories } from "@spectrum-css/icon/stories/icon.stories.js"; export default { title: "Components/Action menu", description: "The Action menu component is an action button with a Popover.", - component: "Action menu", + component: "ActionMenu", argTypes: { + /* No theme styles for express available */ + express: { table: { disable: true } }, items: { table: { disable: true } }, + popoverPosition: { table: { disable: true } }, isOpen: { name: "Open", type: { name: "boolean" }, @@ -39,7 +40,27 @@ export default { }, }, args: { - isOpen: true, + isOpen: false, + label: "More actions", + iconName: "More", + items: [ + { + label: "Action 1", + }, + { + label: "Action 2", + }, + { + label: "Action 3", + }, + { + label: "Action 4", + }, + ], + customStorybookStyles: { + display: "block", + position: "relative" + } }, parameters: { actions: { @@ -52,38 +73,16 @@ export default { status: { type: process.env.MIGRATED_PACKAGES.includes("actionmenu") ? "migrated" - : undefined, + : "legacy", }, chromatic: { delay: 2000 }, }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await new Promise((resolve) => setTimeout(resolve, 100)); + await userEvent.click(canvas.getByRole('button', { id: 'trigger' })); + }, }; export const Default = Template.bind({}); -Default.play = async ({ canvasElement }) => { - const canvas = within(canvasElement); - - await new Promise((resolve) => setTimeout(resolve, 100)); - - await userEvent.click(canvas.getByRole('button', { id: 'trigger' })); -}; -// provide padding so that Chromatic can capture the full focus indicator -Default.decorators = [(Story) => html`
${Story().outerHTML || Story()}
`]; -Default.args = { - isOpen: false, - label: "More Actions", - iconName: "More", - items: [ - { - label: "Action 1", - }, - { - label: "Action 2", - }, - { - label: "Action 3", - }, - { - label: "Action 4", - }, - ], -}; +Default.args = {}; diff --git a/components/actionmenu/stories/template.js b/components/actionmenu/stories/template.js index 5a59bbe8a03..898273e6218 100644 --- a/components/actionmenu/stories/template.js +++ b/components/actionmenu/stories/template.js @@ -11,6 +11,7 @@ export const Template = ({ label, iconName, size = "m", + popoverPosition = "bottom", ...globals }) => { @@ -21,7 +22,7 @@ export const Template = ({ return Popover({ ...globals, - position: "bottom", + position: popoverPosition, isOpen, id: "popover-1", testId: "popover-1", diff --git a/components/actionmenu/themes/express.css b/components/actionmenu/themes/express.css deleted file mode 100644 index 78921ae6a63..00000000000 --- a/components/actionmenu/themes/express.css +++ /dev/null @@ -1,12 +0,0 @@ -/*! -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -@container (--system: express) {} diff --git a/components/actionmenu/themes/spectrum.css b/components/actionmenu/themes/spectrum.css deleted file mode 100644 index 88cfca9b111..00000000000 --- a/components/actionmenu/themes/spectrum.css +++ /dev/null @@ -1,12 +0,0 @@ -/*! -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -@container (--system: spectrum) {} diff --git a/components/alertbanner/metadata/mods.md b/components/alertbanner/metadata/mods.md index 42743b5d456..0bd1ac33acb 100644 --- a/components/alertbanner/metadata/mods.md +++ b/components/alertbanner/metadata/mods.md @@ -1,4 +1,4 @@ -| Modifiable Custom Properties | +| Modifiable custom properties | | ---------------------------------------------- | | `--mod-alert-banner-bottom-text` | | `--mod-alert-banner-close-button-spacing` | diff --git a/components/alertbanner/stories/alertbanner.stories.js b/components/alertbanner/stories/alertbanner.stories.js index 71d6cf00e2e..e02eaef15d9 100644 --- a/components/alertbanner/stories/alertbanner.stories.js +++ b/components/alertbanner/stories/alertbanner.stories.js @@ -1,6 +1,8 @@ -import { Template } from "./template"; -import { html } from "lit"; import isChromatic from "chromatic/isChromatic"; +import { html } from "lit"; +import { when } from "lit/directives/when.js"; + +import { Template } from "./template"; export default { title: "Components/Alert banner", @@ -53,6 +55,9 @@ export default { variant: "neutral", hasActionButton: true, text: "Your trial has expired", + customStorybookStyles: { + flexDirection: "column", + } }, parameters: { actions: { @@ -61,38 +66,33 @@ export default { status: { type: process.env.MIGRATED_PACKAGES.includes("alertbanner") ? "migrated" - : undefined, + : "legacy", }, }, }; -const AlertBannerGroup = ({ - ...args - }) => { - return html` -
- ${Template({ - ...args, - })} - ${isChromatic() ? - Template({ - ...args, - hasActionButton: true, - variant: "info", - text: "Your trial will expire in 3 days. Once it expires your files will be saved and ready for you to open again once you have purcahsed the software." - }): null } - ${isChromatic() ? - Template({ - ...args, - hasActionButton: true, - variant: "negative", - text: "Connection interupted. Check your network to continue." - }) - : null } -
- `; -}; +const AlertBannerGroup = (args) => html` + ${Template(args)} + ${when(isChromatic(), () => html` + ${Template({ + ...args, + hasActionButton: true, + variant: "info", + text: "Your trial will expire in 3 days. Once it expires your files will be saved and ready for you to open again once you have purcahsed the software." + })} + ${Template({ + ...args, + hasActionButton: true, + variant: "negative", + text: "Connection interupted. Check your network to continue." + })} + `)} +`; export const Default = AlertBannerGroup.bind({}); -Default.args = { +Default.args = {}; + +export const Express = AlertBannerGroup.bind({}); +Express.args = { + express: true }; diff --git a/components/alertdialog/metadata/mods.md b/components/alertdialog/metadata/mods.md index 14400a302c1..e80747e43af 100644 --- a/components/alertdialog/metadata/mods.md +++ b/components/alertdialog/metadata/mods.md @@ -1,4 +1,4 @@ -| Modifiable Custom Properties | +| Modifiable custom properties | | ------------------------------------------- | | `--mod-alert-dialog-body-color` | | `--mod-alert-dialog-body-font-family` | diff --git a/components/alertdialog/stories/alertdialog.stories.js b/components/alertdialog/stories/alertdialog.stories.js index af26b301dea..0b207e13ccb 100644 --- a/components/alertdialog/stories/alertdialog.stories.js +++ b/components/alertdialog/stories/alertdialog.stories.js @@ -6,6 +6,9 @@ export default { "Alert dialogs display important information that users need to acknowledge. They appear over the interface and block further interactions until an action is selected.", component: "AlertDialog", argTypes: { + /* No theme styles for express available */ + express: { table: { disable: true } }, + buttons: { table: { disable: true } }, heading: { name: "Heading", type: { name: "string" }, @@ -38,35 +41,35 @@ export default { args: { rootClass: "spectrum-AlertDialog", isOpen: true, + variant: 'confirmation', + heading: "Enable Smart Filters?", + buttons: [{ + variant: "secondary", + treatment: "outline", + label: "Remind me later" + }, { + variant: "primary", + treatment: "fill", + label: "Enable", + variant: "accent" + }], + content: 'Smart filters are nondestructive and will preserve your original images.', }, parameters: { + layout: 'centered', actions: { handles: ["click .spectrum-AlertDialog button"], }, status: { type: process.env.MIGRATED_PACKAGES.includes("alertdialog") ? "migrated" - : undefined, + : "legacy", }, }, }; export const Default = Template.bind({}); -Default.args = { - variant: 'confirmation', - heading: "Enable Smart Filters?", - buttons: [{ - variant: "secondary", - treatment: "outline", - label: "Remind me later" - }, { - variant: "primary", - treatment: "fill", - label: "Enable", - variant: "accent" - }], - content: 'Smart filters are nondestructive and will preserve your original images.', -}; +Default.args = {}; export const Information = Template.bind({}); Information.args = { diff --git a/components/alertdialog/stories/template.js b/components/alertdialog/stories/template.js index cd0236c971a..1d682eb6b71 100644 --- a/components/alertdialog/stories/template.js +++ b/components/alertdialog/stories/template.js @@ -29,7 +29,7 @@ export const Template = ({ }) => { const [_, updateArgs] = useArgs(); - const Dialog = html` + const Dialog = () => html`

${heading}

${when(icon, () => Icon({ + ...globals, size: 'm', iconName: "Alert", customClasses: [`${rootClass}-icon`], - ...globals, - })) } + }))}
${Divider({ + ...globals, horizontal: true, customClasses: [`${rootClass}-divider`], - ...globals, })}
${content}
${ButtonGroup({ + ...globals, items: buttons, onclick: () => { updateArgs({ isOpen: !isOpen }); @@ -69,24 +70,21 @@ export const Template = ({ `; - return html` + return html` ${Underlay({ ...globals, isOpen, + onclick: () => { + if (isOpen) updateArgs({ isOpen: false }); + }, })} ${Button({ ...globals, size: "m", variant: "secondary", - label: "Click to open Alert Dialog", + label: "Click to open", treatment: "outline", customClasses: [], - customStyles: { - position: "absolute", - insetInlineStart: "50%", - insetBlockStart: "50%", - transform: "translate(-50%, -50%)", - }, onclick: () => { updateArgs({ isOpen: !isOpen }); }, @@ -94,7 +92,7 @@ export const Template = ({ ${Modal({ ...globals, isOpen, - content: Dialog, + content: [Dialog()], })} ` } diff --git a/components/alertdialog/themes/express.css b/components/alertdialog/themes/express.css deleted file mode 100644 index 2899a53a733..00000000000 --- a/components/alertdialog/themes/express.css +++ /dev/null @@ -1,13 +0,0 @@ -/*! -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -@container (--system: express) {} diff --git a/components/alertdialog/themes/spectrum.css b/components/alertdialog/themes/spectrum.css deleted file mode 100644 index d963d64ba60..00000000000 --- a/components/alertdialog/themes/spectrum.css +++ /dev/null @@ -1,13 +0,0 @@ -/*! -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -@container (--system: spectrum) {} diff --git a/components/asset/index.css b/components/asset/index.css index e9b7c701854..8a4b813e153 100644 --- a/components/asset/index.css +++ b/components/asset/index.css @@ -33,3 +33,23 @@ governing permissions and limitations under the License. max-inline-size: var(--spectrum-asset-icon-max-width); margin: var(--spectrum-asset-icon-margin); } + +.spectrum-Asset-folderBackground { + fill: var(--highcontrast-asset-folder-background-color, var(--spectrum-asset-folder-background-color)); +} + +.spectrum-Asset-fileBackground { + fill: var(--highcontrast-asset-file-background-color, var(--spectrum-asset-file-background-color)); +} + +.spectrum-Asset-folderOutline, +.spectrum-Asset-fileOutline { + fill: var(--spectrum-asset-icon-outline-color); +} + +@media (forced-colors: active) { + .spectrum-Asset { + --highcontrast-asset-folder-background-color: currentColor; + --highcontrast-asset-file-background-color: currentColor; + } +} diff --git a/components/asset/skin.css b/components/asset/skin.css deleted file mode 100644 index d4c4ca95929..00000000000 --- a/components/asset/skin.css +++ /dev/null @@ -1,31 +0,0 @@ -/*! -Copyright 2023 Adobe. All rights reserved. -This file is licensed to you under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. You may obtain a copy -of the License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under -the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -OF ANY KIND, either express or implied. See the License for the specific language -governing permissions and limitations under the License. -*/ - -.spectrum-Asset-folderBackground { - fill: var(--highcontrast-asset-folder-background-color, var(--spectrum-asset-folder-background-color)); -} - -.spectrum-Asset-fileBackground { - fill: var(--highcontrast-asset-file-background-color, var(--spectrum-asset-file-background-color)); -} - -.spectrum-Asset-folderOutline, -.spectrum-Asset-fileOutline { - fill: var(--spectrum-asset-icon-outline-color); -} - -@media (forced-colors: active) { - .spectrum-Asset { - --highcontrast-asset-folder-background-color: currentColor; - --highcontrast-asset-file-background-color: currentColor; - } -} diff --git a/components/asset/stories/asset.stories.js b/components/asset/stories/asset.stories.js index 6187bdb79e8..12ba94581fc 100644 --- a/components/asset/stories/asset.stories.js +++ b/components/asset/stories/asset.stories.js @@ -1,4 +1,3 @@ -// Import the component markup template import { Template } from "./template"; export default { @@ -7,6 +6,8 @@ export default { "Use an asset element to visually represent a file, folder or image. File and folder representations will center themselves horizontally and vertically in the space provided to the element. Images will be contained to the element, growing to the element's full height while centering itself within the width provided.", component: "Asset", argTypes: { + /* No theme styles for express available */ + express: { table: { disable: true } }, reducedMotion: { table: { disable: true } }, preset: { name: "Preset asset types", @@ -35,7 +36,7 @@ export default { status: { type: process.env.MIGRATED_PACKAGES.includes("asset") ? "migrated" - : undefined, + : "legacy", }, }, }; diff --git a/components/asset/stories/template.js b/components/asset/stories/template.js index cb3b9e01742..0946e5bd540 100644 --- a/components/asset/stories/template.js +++ b/components/asset/stories/template.js @@ -3,7 +3,6 @@ import { classMap } from "lit/directives/class-map.js"; import { ifDefined } from "lit/directives/if-defined.js"; import "../index.css"; -import "../skin.css"; export const Template = ({ rootClass = "spectrum-Asset", diff --git a/components/assetcard/metadata/mods.md b/components/assetcard/metadata/mods.md index f1f7b7d24de..867a8fe680f 100644 --- a/components/assetcard/metadata/mods.md +++ b/components/assetcard/metadata/mods.md @@ -1,4 +1,4 @@ -| Modifiable Custom Properties | +| Modifiable custom properties | | ------------------------------------------------------------- | | `--mod-assectcard-border-color-selected-down` | | `--mod-assectcard-focus-indicator-color` | diff --git a/components/assetcard/stories/assetcard.stories.js b/components/assetcard/stories/assetcard.stories.js index 81e57830723..e5a6f44e1fb 100644 --- a/components/assetcard/stories/assetcard.stories.js +++ b/components/assetcard/stories/assetcard.stories.js @@ -1,4 +1,3 @@ -// Import the component markup template import { Template } from "./template"; import { default as Checkbox } from "@spectrum-css/checkbox/stories/checkbox.stories.js"; @@ -7,7 +6,7 @@ export default { title: "Components/Asset card", description: "The asset card component allows users to select and manage assets and their metadata in a grid.", - component: "Assetcard", + component: "AssetCard", argTypes: { image: { name: "Image", @@ -102,7 +101,7 @@ export default { status: { type: process.env.MIGRATED_PACKAGES.includes("assetcard") ? "migrated" - : undefined, + : "legacy", }, }, }; @@ -161,3 +160,6 @@ DropTarget.args = { isDropTarget: true, isSelected: true, }; + +export const Express = Template.bind({}); +Express.args = { express: true }; diff --git a/components/assetlist/metadata/mods.md b/components/assetlist/metadata/mods.md index c8ce663d3cf..2b5081cf59e 100644 --- a/components/assetlist/metadata/mods.md +++ b/components/assetlist/metadata/mods.md @@ -1,4 +1,4 @@ -| Modifiable Custom Properties | +| Modifiable custom properties | | ------------------------------------------------------ | | `--mod-assetlist-border-color-key-focus` | | `--mod-assetlist-child-indicator-animation` | diff --git a/components/assetlist/stories/assetlist.stories.js b/components/assetlist/stories/assetlist.stories.js index a9fb4f26049..30d5da0e563 100644 --- a/components/assetlist/stories/assetlist.stories.js +++ b/components/assetlist/stories/assetlist.stories.js @@ -1,4 +1,3 @@ -// Import the component markup template import { Template } from "./template"; import { default as Checkbox } from "@spectrum-css/checkbox/stories/checkbox.stories.js"; @@ -9,10 +8,47 @@ export default { "A selectable list of Assets, often used inside of Miller Columns.", component: "AssetList", argTypes: { + /* No theme styles for express available */ + express: { table: { disable: true } }, items: { table: { disable: true } }, }, args: { rootClass: "spectrum-AssetList", + items: [ + { + image: "example-ava.png", + label: "Shantanu.jpg", + isSelectable: true, + ariaLabelledBy: "assetitemlabel-1", + checkboxId: "checkbox-1" + }, + { + iconName: "Document", + label: "Resource Allocation Documentation should truncate", + isSelectable: true, + ariaLabelledby: "assetitemlabel-2", + checkboxId: "checkbox-2", + }, + { + iconName: "Folder", + label: "Frontend Projects", + isSelectable: true, + isBranch: true, + isSelected: true, + ariaLabelledby: "assetitemlabel-3", + checkboxId: "checkbox-3", + }, + { + iconName: "Folder", + label: "Downloads", + isSelectable: true, + isBranch: true, + isSelected: false, + isNavigated: true, + ariaLabelledby: "assetitemlabel-4", + checkboxId: "checkbox-4", + }, + ], }, parameters: { actions: { @@ -21,46 +57,10 @@ export default { status: { type: process.env.MIGRATED_PACKAGES.includes("assetlist") ? "migrated" - : undefined, + : "legacy", }, }, }; export const Default = Template.bind({}); -Default.args = { - items: [ - { - image: "example-ava.png", - label: "Shantanu.jpg", - isSelectable: true, - ariaLabelledBy: "assetitemlabel-1", - checkboxId: "checkbox-1" - }, - { - iconName: "Document", - label: "Resource Allocation Documentation should truncate", - isSelectable: true, - ariaLabelledby: "assetitemlabel-2", - checkboxId: "checkbox-2", - }, - { - iconName: "Folder", - label: "Frontend Projects", - isSelectable: true, - isBranch: true, - isSelected: true, - ariaLabelledby: "assetitemlabel-3", - checkboxId: "checkbox-3", - }, - { - iconName: "Folder", - label: "Downloads", - isSelectable: true, - isBranch: true, - isSelected: false, - isNavigated: true, - ariaLabelledby: "assetitemlabel-4", - checkboxId: "checkbox-4", - }, - ], -}; +Default.args = {}; diff --git a/components/assetlist/stories/template.js b/components/assetlist/stories/template.js index f71dce53d13..f9bc00ee8cd 100644 --- a/components/assetlist/stories/template.js +++ b/components/assetlist/stories/template.js @@ -1,7 +1,7 @@ import { html } from "lit"; import { classMap } from "lit/directives/class-map.js"; -import { when } from "lit/directives/when.js"; import { ifDefined } from "lit/directives/if-defined.js"; +import { when } from "lit/directives/when.js"; import { useArgs } from "@storybook/client-api"; @@ -24,7 +24,6 @@ export const AssetListItem = ({ onclick = () => {}, ...globals }) => { - return html`
  • { return html`
    { - return html` -
    - ${Template({ - ...args, - iconName: undefined, - })} - ${Template({ - ...args, - })} - ${Template({ - ...args, - label: undefined, - })} - ${Template({ - ...args, - label: "24 days left in trial", - customStyles: { "max-inline-size": "100px" }, - })} -
    - `; -}; +const BadgeGroup = (args) => html` + ${Template({ + ...args, + iconName: undefined, + })} + ${Template({ + ...args, + })} + ${Template({ + ...args, + label: undefined, + })} + ${Template({ + ...args, + label: "24 days left in trial", + customStyles: { "max-inline-size": "100px" }, + })} +`; export const Default = BadgeGroup.bind({}); -Default.args = { -}; +Default.args = {}; diff --git a/components/badge/stories/template.js b/components/badge/stories/template.js index 175fbfad021..e1b4937ff22 100644 --- a/components/badge/stories/template.js +++ b/components/badge/stories/template.js @@ -1,7 +1,7 @@ import { html } from "lit"; import { classMap } from "lit/directives/class-map.js"; -import { styleMap } from "lit/directives/style-map.js"; import { ifDefined } from "lit/directives/if-defined.js"; +import { styleMap } from "lit/directives/style-map.js"; import { when } from "lit/directives/when.js"; import { Template as Icon } from "@spectrum-css/icon/stories/template.js"; @@ -20,15 +20,6 @@ export const Template = ({ id, ...globals }) => { - const { express } = globals; - - try { - if (!express) import(/* webpackPrefetch: true */ "../themes/spectrum.css"); - else import(/* webpackPrefetch: true */ "../themes/express.css"); - } catch (e) { - console.warn(e); - } - return html`
    { - const { express } = globals; - - try { - if (!express) import(/* webpackPrefetch: true */ "../themes/spectrum.css"); - else import(/* webpackPrefetch: true */ "../themes/express.css"); - } catch (e) { - console.warn(e); - } - return html`