diff --git a/.changeset/proud-schools-reply.md b/.changeset/proud-schools-reply.md new file mode 100644 index 00000000000..3207fb9cdad --- /dev/null +++ b/.changeset/proud-schools-reply.md @@ -0,0 +1,42 @@ +--- +`@spectrum-css/swatchgroup`: major +`@spectrum-css/swatch`: major +--- + +#### S2 migration swatchgroup + +This migrates the `swatch` and `swatchgroup` components to S2. Custom properties have been remapped and added per the design specification. + +An `Add Swatch` variant has been added with the required color tokens and the specified add UI icon. + +##### Removed custom properties + +`--spectrum-swatch-border-color` +`--spectrum-swatch-dash-icon-color` + +##### New custom properties + +`--spectrum-swatch-border-color-rgb` +`--spectrum-swatch-border-opacity` +`--spectrum-corner-radius-full` +`--spectrum-corner-radius-none` +`--spectrum-swatch-disabled-icon-border-opacity` +`--spectrum-swatch-icon-color` +`--spectrum-swatch-rectangle-width-multiplier` +`--spectrum-swatchgroup-border-color` + +##### New mods + +`--mod-add-button-background` +`--mod-add-button-background-down` +`--mod-add-button-background-hover` +`--mod-add-button-background-keyboard-focus` +`--mod-corner-radius-full` +`--mod-mixed-button-background` +`--mod-swatchgroup-border-color` +`--mod-swatch-border-color-rgb` +`--mod-swatch-border-opacity` + +##### Removed mods + +`--mod-swatchgroup-spacing-compact` diff --git a/components/swatch/dist/metadata.json b/components/swatch/dist/metadata.json index e3affcc83cb..c2f20eb82ff 100644 --- a/components/swatch/dist/metadata.json +++ b/components/swatch/dist/metadata.json @@ -4,6 +4,7 @@ ".spectrum-Swatch", ".spectrum-Swatch .spectrum-Swatch-disabledIcon", ".spectrum-Swatch .spectrum-Swatch-fill", + ".spectrum-Swatch--border .spectrum-Swatch-fill:before", ".spectrum-Swatch--lightBorder .spectrum-Swatch-fill:before", ".spectrum-Swatch--noBorder .spectrum-Swatch-fill:before", ".spectrum-Swatch--rectangle", @@ -29,13 +30,22 @@ ".spectrum-Swatch-disabledIcon path:last-child", ".spectrum-Swatch-fill", ".spectrum-Swatch-fill:before", + ".spectrum-Swatch-icon", ".spectrum-Swatch-image", - ".spectrum-Swatch-mixedValueIcon", + ".spectrum-Swatch.is-addSwatch", + ".spectrum-Swatch.is-addSwatch .spectrum-Swatch-fill", + ".spectrum-Swatch.is-addSwatch .spectrum-Swatch-icon", + ".spectrum-Swatch.is-addSwatch.is-keyboardFocused", + ".spectrum-Swatch.is-addSwatch:active", + ".spectrum-Swatch.is-addSwatch:focus-visible", + ".spectrum-Swatch.is-addSwatch:hover", ".spectrum-Swatch.is-disabled", ".spectrum-Swatch.is-disabled .spectrum-Swatch-disabledIcon", ".spectrum-Swatch.is-image .spectrum-Swatch-fill:before", + ".spectrum-Swatch.is-keyboardFocused", + ".spectrum-Swatch.is-mixedValue", ".spectrum-Swatch.is-mixedValue .spectrum-Swatch-fill", - ".spectrum-Swatch.is-mixedValue .spectrum-Swatch-mixedValueIcon", + ".spectrum-Swatch.is-mixedValue .spectrum-Swatch-icon", ".spectrum-Swatch.is-nothing .spectrum-Swatch-fill", ".spectrum-Swatch.is-nothing .spectrum-Swatch-fill:after", ".spectrum-Swatch.is-nothing.spectrum-Swatch--rectangle .spectrum-Swatch-fill:after", @@ -43,48 +53,58 @@ ".spectrum-Swatch.is-selected .spectrum-Swatch-fill", ".spectrum-Swatch.is-selected .spectrum-Swatch-fill:before", ".spectrum-Swatch.is-selected:before", - ".spectrum-Swatch:after", ".spectrum-Swatch:before", - ".spectrum-Swatch:focus-visible:after", + ".spectrum-Swatch:focus-visible", ".spectrum-Swatch[disabled]", ".spectrum-Swatch[disabled] .spectrum-Swatch-disabledIcon" ], "modifiers": [ + "--mod-add-button-background", + "--mod-add-button-background-down", + "--mod-add-button-background-hover", + "--mod-add-button-background-keyboard-focus", "--mod-animation-duration-100", + "--mod-corner-radius-full", + "--mod-mixed-button-background", "--mod-swatch-border-color", "--mod-swatch-border-color-light", + "--mod-swatch-border-color-rgb", "--mod-swatch-border-color-selected", + "--mod-swatch-border-opacity", "--mod-swatch-border-radius", "--mod-swatch-border-thickness", "--mod-swatch-border-thickness-selected", "--mod-swatch-disabled-icon-color", "--mod-swatch-disabled-icon-size", - "--mod-swatch-focus-indicator-border-radius", "--mod-swatch-focus-indicator-color", "--mod-swatch-focus-indicator-gap", "--mod-swatch-focus-indicator-thickness", "--mod-swatch-icon-border-color", + "--mod-swatch-icon-color", "--mod-swatch-inner-border-color-selected", "--mod-swatch-size", "--mod-swatch-slash-icon-color", - "--mod-swatch-slash-thickness" + "--mod-swatch-slash-thickness", + "--mod-swatchgroup-border-color" ], "component": [ - "--spectrum-swatch-border-color", "--spectrum-swatch-border-color-light", + "--spectrum-swatch-border-color-rgb", "--spectrum-swatch-border-color-selected", + "--spectrum-swatch-border-opacity", "--spectrum-swatch-border-radius", "--spectrum-swatch-border-thickness", "--spectrum-swatch-border-thickness-selected", - "--spectrum-swatch-dash-icon-color", + "--spectrum-swatch-disabled-icon-border-opacity", "--spectrum-swatch-disabled-icon-color", "--spectrum-swatch-disabled-icon-size", - "--spectrum-swatch-focus-indicator-border-radius", "--spectrum-swatch-focus-indicator-color", "--spectrum-swatch-focus-indicator-gap", "--spectrum-swatch-focus-indicator-thickness", "--spectrum-swatch-icon-border-color", + "--spectrum-swatch-icon-color", "--spectrum-swatch-inner-border-color-selected", + "--spectrum-swatch-rectangle-width-multiplier", "--spectrum-swatch-size", "--spectrum-swatch-size-extra-small", "--spectrum-swatch-size-large", @@ -95,21 +115,32 @@ "--spectrum-swatch-slash-thickness-extra-small", "--spectrum-swatch-slash-thickness-large", "--spectrum-swatch-slash-thickness-medium", - "--spectrum-swatch-slash-thickness-small" + "--spectrum-swatch-slash-thickness-small", + "--spectrum-swatchgroup-border-color" ], "global": [ + "--spectrum-add-button-background", + "--spectrum-add-button-background-down", + "--spectrum-add-button-background-hover", + "--spectrum-add-button-background-keyboard-focus", "--spectrum-animation-duration-100", "--spectrum-border-width-100", "--spectrum-border-width-200", - "--spectrum-corner-radius-100", + "--spectrum-corner-radius-75", + "--spectrum-corner-radius-full", + "--spectrum-corner-radius-none", "--spectrum-focus-indicator-color", "--spectrum-focus-indicator-gap", "--spectrum-focus-indicator-thickness", + "--spectrum-gray-100", + "--spectrum-gray-1000", + "--spectrum-gray-1000-rgb", + "--spectrum-gray-200", "--spectrum-gray-25", - "--spectrum-gray-800", - "--spectrum-gray-900", + "--spectrum-mixed-button-background", + "--spectrum-negative-visual-color", + "--spectrum-neutral-content-color-default", "--spectrum-picked-color", - "--spectrum-red-900", "--spectrum-white", "--spectrum-workflow-icon-size-100", "--spectrum-workflow-icon-size-200", @@ -123,6 +154,7 @@ "--highcontrast-swatch-border-color-selected", "--highcontrast-swatch-disabled-icon-color", "--highcontrast-swatch-fill-foreground-color", - "--highcontrast-swatch-focus-indicator-color" + "--highcontrast-swatch-focus-indicator-color", + "--highcontrast-swatch-icon-color" ] } diff --git a/components/swatch/index.css b/components/swatch/index.css index f0f03dbaac9..3c22d0c4c12 100644 --- a/components/swatch/index.css +++ b/components/swatch/index.css @@ -1,5 +1,5 @@ /*! - * Copyright 2024 Adobe. All rights reserved. + * 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 @@ -11,29 +11,39 @@ * governing permissions and limitations under the License. */ - /* @note: default sizing for swatch is small */ +/* @note: default sizing for swatch is small */ .spectrum-Swatch { /* Placeholder tokens */ - --spectrum-swatch-focus-indicator-border-radius: var(--mod-swatch-focus-indicator-border-radius, 8px); - --spectrum-swatch-icon-border-color: var(--mod-swatch-icon-border-color, rgb(0 0 0 / 51%)); + --spectrum-swatch-icon-border-color: var(--mod-swatch-icon-border-color, rgb(0 0 0 / var(--spectrum-swatch-disabled-icon-border-opacity))); /* Size */ --spectrum-swatch-size: var(--mod-swatch-size, var(--spectrum-swatch-size-small)); - --spectrum-swatch-border-radius: var(--mod-swatch-border-radius, var(--spectrum-corner-radius-100)); + --spectrum-swatch-border-radius: var(--mod-swatch-border-radius, var(--spectrum-corner-radius-75)); --spectrum-swatch-border-thickness: var(--mod-swatch-border-thickness, var(--spectrum-border-width-100)); --spectrum-swatch-border-thickness-selected: var(--mod-swatch-border-thickness-selected, var(--spectrum-border-width-200)); --spectrum-swatch-disabled-icon-size: var(--mod-swatch-disabled-icon-size, var(--spectrum-workflow-icon-size-75)); --spectrum-swatch-slash-thickness: var(--mod-swatch-slash-thickness, var(--spectrum-swatch-slash-thickness-small)); - --spectrum-swatch-focus-indicator-thickness: var(--mod-swatch-focus-indicator-thickness, var(--spectrum-focus-indicator-thickness)); - --spectrum-swatch-focus-indicator-gap: var(--mod-swatch-focus-indicator-gap, var(--spectrum-focus-indicator-gap)); /* Color */ - --spectrum-swatch-border-color-selected: var(--highcontrast-swatch-border-color-selected, var(--mod-swatch-border-color-selected, var(--spectrum-gray-900))); + --spectrum-swatch-border-color-selected: var(--highcontrast-swatch-border-color-selected, var(--mod-swatch-border-color-selected, var(--spectrum-gray-1000))); + --spectrum-swatch-border-color-rgb: var(--spectrum-gray-1000-rgb); --spectrum-swatch-inner-border-color-selected: var(--highcontrast-swatch-background-color-selected, var(--mod-swatch-inner-border-color-selected, var(--spectrum-gray-25))); --spectrum-swatch-disabled-icon-color: var(--highcontrast-swatch-disabled-icon-color, var(--mod-swatch-disabled-icon-color, var(--spectrum-white))); - --spectrum-swatch-dash-icon-color: var(--spectrum-gray-800); - --spectrum-swatch-slash-icon-color: var(--highcontrast-swatch-fill-foreground-color, var(--mod-swatch-slash-icon-color, var(--spectrum-red-900))); + --spectrum-swatch-icon-color: var(--highcontrast-swatch-icon-color, var(--mod-swatch-icon-color, var(--spectrum-neutral-content-color-default))); + --spectrum-swatch-slash-icon-color: var(--highcontrast-swatch-fill-foreground-color, var(--mod-swatch-slash-icon-color, var(--spectrum-negative-visual-color))); + --spectrum-mixed-button-background: var(--spectrum-gray-25); + --spectrum-add-button-background: var(--spectrum-gray-100); + --spectrum-add-button-background-hover: var(--spectrum-gray-200); + --spectrum-add-button-background-down: var(--spectrum-gray-200); + --spectrum-add-button-background-keyboard-focus: var(--spectrum-gray-200); + + /* TODO update to use tokens once available */ + --spectrum-swatch-border-color-light: rgb(var(--spectrum-gray-1000-rgb), 0.2); + + /* Focus ring */ --spectrum-swatch-focus-indicator-color: var(--highcontrast-swatch-focus-indicator-color, var(--mod-swatch-focus-indicator-color, var(--spectrum-focus-indicator-color))); + --spectrum-swatch-focus-indicator-thickness: var(--mod-swatch-focus-indicator-thickness, var(--spectrum-focus-indicator-thickness)); + --spectrum-swatch-focus-indicator-gap: var(--mod-swatch-focus-indicator-gap, var(--spectrum-focus-indicator-gap)); } .spectrum-Swatch--sizeXS { @@ -54,27 +64,6 @@ --spectrum-swatch-slash-thickness: var(--mod-swatch-slash-thickness, var(--spectrum-swatch-slash-thickness-large)); } -/* Windows high contrast mode */ -@media (forced-colors: active) { - .spectrum-Swatch { - --highcontrast-swatch-disabled-icon-color: GrayText; - --highcontrast-swatch-focus-indicator-color: ButtonText; - --highcontrast-swatch-background-color-selected: Background; - --highcontrast-swatch-border-color-selected: Highlight; - --highcontrast-swatch-border-color: ButtonText; - --highcontrast-swatch-fill-foreground-color: ButtonText; - - .spectrum-Swatch-fill { - forced-color-adjust: none; - } - - &[disabled], - &.is-disabled { - --highcontrast-swatch-border-color: GrayText; - } - } -} - .spectrum-Swatch { inline-size: var(--spectrum-swatch-size); block-size: var(--spectrum-swatch-size); @@ -86,7 +75,9 @@ /* contain selection indicator and focus-ring */ position: relative; - outline: none; + outline-width: 0; + outline-style: solid; + outline-color: transparent; /* don't let double clicking select stuff */ user-select: none; @@ -101,6 +92,50 @@ border-radius: var(--spectrum-swatch-border-radius); } + &.is-mixedValue { + --spectrum-picked-color: var(--mod-mixed-button-background, var(--spectrum-mixed-button-background)); + } + + &.is-addSwatch { + --spectrum-picked-color: var(--mod-add-button-background, var(--spectrum-add-button-background)); + + .spectrum-Swatch-fill { + background: var(--spectrum-picked-color); + } + + &:hover { + --spectrum-picked-color: var(--mod-add-button-background-hover, var(--spectrum-add-button-background-hover)); + } + + &:active { + --spectrum-picked-color: var(--mod-add-button-background-down, var(--spectrum-add-button-background-down)); + } + + &:hover, + &:active { + cursor: pointer; + } + + &.is-keyboardFocused, + &:focus-visible { + --spectrum-picked-color: var(--mod-add-button-background-keyboard-focus, var(--spectrum-add-button-background-keyboard-focus)); + } + + .spectrum-Swatch-icon { + color: var(--spectrum-swatch-icon-color); + display: block; + } + } + + &.is-keyboardFocused, + &:focus-visible { + outline-width: var(--mod-swatch-focus-indicator-thickness, var(--spectrum-swatch-focus-indicator-thickness)); + outline-color: var(--mod-swatch-focus-indicator-color, var(--spectrum-swatch-focus-indicator-color)); + outline-offset: var(--mod-swatch-focus-indicator-gap, var(--spectrum-swatch-focus-indicator-gap)); + + transition: outline-color var(--mod-animation-duration-100, var(--spectrum-animation-duration-100)) ease-in-out; + } + &.is-selected { background: var(--spectrum-swatch-inner-border-color-selected); @@ -138,8 +173,8 @@ background: var(--spectrum-picked-color, transparent); } - .spectrum-Swatch-mixedValueIcon { - color: var(--spectrum-swatch-dash-icon-color); + .spectrum-Swatch-icon { + color: var(--spectrum-swatch-icon-color); display: block; } } @@ -186,28 +221,6 @@ pointer-events: none; } - - /* focus-ring */ - &::after { - content: ""; - position: absolute; - inset: calc(-2 * var(--spectrum-swatch-focus-indicator-gap)); - - opacity: 0; - - border-width: var(--spectrum-swatch-focus-indicator-thickness); - border-style: solid; - border-color: var(--spectrum-swatch-focus-indicator-color); - border-radius: var(--spectrum-swatch-focus-indicator-border-radius); - - transition: opacity var(--mod-animation-duration-100, var(--spectrum-animation-duration-100)) ease-in-out; - } - - &:focus-visible { - &::after { - opacity: 1; - } - } } .spectrum-Swatch-fill { @@ -236,7 +249,7 @@ background: var(--spectrum-picked-color, transparent); /* Swatch border */ - box-shadow: inset 0 0 0 var(--mod-swatch-border-thickness, var(--spectrum-swatch-border-thickness)) var(--highcontrast-swatch-border-color, var(--mod-swatch-border-color, var(--spectrum-swatch-border-color))); + box-shadow: inset 0 0 0 var(--mod-swatch-border-thickness, var(--spectrum-swatch-border-thickness)) var(--highcontrast-swatch-border-color, var(--mod-swatch-border-color, rgb(var(--mod-swatch-border-color-rgb, var(--spectrum-swatch-border-color-rgb)), var(--mod-swatch-border-opacity, var(--spectrum-swatch-border-opacity))))); border-radius: var(--mod-swatch-border-radius, var(--spectrum-swatch-border-radius)); } } @@ -251,6 +264,14 @@ } } +.spectrum-Swatch--border { + .spectrum-Swatch-fill { + &::before { + box-shadow: inset 0 0 0 var(--spectrum-swatch-border-thickness) var(--mod-swatchgroup-border-color, var(--spectrum-swatchgroup-border-color)); + } + } +} + .spectrum-Swatch--lightBorder { .spectrum-Swatch-fill { &::before { @@ -259,7 +280,7 @@ } } -.spectrum-Swatch-mixedValueIcon { +.spectrum-Swatch-icon { display: none; pointer-events: none; @@ -289,7 +310,7 @@ } .spectrum-Swatch--rectangle { - inline-size: calc(var(--spectrum-swatch-size) * 2); + inline-size: calc(var(--spectrum-swatch-size) * var(--spectrum-swatch-rectangle-width-multiplier)); } /* Variant: Rounding - None */ @@ -301,7 +322,7 @@ .spectrum-Swatch-fill::before, &.is-selected .spectrum-Swatch-fill, &.is-selected .spectrum-Swatch-fill::before { - border-radius: 0; + border-radius: var(--spectrum-corner-radius-none); } } @@ -315,7 +336,7 @@ .spectrum-Swatch-fill::before, &.is-selected .spectrum-Swatch-fill, &.is-selected .spectrum-Swatch-fill::before { - border-radius: 100%; + border-radius: var(--mod-corner-radius-full, var(--spectrum-corner-radius-full)); } &.is-selected .spectrum-Swatch-fill { @@ -334,3 +355,46 @@ width var(--mod-animation-duration-100, var(--spectrum-animation-duration-100)) ease-in-out, height var(--mod-animation-duration-100, var(--spectrum-animation-duration-100)) ease-in-out; } + +/* Windows high contrast mode */ +@media (forced-colors: active) { + .spectrum-Swatch { + --mod-mixed-button-background: ButtonFace; + + --mod-add-button-background: ButtonFace; + --mod-add-button-background-hover: ButtonText; + --mod-add-button-background-down: ButtonText; + + --highcontrast-swatch-disabled-icon-color: GrayText; + --highcontrast-swatch-focus-indicator-color: ButtonText; + --highcontrast-swatch-background-color-selected: ButtonFace; + --highcontrast-swatch-border-color-selected: Highlight; + --highcontrast-swatch-border-color: ButtonText; + --highcontrast-swatch-fill-foreground-color: ButtonText; + + .spectrum-Swatch-fill { + forced-color-adjust: none; + } + + &.is-mixedValue { + --highcontrast-swatch-icon-color: ButtonFace; + } + + &.is-addSwatch { + &:hover, + &:active { + --highcontrast-swatch-icon-color: ButtonFace; + } + + &.is-keyboardFocused, + &:focus-visible { + --highcontrast-swatch-icon-color: ButtonFace; + } + } + + &[disabled], + &.is-disabled { + --highcontrast-swatch-border-color: GrayText; + } + } +} diff --git a/components/swatch/stories/swatch.stories.js b/components/swatch/stories/swatch.stories.js index d3d1b44b1c2..9df3a3a02f7 100644 --- a/components/swatch/stories/swatch.stories.js +++ b/components/swatch/stories/swatch.stories.js @@ -1,6 +1,6 @@ import { Sizes } from "@spectrum-css/preview/decorators"; import { disableDefaultModes } from "@spectrum-css/preview/modes"; -import { isDisabled, isSelected, size } from "@spectrum-css/preview/types"; +import { isDisabled, isHovered, isActive, isKeyboardFocused, isSelected, size } from "@spectrum-css/preview/types"; import metadata from "../dist/metadata.json"; import packageJson from "../package.json"; import { SwatchGroup } from "./swatch.test.js"; @@ -31,18 +31,30 @@ export default { rounding: { name: "Rounding", description: "The amount of corner rounding for a swatch.", - defaultValue: "regular", + defaultValue: "partial", type: { name: "string" }, table: { type: { summary: "string", required: true }, category: "Component", - defaultValue: { summary: "regular", }, + defaultValue: { summary: "partial", }, }, - options: ["none", "regular", "full"], + options: ["partial", "none", "full"], control: "select", }, - isDisabled, + isDisabled: { + ...isDisabled, + if: { arg: "isAddSwatch", truthy: false }, + }, isSelected, + isHovered: { + ...isHovered, + if: { arg: "isAddSwatch", truthy: true }, + }, + isActive: { + ...isActive, + if: { arg: "isAddSwatch", truthy: true }, + }, + isKeyboardFocused, borderStyle: { name: "Border style", type: { name: "string" }, @@ -85,6 +97,18 @@ export default { category: "Component", }, control: "boolean", + if: { arg: "isAddSwatch", truthy: false }, + }, + isAddSwatch: { + name: "Add swatch", + description: "A swatch that allows a user to add a new value.", + type: { name: "boolean" }, + table: { + type: { summary: "boolean" }, + category: "Component", + }, + control: "boolean", + if: { arg: "isMixedValue", truthy: false }, }, }, args: { @@ -92,11 +116,15 @@ export default { size: "m", isSelected: false, isDisabled: false, - rounding: "regular", + isHovered: false, + isActive: false, + isKeyboardFocused: false, + rounding: "partial", swatchColor: "rgb(174, 216, 230)", borderStyle: "default", shape: "square", isMixedValue: false, + isAddSwatch: false, }, parameters: { design: { @@ -221,6 +249,22 @@ MixedValue.parameters = { chromatic: { disableSnapshot: true }, }; +/** + * When a swatch allows a user to add a new value, the preview shows a `gray-50` fill and an add UI icon. + */ +export const AddSwatch = (args, context) => Sizes({ + Template: DisabledGroup, + withHeading: false, + ...args, +}, context); +AddSwatch.args = { + isAddSwatch: true, +}; +AddSwatch.tags = ["!dev"]; +AddSwatch.parameters = { + chromatic: { disableSnapshot: true }, +}; + export const Gradient = Template.bind({}); Gradient.args = { swatchColor: "linear-gradient(to right, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0) 100%)", diff --git a/components/swatch/stories/swatch.test.js b/components/swatch/stories/swatch.test.js index a441952d391..89f8f89b69e 100644 --- a/components/swatch/stories/swatch.test.js +++ b/components/swatch/stories/swatch.test.js @@ -32,6 +32,14 @@ export const Swatches = (args, context) => { ...args, isMixedValue: true, }, context), + Template({ + ...args, + isDisabled: true, + }, context), + Template({ + ...args, + isAddSwatch: true, + }, context), Template({ ...args, swatchColor: undefined, @@ -61,6 +69,10 @@ export const SwatchGroup = Variants({ testHeading: "No rounding", rounding: "none" }, + { + testHeading: "Partial rounding", + rounding: "partial" + }, { testHeading: "Full rounding", rounding: "full" @@ -93,22 +105,41 @@ export const SwatchGroup = Variants({ testHeading: "Mixed value", isMixedValue: true, }, - ], - stateData: [ { - testHeading: "Disabled", - isDisabled: true, + testHeading: "Add", + isAddSwatch: true, }, + ], + stateData: [ { testHeading: "Empty", swatchColor: undefined, imageUrl: undefined, isMixedValue: false, + isAddSwatch: false, borderStyle: "default", }, { testHeading: "Selected", isSelected: true, }, + { + testHeading: "Keyboard focus", + isKeyboardFocused: true, + }, + { + testHeading: "Disabled", + isDisabled: true, + }, + { + testHeading: "Hovered", + isHovered: true, + include: ["Add"] + }, + { + testHeading: "Active", + isActive: true, + include: ["Add"] + }, ] }); diff --git a/components/swatch/stories/template.js b/components/swatch/stories/template.js index bcf81178f6d..7c4f0291313 100644 --- a/components/swatch/stories/template.js +++ b/components/swatch/stories/template.js @@ -17,9 +17,13 @@ export const Template = ({ shape = "square", imageUrl, isMixedValue = false, + isAddSwatch = false, isSelected = false, isDisabled = false, - rounding = "regular", + isHovered = false, + isActive = false, + isKeyboardFocused = false, + rounding = "partial", customClasses = [], swatchColor, customStyles = {}, @@ -31,11 +35,19 @@ export const Template = ({ case "none": borderStyle = "noBorder"; break; + case "border": + borderStyle = "border"; + break; case "light": borderStyle = "lightBorder"; break; } + let pickedColor = swatchColor; + + if (isMixedValue) pickedColor = "var(--spectrum-gray-25)"; + if (isAddSwatch) pickedColor = undefined; + return html`
({ ...a, [c]: true }), {}), @@ -57,7 +73,7 @@ export const Template = ({ ?disabled=${isDisabled} id=${ifDefined(id)} style=${ifDefined(styleMap({ - "--spectrum-picked-color": isMixedValue ? "var(--spectrum-gray-50)" : swatchColor, + "--spectrum-picked-color": pickedColor, ...customStyles, }))} tabindex="0" @@ -72,7 +88,7 @@ export const Template = ({ updateArgs({ isSelected: !isSelected }); }} > - ${when((typeof imageUrl !== "undefined") && !isDisabled && !isMixedValue, () => html` + ${when((typeof imageUrl !== "undefined") && !isDisabled && !isMixedValue && !isAddSwatch, () => html` ${when(imageUrl, () => html`
@@ -104,7 +120,7 @@ export const Template = ({ `] : []), ...(isMixedValue ? [Icon({ - customClasses: [`${rootClass}-mixedValueIcon`], + customClasses: [`${rootClass}-icon`], setName: "ui", iconName: "Dash" + ({ xs: "75", @@ -114,6 +130,13 @@ export const Template = ({ }[size] || "100"), useRef: false, }, context)] : []), + ...(isAddSwatch ? [Icon({ + customClasses: [`${rootClass}-icon`], + setName: "workflow", + size, + iconName: "Add", + useRef: false, + }, context)] : []), ] })} ` diff --git a/components/swatchgroup/dist/metadata.json b/components/swatchgroup/dist/metadata.json index 24e3423ca5d..771036e4923 100644 --- a/components/swatchgroup/dist/metadata.json +++ b/components/swatchgroup/dist/metadata.json @@ -2,20 +2,19 @@ "sourceFile": "index.css", "selectors": [ ".spectrum-SwatchGroup", - ".spectrum-SwatchGroup--compact", + ".spectrum-SwatchGroup--sizeL", + ".spectrum-SwatchGroup--sizeM", ".spectrum-SwatchGroup--spacious" ], "modifiers": [ - "--mod-swatchgroup-spacing-compact", - "--mod-swatchgroup-spacing-regular", - "--mod-swatchgroup-spacing-spacious" + "--mod-swatch-group-spacing-spacious", + "--mod-swatchgroup-spacing" ], - "component": ["--spectrum-swatchgroup-spacing"], - "global": [ - "--spectrum-spacing-100", - "--spectrum-spacing-50", - "--spectrum-spacing-75" + "component": [ + "--spectrum-swatch-group-spacing-spacious", + "--spectrum-swatchgroup-spacing" ], + "global": ["--spectrum-spacing-100", "--spectrum-spacing-75"], "passthroughs": [], "high-contrast": [] } diff --git a/components/swatchgroup/index.css b/components/swatchgroup/index.css index 78485c77529..ea3471b7823 100644 --- a/components/swatchgroup/index.css +++ b/components/swatchgroup/index.css @@ -1,5 +1,5 @@ /*! - * Copyright 2024 Adobe. All rights reserved. + * 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 @@ -13,24 +13,27 @@ .spectrum-SwatchGroup { --spectrum-swatchgroup-spacing: var(--spectrum-spacing-75); +} +.spectrum-SwatchGroup { display: inline-flex; flex-flow: row wrap; align-items: flex-start; justify-content: flex-start; + gap: var(--mod-swatchgroup-spacing, var(--spectrum-swatchgroup-spacing)); +} - /* Regular (Default) */ - gap: var(--mod-swatchgroup-spacing-regular, var(--spectrum-swatchgroup-spacing)); +/* Spacious */ +.spectrum-SwatchGroup--spacious { + --mod-swatchgroup-spacing: var(--mod-swatch-group-spacing-spacious, var(--spectrum-swatch-group-spacing-spacious)); } -/* Compact */ -.spectrum-SwatchGroup--compact { - --mod-swatchgroup-spacing-regular: var(--mod-swatchgroup-spacing-compact); - --spectrum-swatchgroup-spacing: var(--spectrum-spacing-50); +/* Medium */ +.spectrum-SwatchGroup--sizeM { + --spectrum-swatchgroup-spacing: var(--spectrum-spacing-100); } -/* Spacious */ -.spectrum-SwatchGroup--spacious { - --mod-swatchgroup-spacing-regular: var(--mod-swatchgroup-spacing-spacious); +/* Large */ +.spectrum-SwatchGroup--sizeL { --spectrum-swatchgroup-spacing: var(--spectrum-spacing-100); } diff --git a/components/swatchgroup/stories/swatchgroup.stories.js b/components/swatchgroup/stories/swatchgroup.stories.js index 2a842f06695..bbe41a4d981 100644 --- a/components/swatchgroup/stories/swatchgroup.stories.js +++ b/components/swatchgroup/stories/swatchgroup.stories.js @@ -11,12 +11,6 @@ import { RoundingTemplate, Template } from "./template.js"; * * ## Usage notes * - * ### Corner rounding in swatch groups - * - * A corner rounding of “none” (`.spectrum-Swatch--roundingNone` class) should be used in a swatch group in order to help minimize the Hermann grid illusion that happens at the intersections of the white space within the group. - * - * The only exception is when a swatch group only takes up a single row. In that case, use any of the rounding options. - * * ### Apply border to low-contrast swatches only * * When swatches within a swatch group have low contrast (below 3:1 contrast with the background), they have a less prominent border compared to a single swatch component used by itself, and should have the `.spectrum-Swatch--lightBorder` class. This reduces the likelihood of the UI interfering with color perception and comparisons. Otherwise, swatches within a swatch group that meet contrast should have the `.spectrum-Swatch--noBorder` class. @@ -25,7 +19,7 @@ import { RoundingTemplate, Template } from "./template.js"; * * ### Density * - * Swatch groups come in 3 densities: regular (default), compact, and spacious. Compact and spacious densities retain the same swatch size as regular density, but have less or more padding between each swatch, respectively. + * Swatch groups come in several densities: regular (default), spacious, medium and large. Each density retains the same swatch size, but have less or more padding between each swatch, respectively. */ export default { title: "Swatch group", @@ -36,7 +30,10 @@ export default { shape: { table: { disable: true } }, imageUrl: { table: { disable: true } }, isMixedValue: { table: { disable: true } }, - gradient: { table: { disable: true } }, + isKeyboardFocused: { table: { disable: true } }, + isDisabled: { table: { disable: true } }, + isSelected: { table: { disable: true } }, + isAddSwatch: { table: { disable: true } }, density: { name: "Density", type: { name: "string" }, @@ -44,7 +41,7 @@ export default { type: { summary: "string" }, category: "Component", }, - options: ["regular", "compact", "spacious"], + options: ["regular", "spacious", "sizeM", "sizeL"], control: "select", }, items: { @@ -55,16 +52,6 @@ export default { name: "Container width", table: { disable: true }, }, - rounding: { - ...Swatch.argTypes.rounding, - description: "Only use rounded swatches if there is a single row.", - defaultValue: "none", - table: { - type: { summary: "string", required: true }, - category: "Component", - defaultValue: { summary: "none", }, - }, - }, borderStyle: { ...Swatch.argTypes.borderStyle, defaultValue: "noBorder", @@ -74,18 +61,15 @@ export default { category: "Component", defaultValue: { summary: "noBorder" }, }, - options: ["noBorder", "lightBorder"], + if: { arg: "isSelected", truthy: false }, + options: ["noBorder", "border", "lightBorder"], }, }, args: { rootClass: "spectrum-SwatchGroup", - size: "m", density: "regular", - rounding: "none", borderStyle: "noBorder", containerWidth: "200px", - isDisabled: false, - isSelected: false, items: [ {swatchColor: "rgb(184, 109, 70)",}, {swatchColor: "rgb(240, 56, 35)",}, @@ -128,15 +112,15 @@ export const Default = SwatchgroupGroup.bind({}); Default.args = {}; // ********* DOCS ONLY ********* // -export const Compact = Template.bind({}); -Compact.args = { - density: "compact", +export const Medium = Template.bind({}); +Medium.args = { + density: "sizeM", }; -Compact.tags = ["!dev"]; -Compact.parameters = { +Medium.tags = ["!dev"]; +Medium.parameters = { chromatic: { disableSnapshot: true }, }; -Compact.storyName = "Density - Compact"; +Medium.storyName = "Density - Medium"; export const Spacious = Template.bind({}); Spacious.args = { @@ -214,6 +198,16 @@ WithLightBorder.parameters = { chromatic: { disableSnapshot: true }, }; +export const WithBorder = Template.bind({}); +WithBorder.args = { + borderStyle: "border", +}; +WithBorder.tags = ["!dev"]; +WithBorder.storyName = "With border"; +WithBorder.parameters = { + chromatic: { disableSnapshot: true }, +}; + // ********* VRT ONLY ********* // export const WithForcedColors = SwatchgroupGroup.bind({}); WithForcedColors.tags = ["!autodocs", "!dev"]; diff --git a/components/swatchgroup/stories/swatchgroup.test.js b/components/swatchgroup/stories/swatchgroup.test.js index fb182c67163..f375947784f 100644 --- a/components/swatchgroup/stories/swatchgroup.test.js +++ b/components/swatchgroup/stories/swatchgroup.test.js @@ -7,14 +7,18 @@ export const SwatchgroupGroup = Variants({ { testHeading: "Default", }, - { - testHeading: "Compact", - density: "compact", - }, { testHeading: "Spacious", density: "spacious", }, + { + testHeading: "Medium", + density: "sizeM", + }, + { + testHeading: "Large", + density: "sizeL", + }, { testHeading: "Full rounding", rounding: "full", @@ -23,6 +27,10 @@ export const SwatchgroupGroup = Variants({ testHeading: "Regular rounding", rounding: "regular", }, + { + testHeading: "With borders", + borderStyle: "border", + }, { testHeading: "With light borders", borderStyle: "lightBorder", diff --git a/components/swatchgroup/stories/template.js b/components/swatchgroup/stories/template.js index 01c059998bd..9f4c76ea1f4 100644 --- a/components/swatchgroup/stories/template.js +++ b/components/swatchgroup/stories/template.js @@ -12,13 +12,11 @@ export const Template = ({ customClasses = [], size = "m", density = "regular", - rounding = "regular", + rounding = "partial", borderStyle = "noBorder", containerWidth, items = [], customStyles = {}, - isDisabled =false, - isSelected = false, id = getRandomId("swatchgroup"), } = {}, context = {}) => html`
Swatch({ size, rounding, - isDisabled, - isSelected, borderStyle, ...swatch, }, context))} @@ -62,11 +58,11 @@ export const RoundingTemplate = (args, context) => Container({ }, context)} ${Container({ withBorder: false, - heading: "Regular", + heading: "Partial", containerStyles: {"gap": "8px",}, content: Template({ ...args, - rounding: "regular", + rounding: "partial", }, context) }, context)} ${Container({ diff --git a/tokens/custom/dark-vars.css b/tokens/custom/dark-vars.css index df53227a159..fbce8adb353 100644 --- a/tokens/custom/dark-vars.css +++ b/tokens/custom/dark-vars.css @@ -1,5 +1,5 @@ /*! - * Copyright 2024 Adobe. All rights reserved. + * 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 @@ -24,19 +24,19 @@ --spectrum-assetcard-selectionindicator-background-color-ordered: var(--spectrum-blue-800); --spectrum-assestcard-focus-indicator-color: var(--spectrum-blue-700); - --spectrum-assetlist-item-background-color-selected-hover: rgba(var(--spectrum-blue-800-rgb), 0.25); - --spectrum-assetlist-item-background-color-selected: rgba(var(--spectrum-blue-800-rgb), 0.15); + --spectrum-assetlist-item-background-color-selected-hover: rgb(var(--spectrum-blue-800-rgb), 0.25); + --spectrum-assetlist-item-background-color-selected: rgb(var(--spectrum-blue-800-rgb), 0.15); --spectrum-assetlist-border-color-key-focus: var(--spectrum-blue-700); --spectrum-badge-label-icon-color-primary: var(--spectrum-black); - --spectrum-calendar-day-background-color-selected: rgba(var(--spectrum-blue-800-rgb), 0.15); - --spectrum-calendar-day-background-color-hover: rgba(var(--spectrum-white-rgb), 0.07); - --spectrum-calendar-day-today-background-color-selected-hover: rgba(var(--spectrum-blue-800-rgb), 0.25); - --spectrum-calendar-day-background-color-selected-hover: rgba(var(--spectrum-blue-800-rgb), 0.25); + --spectrum-calendar-day-background-color-selected: rgb(var(--spectrum-blue-800-rgb), 0.15); + --spectrum-calendar-day-background-color-hover: rgb(var(--spectrum-white-rgb), 0.07); + --spectrum-calendar-day-today-background-color-selected-hover: rgb(var(--spectrum-blue-800-rgb), 0.25); + --spectrum-calendar-day-background-color-selected-hover: rgb(var(--spectrum-blue-800-rgb), 0.25); --spectrum-calendar-day-background-color-down: var(--spectrum-transparent-white-200); - --spectrum-calendar-day-background-color-cap-selected: rgba(var(--spectrum-blue-800-rgb), 0.25); - --spectrum-calendar-day-background-color-key-focus: rgba(var(--spectrum-white-rgb), 0.07); + --spectrum-calendar-day-background-color-cap-selected: rgb(var(--spectrum-blue-800-rgb), 0.25); + --spectrum-calendar-day-background-color-key-focus: rgb(var(--spectrum-white-rgb), 0.07); --spectrum-calendar-day-border-color-key-focus: var(--spectrum-blue-700); --spectrum-card-selected-background-color-rgb: var(--spectrum-blue-500-rgb); @@ -57,9 +57,8 @@ --spectrum-steplist-current-marker-color-key-focus: var(--spectrum-blue-700); - --spectrum-swatch-border-color: rgb(255 255 255 / 51%); - --spectrum-swatch-border-color-light: rgb(255 255 255 / 20%); + --spectrum-swatchgroup-border-color: rgb(255 255 255 / 20%); - --spectrum-treeview-item-background-color-quiet-selected: rgba(var(--spectrum-gray-900-rgb), 0.07); - --spectrum-treeview-item-background-color-selected: rgba(var(--spectrum-blue-800-rgb), 0.15); + --spectrum-treeview-item-background-color-quiet-selected: rgb(var(--spectrum-gray-900-rgb), 0.07); + --spectrum-treeview-item-background-color-selected: rgb(var(--spectrum-blue-800-rgb), 0.15); } diff --git a/tokens/custom/light-vars.css b/tokens/custom/light-vars.css index 131f3951b10..0355d7438e8 100644 --- a/tokens/custom/light-vars.css +++ b/tokens/custom/light-vars.css @@ -1,5 +1,5 @@ /*! - * Copyright 2024 Adobe. All rights reserved. + * 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 @@ -22,19 +22,19 @@ --spectrum-assetcard-selectionindicator-background-color-ordered: var(--spectrum-blue-900); --spectrum-assestcard-focus-indicator-color: var(--spectrum-blue-800); - --spectrum-assetlist-item-background-color-selected-hover: rgba(var(--spectrum-blue-900-rgb), 0.2); - --spectrum-assetlist-item-background-color-selected: rgba(var(--spectrum-blue-900-rgb), 0.1); + --spectrum-assetlist-item-background-color-selected-hover: rgb(var(--spectrum-blue-900-rgb), 0.2); + --spectrum-assetlist-item-background-color-selected: rgb(var(--spectrum-blue-900-rgb), 0.1); --spectrum-assetlist-border-color-key-focus: var(--spectrum-blue-800); --spectrum-badge-label-icon-color-primary: var(--spectrum-white); - --spectrum-calendar-day-background-color-selected: rgba(var(--spectrum-blue-900-rgb), 0.1); - --spectrum-calendar-day-background-color-hover: rgba(var(--spectrum-black-rgb), 0.06); - --spectrum-calendar-day-today-background-color-selected-hover: rgba(var(--spectrum-blue-900-rgb), 0.2); - --spectrum-calendar-day-background-color-selected-hover: rgba(var(--spectrum-blue-900-rgb), 0.2); + --spectrum-calendar-day-background-color-selected: rgb(var(--spectrum-blue-900-rgb), 0.1); + --spectrum-calendar-day-background-color-hover: rgb(var(--spectrum-black-rgb), 0.06); + --spectrum-calendar-day-today-background-color-selected-hover: rgb(var(--spectrum-blue-900-rgb), 0.2); + --spectrum-calendar-day-background-color-selected-hover: rgb(var(--spectrum-blue-900-rgb), 0.2); --spectrum-calendar-day-background-color-down: var(--spectrum-transparent-black-200); - --spectrum-calendar-day-background-color-cap-selected: rgba(var(--spectrum-blue-900-rgb), 0.2); - --spectrum-calendar-day-background-color-key-focus: rgba(var(--spectrum-black-rgb), 0.06); + --spectrum-calendar-day-background-color-cap-selected: rgb(var(--spectrum-blue-900-rgb), 0.2); + --spectrum-calendar-day-background-color-key-focus: rgb(var(--spectrum-black-rgb), 0.06); --spectrum-calendar-day-border-color-key-focus: var(--spectrum-blue-800); --spectrum-card-selected-background-color-rgb: var(--spectrum-blue-900-rgb); @@ -55,9 +55,8 @@ --spectrum-steplist-current-marker-color-key-focus: var(--spectrum-blue-800); - --spectrum-swatch-border-color: rgb(0 0 0 / 51%); - --spectrum-swatch-border-color-light: rgb(0 0 0 / 20%); + --spectrum-swatchgroup-border-color: rgb(255 255 255 / 20%); - --spectrum-treeview-item-background-color-quiet-selected: rgba(var(--spectrum-gray-900-rgb), 0.06); - --spectrum-treeview-item-background-color-selected: rgba(var(--spectrum-blue-900-rgb), 0.1); + --spectrum-treeview-item-background-color-quiet-selected: rgb(var(--spectrum-gray-900-rgb), 0.06); + --spectrum-treeview-item-background-color-selected: rgb(var(--spectrum-blue-900-rgb), 0.1); }