diff --git a/.changeset/flat-snails-admire.md b/.changeset/flat-snails-admire.md new file mode 100644 index 0000000000..fa25475ac2 --- /dev/null +++ b/.changeset/flat-snails-admire.md @@ -0,0 +1,7 @@ +--- +"@spectrum-css/infieldprogresscircle": major +--- + +## Infield Progresscircle S2 Migration + +In-field progress circle is a new component created to replace progress circle (size S) in t-shirt size components. The button, textfield, combo box, and picker `template.js` files have all been updated to call for infield progress circles. This component comes in four sizes: (S, M, L, XL), has updated color variants (default, white, black), and has a unified track thickness. diff --git a/components/button/stories/template.js b/components/button/stories/template.js index cecada6f7a..1fa7369774 100644 --- a/components/button/stories/template.js +++ b/components/button/stories/template.js @@ -1,6 +1,6 @@ import { Template as Icon } from "@spectrum-css/icon/stories/template.js"; +import { Template as InfieldProgressCircle } from "@spectrum-css/infieldprogresscircle/stories/template.js"; import { Container, getRandomId } from "@spectrum-css/preview/decorators"; -import { Template as ProgressCircle } from "@spectrum-css/progresscircle/stories/template.js"; import { html } from "lit"; import { classMap } from "lit/directives/class-map.js"; import { ifDefined } from "lit/directives/if-defined.js"; @@ -89,15 +89,12 @@ export const Template = ({ Icon({ iconName, setName: iconSet, size }, context) )} ${when(isPending, () => - ProgressCircle( - { - size: "s", - testId: "progress-circle", - staticColor, - isIndeterminate: true, - }, - context - ) + InfieldProgressCircle({ + size: size, + staticColor, + isIndeterminate: true, + testId: "infield-progress-circle" + }, context) )} `; diff --git a/components/combobox/stories/template.js b/components/combobox/stories/template.js index 96dfdcf25e..f8cc0dbc1b 100644 --- a/components/combobox/stories/template.js +++ b/components/combobox/stories/template.js @@ -63,7 +63,7 @@ const Combobox = ({ ], customInputClasses: [`${rootClass}-input`], isLoading, - customProgressCircleClasses: ["spectrum-Combobox-progress-circle"], + customInfieldProgressCircleClasses: ["spectrum-Combobox-progress-circle"], name: "field", isReadOnly, value, diff --git a/components/infieldprogresscircle/README.md b/components/infieldprogresscircle/README.md new file mode 100644 index 0000000000..4d411cc950 --- /dev/null +++ b/components/infieldprogresscircle/README.md @@ -0,0 +1,7 @@ +# @spectrum-css/infieldprogresscircle + +> The Spectrum CSS infield progress circle component + +This package is part of the [Spectrum CSS project](https://github.com/adobe/spectrum-css). + +See the [Spectrum CSS documentation](https://opensource.adobe.com/spectrum-css/) and [Spectrum CSS on GitHub](https://github.com/adobe/spectrum-css) for details. diff --git a/components/infieldprogresscircle/dist/metadata.json b/components/infieldprogresscircle/dist/metadata.json new file mode 100644 index 0000000000..ffc95f1139 --- /dev/null +++ b/components/infieldprogresscircle/dist/metadata.json @@ -0,0 +1,25 @@ +{ + "sourceFile": "index.css", + "selectors": [ + ".spectrum-InfieldProgressCircle", + ".spectrum-InfieldProgressCircle .spectrum-ProgressCircle-fill", + ".spectrum-InfieldProgressCircle--sizeL", + ".spectrum-InfieldProgressCircle--sizeS", + ".spectrum-InfieldProgressCircle--sizeXL" + ], + "modifiers": [], + "component": [ + "--spectrum-in-field-progress-circle-edge-to-fill", + "--spectrum-in-field-progress-circle-size-100", + "--spectrum-in-field-progress-circle-size-200", + "--spectrum-in-field-progress-circle-size-300", + "--spectrum-in-field-progress-circle-size-75", + "--spectrum-infieldprogresscircle-padding-block" + ], + "global": ["--spectrum-progress-circle-thickness-small"], + "passthroughs": [ + "--mod-progress-circle-size", + "--mod-progress-circle-thickness" + ], + "high-contrast": [] +} diff --git a/components/infieldprogresscircle/index.css b/components/infieldprogresscircle/index.css new file mode 100644 index 0000000000..e3525eccc4 --- /dev/null +++ b/components/infieldprogresscircle/index.css @@ -0,0 +1,37 @@ +/*! +Copyright 2025 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-InfieldProgressCircle { + --mod-progress-circle-thickness: var(--spectrum-progress-circle-thickness-small); + --mod-progress-circle-size: var(--spectrum-in-field-progress-circle-size-100); + --spectrum-infieldprogresscircle-padding-block: var(--spectrum-in-field-progress-circle-edge-to-fill); +} + +.spectrum-InfieldProgressCircle--sizeS { + --mod-progress-circle-size: var(--spectrum-in-field-progress-circle-size-75); +} + +.spectrum-InfieldProgressCircle--sizeL { + --mod-progress-circle-size: var(--spectrum-in-field-progress-circle-size-200); +} + +.spectrum-InfieldProgressCircle--sizeXL { + --mod-progress-circle-size: var(--spectrum-in-field-progress-circle-size-300); +} + +.spectrum-InfieldProgressCircle { + padding-block: var(--spectrum-infieldprogresscircle-padding-block); + + .spectrum-ProgressCircle-fill { + stroke-linecap: square; + } +} diff --git a/components/infieldprogresscircle/package.json b/components/infieldprogresscircle/package.json new file mode 100644 index 0000000000..a8248fc83c --- /dev/null +++ b/components/infieldprogresscircle/package.json @@ -0,0 +1,52 @@ +{ + "name": "@spectrum-css/infieldprogresscircle", + "version": "0.0.0", + "description": "The Spectrum CSS infieldprogresscircle component", + "license": "Apache-2.0", + "author": "Adobe", + "homepage": "https://opensource.adobe.com/spectrum-css/?path=/docs/components-in-field-progress-circle--docs", + "repository": { + "type": "git", + "url": "https://github.com/adobe/spectrum-css.git", + "directory": "components/infieldprogresscircle" + }, + "bugs": { + "url": "https://github.com/adobe/spectrum-css/issues" + }, + "exports": { + ".": "./dist/index.css", + "./*.md": "./*.md", + "./dist/*": "./dist/*", + "./index-*.css": "./dist/index-*.css", + "./index.css": "./dist/index.css", + "./metadata.json": "./dist/metadata.json", + "./package.json": "./package.json", + "./stories/*": "./stories/*" + }, + "main": "dist/index.css", + "peerDependencies": { + "@spectrum-css/tokens": ">=16" + }, + "devDependencies": { + "@spectrum-css/tokens": "16.0.0" + }, + "keywords": [ + "design-system", + "spectrum", + "spectrum-css", + "adobe", + "adobe-spectrum", + "component", + "css" + ], + "publishConfig": { + "access": "public" + }, + "spectrum": [ + { + "guidelines": "https://spectrum.adobe.com/page/progress-circle", + "rootClass": "spectrum-InfieldProgressCircle", + "swc": "https://opensource.adobe.com/spectrum-web-components/components/progress-circle/" + } + ] +} diff --git a/components/infieldprogresscircle/project.json b/components/infieldprogresscircle/project.json new file mode 100644 index 0000000000..ff11b0651f --- /dev/null +++ b/components/infieldprogresscircle/project.json @@ -0,0 +1,17 @@ +{ + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "name": "infieldprogresscircle", + "tags": ["component"], + "targets": { + "build": {}, + "clean": {}, + "compare": {}, + "format": {}, + "lint": {}, + "report": {}, + "test": { + "defaultConfiguration": "scope" + }, + "validate": {} + } +} diff --git a/components/infieldprogresscircle/stories/infieldprogresscircle.stories.js b/components/infieldprogresscircle/stories/infieldprogresscircle.stories.js new file mode 100644 index 0000000000..e8c60ee9d6 --- /dev/null +++ b/components/infieldprogresscircle/stories/infieldprogresscircle.stories.js @@ -0,0 +1,121 @@ +import { Sizes } from "@spectrum-css/preview/decorators"; +import { disableDefaultModes } from "@spectrum-css/preview/modes"; +import { size } from "@spectrum-css/preview/types"; +import { default as ProgressCircle } from "@spectrum-css/progresscircle/stories/progresscircle.stories.js"; +import metadata from "../dist/metadata.json"; +import packageJson from "../package.json"; +import { InfieldProgressCircleGroup } from "./infieldprogresscircle.test.js"; +import { Template } from "./template.js"; + +/** + * In-field progress circles are used in t-shirt size components such as [buttons](/docs/components-button--docs), [combo boxes](/docs/components-combobox--docs), and [pickers](/docs/components-picker--docs). The in-field progress circle can be used in place of an icon or in tight spaces when space is limited both vertically and horizontally. +*/ + +export default { + title: "In-field progress circle", + component: "InfieldProgressCircle", + argTypes: { + ...ProgressCircle.argTypes, + size: size(["s", "m", "l", "xl"]), + }, + args: { + ...ProgressCircle.args, + rootClass: "spectrum-InfieldProgressCircle", + }, + parameters: { + ...ProgressCircle.parameters, + design: { + type: "figma", + url: "https://www.figma.com/design/eoZHKJH9a3LJkHYCGt60Vb/S2-token-specs?node-id=14970-6050", + }, + packageJson, + metadata, + } +}; + +export const Default = InfieldProgressCircleGroup.bind({}); +Default.args = {}; + +// ********* VRT ONLY ********* // +export const WithForcedColors = InfieldProgressCircleGroup.bind({}); +WithForcedColors.args = Default.args; +WithForcedColors.tags = ["!autodocs", "!dev"]; +WithForcedColors.parameters = { + chromatic: { + forcedColors: "active", + modes: disableDefaultModes, + }, +}; + +// ********* DOCS ONLY ********* // + +export const Sizing = (args, context) => Sizes({ + Template, + withHeading: false, + withBorder: false, + ...args, +}, context); +Sizing.args = {}; +Sizing.tags = ["!dev"]; +Sizing.parameters = { + chromatic: { disableSnapshot: true }, +}; + +/** + * The indeterminate progress circle displays a repeating animation for the inner fill. + */ +export const Indeterminate = (args, context) => Sizes({ + Template, + withHeading: false, + withBorder: false, + ...args, +}, context); +Indeterminate.args = { + isIndeterminate: true, +}; +Indeterminate.tags = ["!dev"]; +Indeterminate.parameters = { + chromatic: { disableSnapshot: true }, +}; + +export const StaticWhiteDeterminate = Sizing.bind({}); +StaticWhiteDeterminate.tags = ["!dev"]; +StaticWhiteDeterminate.storyName = "Static white, default"; +StaticWhiteDeterminate.args = { + staticColor: "white", +}; +StaticWhiteDeterminate.parameters = { + chromatic: { disableSnapshot: true }, +}; + +export const StaticWhiteIndeterminate = Sizing.bind({}); +StaticWhiteIndeterminate.tags = ["!dev"]; +StaticWhiteIndeterminate.storyName = "Static white, indeterminate"; +StaticWhiteIndeterminate.args = { + staticColor: "white", + isIndeterminate: true, +}; +StaticWhiteIndeterminate.parameters = { + chromatic: { disableSnapshot: true }, +}; + +export const StaticBlackDeterminate = Sizing.bind({}); +StaticBlackDeterminate.tags = ["!dev"]; +StaticBlackDeterminate.storyName = "Static black, default"; +StaticBlackDeterminate.args = { + staticColor: "black", +}; +StaticBlackDeterminate.parameters = { + chromatic: { disableSnapshot: true }, +}; + +export const StaticBlackIndeterminate = Sizing.bind({}); +StaticBlackIndeterminate.tags = ["!dev"]; +StaticBlackIndeterminate.storyName = "Static black, indeterminate"; +StaticBlackIndeterminate.args = { + staticColor: "black", + isIndeterminate: true, +}; +StaticBlackIndeterminate.parameters = { + chromatic: { disableSnapshot: true }, +}; diff --git a/components/infieldprogresscircle/stories/infieldprogresscircle.test.js b/components/infieldprogresscircle/stories/infieldprogresscircle.test.js new file mode 100644 index 0000000000..2ef07f947a --- /dev/null +++ b/components/infieldprogresscircle/stories/infieldprogresscircle.test.js @@ -0,0 +1,25 @@ +import { Variants } from "@spectrum-css/preview/decorators"; +import { Template } from "./template.js"; + +export const InfieldProgressCircleGroup = Variants({ + Template, + testData: [ + { + testHeading: "Default", + }, + { + testHeading: "Static white", + staticColor: "white", + }, + { + testHeading: "Static black", + staticColor: "black", + }, + ], + stateData: [ + { + testHeading: "Indeterminate", + isIndeterminate: true, + } + ] +}); diff --git a/components/infieldprogresscircle/stories/template.js b/components/infieldprogresscircle/stories/template.js new file mode 100644 index 0000000000..7f8fc1f8de --- /dev/null +++ b/components/infieldprogresscircle/stories/template.js @@ -0,0 +1,21 @@ +import { Template as ProgressCircle } from "@spectrum-css/progresscircle/stories/template.js"; +import { capitalize } from "lodash-es"; +import "../index.css"; + +export const Template = ({ + customClasses = [], + rootClass = "spectrum-InfieldProgressCircle", + size = "m", + staticColor, + ...item +} = {}, context = {}) => ProgressCircle({ + customClasses: [ + rootClass, + typeof size !== "undefined" ? `${rootClass}--size${size.toUpperCase()}` : null, + typeof staticColor !== "undefined" ? `${rootClass}--static${capitalize(staticColor)}` : null, + ...customClasses + ].filter(Boolean), + size, + staticColor, + ...item +}, context ); diff --git a/components/picker/stories/template.js b/components/picker/stories/template.js index f1219f9808..0d8bec6d42 100644 --- a/components/picker/stories/template.js +++ b/components/picker/stories/template.js @@ -1,9 +1,9 @@ import { Template as FieldLabel } from "@spectrum-css/fieldlabel/stories/template.js"; import { Template as HelpText } from "@spectrum-css/helptext/stories/template.js"; import { Template as Icon } from "@spectrum-css/icon/stories/template.js"; +import { Template as InfieldProgressCircle } from "@spectrum-css/infieldprogresscircle/stories/template.js"; import { Template as Popover } from "@spectrum-css/popover/stories/template.js"; import { Container, getRandomId } from "@spectrum-css/preview/decorators"; -import { Template as ProgressCircle } from "@spectrum-css/progresscircle/stories/template.js"; import { Template as Switch } from "@spectrum-css/switch/stories/template.js"; import { html } from "lit"; import { classMap } from "lit/directives/class-map.js"; @@ -78,8 +78,8 @@ export const Picker = ({ } ${placeholder} ${when(isLoading, () => - ProgressCircle({ - size: "s", + InfieldProgressCircle({ + size: size, isIndeterminate: true, }, context) )} diff --git a/components/progresscircle/stories/progresscircle.stories.js b/components/progresscircle/stories/progresscircle.stories.js index ac3f311133..9146a54f0f 100644 --- a/components/progresscircle/stories/progresscircle.stories.js +++ b/components/progresscircle/stories/progresscircle.stories.js @@ -17,11 +17,18 @@ export default { isIndeterminate, staticColor, value: { + name: "Percent filled", + type: { name: "number" }, + table: { + type: { summary: "number" }, + category: "Content", + }, control: { type: "range", min: 0, max: 100 - } + }, + if: { arg: "isIndeterminate", truthy: false }, } }, args: { diff --git a/components/textfield/stories/template.js b/components/textfield/stories/template.js index 55c2d55d12..9413a7504e 100644 --- a/components/textfield/stories/template.js +++ b/components/textfield/stories/template.js @@ -1,8 +1,8 @@ import { Template as FieldLabel } from "@spectrum-css/fieldlabel/stories/template.js"; import { Template as HelpText } from "@spectrum-css/helptext/stories/template.js"; import { Template as Icon } from "@spectrum-css/icon/stories/template.js"; +import { Template as InfieldProgressCircle } from "@spectrum-css/infieldprogresscircle/stories/template.js"; import { Container, getRandomId } from "@spectrum-css/preview/decorators"; -import { Template as ProgressCircle } from "@spectrum-css/progresscircle/stories/template.js"; import { html } from "lit"; import { classMap } from "lit/directives/class-map.js"; import { ifDefined } from "lit/directives/if-defined.js"; @@ -18,7 +18,7 @@ import "../index.css"; * @property {string[]} [customClasses=[]] * @property {string[]} [customInputClasses=[]] * @property {string[]} [customIconClasses=[]] - * @property {string[]} [customProgressCircleClasses=[]] + * @property {string[]} [customInfieldProgressCircleClasses=[]] * @property {Record} [customStyles={}] * @property {boolean} [isInvalid=false] * @property {boolean} [isValid=false] @@ -58,7 +58,7 @@ export const Template = ({ customClasses = [], customInputClasses = [], customIconClasses = [], - customProgressCircleClasses = [], + customInfieldProgressCircleClasses = [], isInvalid = false, isValid = false, multiline = false, @@ -196,10 +196,10 @@ export const Template = ({ })} />` )} - ${when(isLoading, () => ProgressCircle({ + ${when(isLoading, () => InfieldProgressCircle({ isIndeterminate: true, - size: "s", - customClasses: customProgressCircleClasses, + size: size, + customClasses: customInfieldProgressCircleClasses, }, context))} ${when(helpText, () => HelpText({ diff --git a/tools/bundle/package.json b/tools/bundle/package.json index 118d537cbb..705df26f32 100644 --- a/tools/bundle/package.json +++ b/tools/bundle/package.json @@ -74,6 +74,7 @@ "@spectrum-css/icon": "workspace:^", "@spectrum-css/illustratedmessage": "workspace:^", "@spectrum-css/infieldbutton": "workspace:^", + "@spectrum-css/infieldprogresscircle": "workspace:^", "@spectrum-css/inlinealert": "workspace:^", "@spectrum-css/link": "workspace:^", "@spectrum-css/logicbutton": "workspace:^", diff --git a/tools/bundle/src/index.css b/tools/bundle/src/index.css index 31d68ccee0..3f1db509c7 100644 --- a/tools/bundle/src/index.css +++ b/tools/bundle/src/index.css @@ -66,6 +66,7 @@ @import "@spectrum-css/icon"; @import "@spectrum-css/illustratedmessage"; @import "@spectrum-css/infieldbutton"; +@import "@spectrum-css/infieldprogresscircle"; @import "@spectrum-css/inlinealert"; @import "@spectrum-css/link"; @import "@spectrum-css/logicbutton"; diff --git a/yarn.lock b/yarn.lock index 6a9bc09938..86493c1f22 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3902,6 +3902,7 @@ __metadata: "@spectrum-css/icon": "workspace:^" "@spectrum-css/illustratedmessage": "workspace:^" "@spectrum-css/infieldbutton": "workspace:^" + "@spectrum-css/infieldprogresscircle": "workspace:^" "@spectrum-css/inlinealert": "workspace:^" "@spectrum-css/link": "workspace:^" "@spectrum-css/logicbutton": "workspace:^" @@ -4440,6 +4441,16 @@ __metadata: languageName: unknown linkType: soft +"@spectrum-css/infieldprogresscircle@workspace:^, @spectrum-css/infieldprogresscircle@workspace:components/infieldprogresscircle": + version: 0.0.0-use.local + resolution: "@spectrum-css/infieldprogresscircle@workspace:components/infieldprogresscircle" + dependencies: + "@spectrum-css/tokens": "npm:16.0.0" + peerDependencies: + "@spectrum-css/tokens": ">=16" + languageName: unknown + linkType: soft + "@spectrum-css/inlinealert@workspace:^, @spectrum-css/inlinealert@workspace:components/inlinealert": version: 0.0.0-use.local resolution: "@spectrum-css/inlinealert@workspace:components/inlinealert"