From 5731baee72b654e53bd1c017933404664640322f Mon Sep 17 00:00:00 2001 From: Josh Winn <965114+jawinn@users.noreply.github.com> Date: Wed, 1 May 2024 14:30:28 -0400 Subject: [PATCH] feat(button): migrate to Spectrum 2 (#2600) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(button): spectrum 2 styles and cleanup Spectrum 2 changes to CSS: - integrate themes css into main css - use s2 corner rounding - use s2 colors Cleanup items of note: - make medium size the default - consolidate and organize focus indicator styles. Some declarations were repeated. - Rename mod for font weight that was referencing a global token instead of a component specific name. - simplify repetitive disabled custom properties - removed some unused css; static variant declarations at the end of the file were being overridden by more specific styles - remove unused is-selected, emphasized, and quiet classes that are not used on this component - remove the spectrum-Button--fill class. it was already the default. * fix(button): high contrast - ensure matching color pairs for accent Ensures that a matching background and foreground color pair is used for the high contrast colors, for Accent hover, down, and focus. Changes the content color to HighlightText to ensure contrast when these have a background set to Highlight. * docs(button): update documentation and storybook for s2 - Some improvements and additions to the spectrum 2 release notes. - Updates migration guide notes to include version and dates for the previous notes. - Removes spectrum-Button--sizeM class from examples. Excludes the spectrum-Button--sizeM class in the storybook template. - Removes medium size class from storybook - Fixes default flex alignment stretching buttons vertically in Storybook to the tallest button. * fix(button): calculate corner rounding to support wrapping design Calculate corner rounding based on the component height, so that the rounding looks correct when there is wrapping text. Otherwise, when the button wraps, it has too much rounding as compared to the design when using the corner-radius-full token. * feat(button): outline option removals and use accent as the default Removes the outline option for the accent and negative variants, and makes sure that the accent variant is the default. == outline option removal == Per design feedback and updated design spec changelog, the outline treatment (style) is no longer supported for the Accent and Negative color variants: "Outline buttons are no longer available in accent and negative options — use the filled variant instead" This removes their CSS, lists the change in the migration notes, and disables the treatment control for the Accent and Negative stories. It also removes the outline example in the template for those two stories. == use accent as the default == Use accent styles for the default button when there is no variant class applied, to match the default defined on the guidelines. * fix(button): additional s2 style adjustments and organization - make usage of edge to visual values consistent - use full corner rounding on icon-only variant, which does not need to account for wrapping text - correct static white secondary outline background color, per PR review - chore: apply linter formatting * docs(button): custom mdx docs page Create an MDX "Docs" page that works as a replacement for the YML docs pages, and covers the important Button options from there and the guidelines. Adds the tag "is-hidden-story" for excluding Storybook sidebar items. * chore(button): add changeset * build(button): use beta version of commons dependency Since the commons version on main was updated to 10.0, the Button started building with the wrong version of commons when importing basebutton.css and listing mods that have been removed in the version of commons in the spectrum-two branch. * chore(button): clear up linter warnings Fixes warnings and errors from stylelint and eslint. * fix(button): correct focus indicator rounding and basebutton mod The focus indicator rounding needed an additional calc in order to have the correct rounding. While testing --mod-button-focus-ring-gap and some other mods, it was also noticed that a declaration being imported from basebutton was causing some of the mod names to be different and the mod to not work correctly (basebutton is generating a selector for the margin of .spectrum-Button:focus-visible::after). --- .changeset/nine-kings-repair.md | 15 + .storybook/assets/base.css | 8 + .storybook/main.js | 1 + .storybook/manager.js | 2 +- components/button/index.css | 495 +++++++++++++----- components/button/metadata/button-accent.yml | 87 +-- .../button/metadata/button-negative.yml | 90 ++-- components/button/metadata/button-pending.yml | 24 +- components/button/metadata/button-primary.yml | 90 ++-- .../button/metadata/button-secondary.yml | 90 ++-- .../button/metadata/button-staticcolor.yml | 178 ++++--- components/button/metadata/mods.md | 94 ++-- components/button/package.json | 2 +- components/button/stories/button.mdx | 101 ++++ components/button/stories/button.stories.js | 480 +++++++++++------ components/button/stories/template.js | 13 +- components/button/themes/express.css | 37 -- components/button/themes/spectrum.css | 462 ---------------- yarn.lock | 4 +- 19 files changed, 1146 insertions(+), 1127 deletions(-) create mode 100644 .changeset/nine-kings-repair.md create mode 100644 components/button/stories/button.mdx delete mode 100644 components/button/themes/express.css delete mode 100644 components/button/themes/spectrum.css diff --git a/.changeset/nine-kings-repair.md b/.changeset/nine-kings-repair.md new file mode 100644 index 00000000000..0714bbb8274 --- /dev/null +++ b/.changeset/nine-kings-repair.md @@ -0,0 +1,15 @@ +--- +"@spectrum-css/button": major +--- + +#### Spectrum 2 migration +Button now uses Spectrum 2 tokens and specifications, which includes many color changes to all variants. A few other notable changes: +- Outline buttons are no longer available in accent and negative options — use the filled variant instead. +- Medium size is now the default. The class `.spectrum-Button--sizeM` is now unnecessary for this size, and has been removed. +- The `.spectrum-Button--fill` class is no longer needed and has been removed. + +The following `--mod` custom properties have been renamed: +- `--mod-line-height-100` has been renamed to `--mod-button-line-height` +- `--mod-sans-font-family-stack` has been renamed to `--mod-button-font-family` +- `--mod-animation-duration-100` has been renamed to `--mod-button-animation-duration` +- `--mod-bold-font-weight` has been renamed to `--mod-button-font-weight` diff --git a/.storybook/assets/base.css b/.storybook/assets/base.css index d261f565d01..2f123142985 100644 --- a/.storybook/assets/base.css +++ b/.storybook/assets/base.css @@ -36,6 +36,14 @@ body { -webkit-tap-highlight-color: rgba(0, 0, 0, 0%); } +.spectrum .spectrum-examples-static-black { + background: var(--spectrum-examples-gradient-static-black); +} + +.spectrum .spectrum-examples-static-white { + background: var(--spectrum-examples-gradient-static-white) +} + /* Hide the SVG elements that only include references */ svg:has(symbol):not(:has(use)) { display: none; diff --git a/.storybook/main.js b/.storybook/main.js index 8a024ddafa8..d6e748a3330 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -10,6 +10,7 @@ const componentPkgs = readdirSync(componentsPath, { module.exports = { stories: [ + "../components/*/stories/*.mdx", "../components/*/stories/*.stories.js", "./guides/*.mdx", "./foundations/*/*.mdx", diff --git a/.storybook/manager.js b/.storybook/manager.js index fb843f695a3..791ceaca79f 100644 --- a/.storybook/manager.js +++ b/.storybook/manager.js @@ -50,7 +50,7 @@ addons.setConfig({ sidebar: { showRoots: false, filters: { - patterns: (item) => !(item.id.includes('forced-colors') || item.tags.includes('foundation')), + patterns: (item) => !item.id.includes('forced-colors') && ['foundation','is-hidden-story'].every((tag) => !item.tags.includes(tag)), } }, }); diff --git a/components/button/index.css b/components/button/index.css index 9970e58cecd..5da0ec6c1a8 100644 --- a/components/button/index.css +++ b/components/button/index.css @@ -10,38 +10,53 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -@import "./themes/express.css"; @import "@spectrum-css/commons/basebutton.css"; -/* default for all buttons */ .spectrum-Button { --spectrum-button-animation-duration: var(--spectrum-animation-duration-100); - --spectrum-button-border-radius: var(--spectrum-corner-radius-100); - --spectrum-button-border-width: var(--spectrum-border-width-200); - --spectrum-button-line-height: 1.2; /* Hack to keep buttons at 32px */ --spectrum-button-focus-ring-gap: var(--spectrum-focus-indicator-gap); - --spectrum-button-focus-ring-border-radius: calc(var(--spectrum-button-border-radius) + var(--spectrum-button-focus-ring-gap)); --spectrum-button-focus-ring-thickness: var(--spectrum-focus-indicator-thickness); --spectrum-button-focus-indicator-color: var(--spectrum-focus-indicator-color); - --spectrum-button-intended-icon-size: var(--spectrum-workflow-icon-size-50); + + --spectrum-button-min-width: calc(var(--spectrum-component-height-100) * var(--spectrum-button-minimum-width-multiplier)); + --spectrum-button-height: var(--spectrum-component-height-100); + + --spectrum-button-border-radius: calc(var(--spectrum-button-height) / 2); + --spectrum-button-border-width: var(--spectrum-border-width-200); + + /* @todo set line-height using font size specific line-height tokens when they are finalized along with the new variable font. */ + --spectrum-button-line-height: 1.2; + --spectrum-button-font-weight: var(--spectrum-bold-font-weight); + --spectrum-button-font-size: var(--spectrum-font-size-100); + + --spectrum-button-edge-to-visual: calc(var(--spectrum-component-pill-edge-to-visual-100) - var(--mod-button-border-width, var(--spectrum-button-border-width))); + --spectrum-button-edge-to-visual-only: calc(var(--spectrum-component-pill-edge-to-visual-only-100) - var(--mod-button-border-width, var(--spectrum-button-border-width))); + --spectrum-button-edge-to-text: calc(var(--spectrum-component-pill-edge-to-text-100) - var(--mod-button-border-width, var(--spectrum-button-border-width))); + --spectrum-button-padding-label-to-icon: var(--spectrum-text-to-visual-100); + --spectrum-button-top-to-text: var(--spectrum-button-top-to-text-medium); + --spectrum-button-bottom-to-text: var(--spectrum-button-bottom-to-text-medium); + --spectrum-button-top-to-icon: var(--spectrum-component-top-to-workflow-icon-100); + --spectrum-button-intended-icon-size: var(--spectrum-workflow-icon-size-100); --mod-progress-circle-position: absolute; - /* stylelint-disable-next-line spectrum-tools/no-unknown-custom-properties */ + /* stylelint-disable-next-line spectrum-tools/no-unknown-custom-properties -- height and width are set by implementations */ --spectrum-downstate-perspective: max(var(--spectrum-downstate-height), var(--spectrum-downstate-width) * var(--spectrum-component-size-width-ratio-down)); + + &.spectrum-Button--iconOnly { + --spectrum-button-border-radius: var(--spectrum-corner-radius-full); + } } .spectrum-Button--sizeS { --spectrum-button-min-width: calc(var(--spectrum-component-height-75) * var(--spectrum-button-minimum-width-multiplier)); - - --spectrum-button-border-radius: var(--spectrum-component-pill-edge-to-text-75); --spectrum-button-height: var(--spectrum-component-height-75); --spectrum-button-font-size: var(--spectrum-font-size-75); - --spectrum-button-edge-to-visual: calc(var(--spectrum-component-pill-edge-to-visual-75) - var(--spectrum-button-border-width)); - --spectrum-button-edge-to-visual-only: var(--spectrum-component-pill-edge-to-visual-only-75); - --spectrum-button-edge-to-text: calc(var(--spectrum-component-pill-edge-to-text-75) - var(--spectrum-button-border-width)); + --spectrum-button-edge-to-visual: calc(var(--spectrum-component-pill-edge-to-visual-75) - var(--mod-button-border-width, var(--spectrum-button-border-width))); + --spectrum-button-edge-to-visual-only: calc(var(--spectrum-component-pill-edge-to-visual-only-75) - var(--mod-button-border-width, var(--spectrum-button-border-width))); + --spectrum-button-edge-to-text: calc(var(--spectrum-component-pill-edge-to-text-75) - var(--mod-button-border-width, var(--spectrum-button-border-width))); --spectrum-button-padding-label-to-icon: var(--spectrum-text-to-visual-75); --spectrum-button-top-to-text: var(--spectrum-button-top-to-text-small); --spectrum-button-bottom-to-text: var(--spectrum-button-bottom-to-text-small); @@ -53,35 +68,15 @@ governing permissions and limitations under the License. } } -.spectrum-Button--sizeM { - --spectrum-button-min-width: calc(var(--spectrum-component-height-100) * var(--spectrum-button-minimum-width-multiplier)); - - --spectrum-button-border-radius: var(--spectrum-component-pill-edge-to-text-100); - --spectrum-button-height: var(--spectrum-component-height-100); - - --spectrum-button-font-size: var(--spectrum-font-size-100); - - --spectrum-button-edge-to-visual: calc(var(--spectrum-component-pill-edge-to-visual-100) - var(--spectrum-button-border-width)); - --spectrum-button-edge-to-visual-only: var(--spectrum-component-pill-edge-to-visual-only-100); - --spectrum-button-edge-to-text: calc(var(--spectrum-component-pill-edge-to-text-100) - var(--spectrum-button-border-width)); - --spectrum-button-padding-label-to-icon: var(--spectrum-text-to-visual-100); - --spectrum-button-top-to-text: var(--spectrum-button-top-to-text-medium); - --spectrum-button-bottom-to-text: var(--spectrum-button-bottom-to-text-medium); - --spectrum-button-top-to-icon: var(--spectrum-component-top-to-workflow-icon-100); - --spectrum-button-intended-icon-size: var(--spectrum-workflow-icon-size-100); -} - .spectrum-Button--sizeL { --spectrum-button-min-width: calc(var(--spectrum-component-height-200) * var(--spectrum-button-minimum-width-multiplier)); - - --spectrum-button-border-radius: var(--spectrum-component-pill-edge-to-text-200); --spectrum-button-height: var(--spectrum-component-height-200); --spectrum-button-font-size: var(--spectrum-font-size-200); - --spectrum-button-edge-to-visual: calc(var(--spectrum-component-pill-edge-to-visual-200) - var(--spectrum-button-border-width)); - --spectrum-button-edge-to-visual-only: var(--spectrum-component-pill-edge-to-visual-only-200); - --spectrum-button-edge-to-text: calc(var(--spectrum-component-pill-edge-to-text-200) - var(--spectrum-button-border-width)); + --spectrum-button-edge-to-visual: calc(var(--spectrum-component-pill-edge-to-visual-200) - var(--mod-button-border-width, var(--spectrum-button-border-width))); + --spectrum-button-edge-to-visual-only: calc(var(--spectrum-component-pill-edge-to-visual-only-200) - var(--mod-button-border-width, var(--spectrum-button-border-width))); + --spectrum-button-edge-to-text: calc(var(--spectrum-component-pill-edge-to-text-200) - var(--mod-button-border-width, var(--spectrum-button-border-width))); --spectrum-button-padding-label-to-icon: var(--spectrum-text-to-visual-200); --spectrum-button-top-to-text: var(--spectrum-button-top-to-text-large); --spectrum-button-bottom-to-text: var(--spectrum-button-bottom-to-text-large); @@ -91,15 +86,13 @@ governing permissions and limitations under the License. .spectrum-Button--sizeXL { --spectrum-button-min-width: calc(var(--spectrum-component-height-300) * var(--spectrum-button-minimum-width-multiplier)); - - --spectrum-button-border-radius: var(--spectrum-component-pill-edge-to-text-300); --spectrum-button-height: var(--spectrum-component-height-300); --spectrum-button-font-size: var(--spectrum-font-size-300); - --spectrum-button-edge-to-visual: calc(var(--spectrum-component-pill-edge-to-visual-300) - var(--spectrum-button-border-width)); - --spectrum-button-edge-to-visual-only: var(--spectrum-component-pill-edge-to-visual-only-300); - --spectrum-button-edge-to-text: calc(var(--spectrum-component-pill-edge-to-text-300) - var(--spectrum-button-border-width)); + --spectrum-button-edge-to-visual: calc(var(--spectrum-component-pill-edge-to-visual-300) - var(--mod-button-border-width, var(--spectrum-button-border-width))); + --spectrum-button-edge-to-visual-only: calc(var(--spectrum-component-pill-edge-to-visual-only-300) - var(--mod-button-border-width, var(--spectrum-button-border-width))); + --spectrum-button-edge-to-text: calc(var(--spectrum-component-pill-edge-to-text-300) - var(--mod-button-border-width, var(--spectrum-button-border-width))); --spectrum-button-padding-label-to-icon: var(--spectrum-text-to-visual-300); --spectrum-button-top-to-text: var(--spectrum-button-top-to-text-extra-large); --spectrum-button-bottom-to-text: var(--spectrum-button-bottom-to-text-extra-large); @@ -107,6 +100,235 @@ governing permissions and limitations under the License. --spectrum-button-intended-icon-size: var(--spectrum-workflow-icon-size-300); } +/* Variants and colors */ +.spectrum-Button { + --spectrum-button-content-color-default: var(--spectrum-white); + --spectrum-button-content-color-hover: var(--spectrum-white); + --spectrum-button-content-color-down: var(--spectrum-white); + --spectrum-button-content-color-focus: var(--spectrum-white); + + --spectrum-button-border-color-default: transparent; + --spectrum-button-border-color-hover: transparent; + --spectrum-button-border-color-down: transparent; + --spectrum-button-border-color-focus: transparent; + + --spectrum-button-background-color-disabled: var(--spectrum-disabled-background-color); + --spectrum-button-border-color-disabled: transparent; + --spectrum-button-content-color-disabled: var(--spectrum-disabled-content-color); + + &.spectrum-Button--outline { + --spectrum-button-background-color-disabled: transparent; + --spectrum-button-border-color-disabled: var(--spectrum-disabled-border-color); + --spectrum-button-content-color-disabled: var(--spectrum-disabled-content-color); + } + + /* ---- Accent ---- */ + /* Also shows as the default when a variant class is not used. */ + &.spectrum-Button--accent, + & { + --spectrum-button-background-color-default: var(--spectrum-accent-background-color-default); + --spectrum-button-background-color-hover: var(--spectrum-accent-background-color-hover); + --spectrum-button-background-color-down: var(--spectrum-accent-background-color-down); + --spectrum-button-background-color-focus: var(--spectrum-accent-background-color-key-focus); + } + + /* ---- Negative ---- */ + &.spectrum-Button--negative { + --spectrum-button-background-color-default: var(--spectrum-negative-background-color-default); + --spectrum-button-background-color-hover: var(--spectrum-negative-background-color-hover); + --spectrum-button-background-color-down: var(--spectrum-negative-background-color-down); + --spectrum-button-background-color-focus: var(--spectrum-negative-background-color-key-focus); + } + + /* ---- Primary ---- */ + &.spectrum-Button--primary { + --spectrum-button-background-color-default: var(--spectrum-neutral-background-color-default); + --spectrum-button-background-color-hover: var(--spectrum-neutral-background-color-hover); + --spectrum-button-background-color-down: var(--spectrum-neutral-background-color-down); + --spectrum-button-background-color-focus: var(--spectrum-neutral-background-color-key-focus); + + --spectrum-button-content-color-default: var(--spectrum-gray-25); + --spectrum-button-content-color-hover: var(--spectrum-gray-25); + --spectrum-button-content-color-down: var(--spectrum-gray-25); + --spectrum-button-content-color-focus: var(--spectrum-gray-25); + + &.spectrum-Button--outline { + --spectrum-button-background-color-default: transparent; + --spectrum-button-background-color-hover: var(--spectrum-gray-100); + --spectrum-button-background-color-down: var(--spectrum-gray-100); + --spectrum-button-background-color-focus: var(--spectrum-gray-100); + + --spectrum-button-border-color-default: var(--spectrum-gray-800); + --spectrum-button-border-color-hover: var(--spectrum-gray-900); + --spectrum-button-border-color-down: var(--spectrum-gray-900); + --spectrum-button-border-color-focus: var(--spectrum-gray-900); + + --spectrum-button-content-color-default: var(--spectrum-neutral-content-color-default); + --spectrum-button-content-color-hover: var(--spectrum-neutral-content-color-hover); + --spectrum-button-content-color-down: var(--spectrum-neutral-content-color-down); + --spectrum-button-content-color-focus: var(--spectrum-neutral-content-color-key-focus); + } + } + + /* ---- Secondary ---- */ + &.spectrum-Button--secondary { + --spectrum-button-background-color-default: var(--spectrum-gray-100); + --spectrum-button-background-color-hover: var(--spectrum-gray-200); + --spectrum-button-background-color-down: var(--spectrum-gray-200); + --spectrum-button-background-color-focus: var(--spectrum-gray-200); + + --spectrum-button-content-color-default: var(--spectrum-neutral-content-color-default); + --spectrum-button-content-color-hover: var(--spectrum-neutral-content-color-hover); + --spectrum-button-content-color-down: var(--spectrum-neutral-content-color-down); + --spectrum-button-content-color-focus: var(--spectrum-neutral-content-color-key-focus); + + &.spectrum-Button--outline { + --spectrum-button-background-color-default: transparent; + --spectrum-button-background-color-hover: var(--spectrum-gray-100); + --spectrum-button-background-color-down: var(--spectrum-gray-100); + --spectrum-button-background-color-focus: var(--spectrum-gray-100); + + --spectrum-button-border-color-default: var(--spectrum-gray-300); + --spectrum-button-border-color-hover: var(--spectrum-gray-400); + --spectrum-button-border-color-down: var(--spectrum-gray-400); + --spectrum-button-border-color-focus: var(--spectrum-gray-400); + + --spectrum-button-content-color-default: var(--spectrum-neutral-content-color-default); + --spectrum-button-content-color-hover: var(--spectrum-neutral-content-color-hover); + --spectrum-button-content-color-down: var(--spectrum-neutral-content-color-down); + --spectrum-button-content-color-focus: var(--spectrum-neutral-content-color-key-focus); + } + } + + /* ---- Static White ---- */ + &.spectrum-Button--staticWhite { + --spectrum-button-background-color-default: var(--spectrum-transparent-white-800); + --spectrum-button-background-color-hover: var(--spectrum-transparent-white-900); + --spectrum-button-background-color-down: var(--spectrum-transparent-white-900); + --spectrum-button-background-color-focus: var(--spectrum-transparent-white-900); + + --spectrum-button-content-color-default: var(--spectrum-black); + --spectrum-button-content-color-hover: var(--spectrum-black); + --spectrum-button-content-color-down: var(--spectrum-black); + --spectrum-button-content-color-focus: var(--spectrum-black); + + --spectrum-button-focus-indicator-color: var(--spectrum-static-white-focus-indicator-color); + + --spectrum-button-background-color-disabled: var(--spectrum-disabled-static-white-background-color); + --spectrum-button-border-color-disabled: transparent; + --spectrum-button-content-color-disabled: var(--spectrum-disabled-static-white-content-color); + + &.spectrum-Button--outline { + --spectrum-button-background-color-default: var(--spectrum-transparent-white-25); + --spectrum-button-background-color-hover: var(--spectrum-transparent-white-100); + --spectrum-button-background-color-down: var(--spectrum-transparent-white-100); + --spectrum-button-background-color-focus: var(--spectrum-transparent-white-100); + + --spectrum-button-border-color-default: var(--spectrum-transparent-white-800); + --spectrum-button-border-color-hover: var(--spectrum-transparent-white-900); + --spectrum-button-border-color-down: var(--spectrum-transparent-white-900); + --spectrum-button-border-color-focus: var(--spectrum-transparent-white-900); + + --spectrum-button-content-color-default: var(--spectrum-transparent-white-800); + --spectrum-button-content-color-hover: var(--spectrum-transparent-white-900); + --spectrum-button-content-color-down: var(--spectrum-transparent-white-900); + --spectrum-button-content-color-focus: var(--spectrum-transparent-white-900); + + --spectrum-button-background-color-disabled: var(--spectrum-transparent-white-25); + --spectrum-button-border-color-disabled: var(--spectrum-disabled-static-white-border-color); + --spectrum-button-content-color-disabled: var(--spectrum-disabled-static-white-content-color); + } + + &.spectrum-Button--secondary { + --spectrum-button-background-color-default: var(--spectrum-transparent-white-100); + --spectrum-button-background-color-hover: var(--spectrum-transparent-white-200); + --spectrum-button-background-color-down: var(--spectrum-transparent-white-200); + --spectrum-button-background-color-focus: var(--spectrum-transparent-white-200); + + --spectrum-button-content-color-default: var(--spectrum-transparent-white-800); + --spectrum-button-content-color-hover: var(--spectrum-transparent-white-900); + --spectrum-button-content-color-down: var(--spectrum-transparent-white-900); + --spectrum-button-content-color-focus: var(--spectrum-transparent-white-900); + + &.spectrum-Button--outline { + --spectrum-button-background-color-default: var(--spectrum-transparent-white-25); + --spectrum-button-background-color-hover: var(--spectrum-transparent-white-100); + --spectrum-button-background-color-down: var(--spectrum-transparent-white-100); + --spectrum-button-background-color-focus: var(--spectrum-transparent-white-100); + + --spectrum-button-border-color-default: var(--spectrum-transparent-white-300); + --spectrum-button-border-color-hover: var(--spectrum-transparent-white-400); + --spectrum-button-border-color-down: var(--spectrum-transparent-white-400); + --spectrum-button-border-color-focus: var(--spectrum-transparent-white-400); + } + } + } + + /* ---- Static Black ---- */ + &.spectrum-Button--staticBlack { + --spectrum-button-background-color-default: var(--spectrum-transparent-black-800); + --spectrum-button-background-color-hover: var(--spectrum-transparent-black-900); + --spectrum-button-background-color-down: var(--spectrum-transparent-black-900); + --spectrum-button-background-color-focus: var(--spectrum-transparent-black-900); + + --spectrum-button-content-color-default: var(--spectrum-white); + --spectrum-button-content-color-hover: var(--spectrum-white); + --spectrum-button-content-color-down: var(--spectrum-white); + --spectrum-button-content-color-focus: var(--spectrum-white); + + --spectrum-button-focus-indicator-color: var(--spectrum-static-black-focus-indicator-color); + + --spectrum-button-background-color-disabled: var(--spectrum-disabled-static-black-background-color); + --spectrum-button-border-color-disabled: transparent; + --spectrum-button-content-color-disabled: var(--spectrum-disabled-static-black-content-color); + + &.spectrum-Button--outline { + --spectrum-button-background-color-default: var(--spectrum-transparent-black-25); + --spectrum-button-background-color-hover: var(--spectrum-transparent-black-100); + --spectrum-button-background-color-down: var(--spectrum-transparent-black-100); + --spectrum-button-background-color-focus: var(--spectrum-transparent-black-100); + + --spectrum-button-border-color-default: var(--spectrum-transparent-black-800); + --spectrum-button-border-color-hover: var(--spectrum-transparent-black-900); + --spectrum-button-border-color-down: var(--spectrum-transparent-black-900); + --spectrum-button-border-color-focus: var(--spectrum-transparent-black-900); + + --spectrum-button-content-color-default: var(--spectrum-transparent-black-800); + --spectrum-button-content-color-hover: var(--spectrum-transparent-black-900); + --spectrum-button-content-color-down: var(--spectrum-transparent-black-900); + --spectrum-button-content-color-focus: var(--spectrum-transparent-black-900); + + --spectrum-button-background-color-disabled: transparent; + --spectrum-button-border-color-disabled: var(--spectrum-disabled-static-black-border-color); + --spectrum-button-content-color-disabled: var(--spectrum-disabled-static-black-content-color); + } + + &.spectrum-Button--secondary { + --spectrum-button-background-color-default: var(--spectrum-transparent-black-100); + --spectrum-button-background-color-hover: var(--spectrum-transparent-black-200); + --spectrum-button-background-color-down: var(--spectrum-transparent-black-200); + --spectrum-button-background-color-focus: var(--spectrum-transparent-black-200); + + --spectrum-button-content-color-default: var(--spectrum-transparent-black-800); + --spectrum-button-content-color-hover: var(--spectrum-transparent-black-900); + --spectrum-button-content-color-down: var(--spectrum-transparent-black-900); + --spectrum-button-content-color-focus: var(--spectrum-transparent-black-900); + + &.spectrum-Button--outline { + --spectrum-button-background-color-default: var(--spectrum-transparent-black-25); + --spectrum-button-background-color-hover: var(--spectrum-transparent-black-100); + --spectrum-button-background-color-down: var(--spectrum-transparent-black-100); + --spectrum-button-background-color-focus: var(--spectrum-transparent-black-100); + + --spectrum-button-border-color-default: var(--spectrum-transparent-black-300); + --spectrum-button-border-color-hover: var(--spectrum-transparent-black-400); + --spectrum-button-border-color-down: var(--spectrum-transparent-black-400); + --spectrum-button-border-color-focus: var(--spectrum-transparent-black-400); + } + } + } +} + .spectrum-Button { @extend %spectrum-BaseButton; @extend %spectrum-ButtonWithFocusRing; @@ -115,39 +337,41 @@ governing permissions and limitations under the License. border-width: var(--mod-button-border-width, var(--spectrum-button-border-width)); border-style: solid; font-size: var(--mod-button-font-size, var(--spectrum-button-font-size)); - font-weight: var(--mod-bold-font-weight, var(--spectrum-bold-font-weight)); + font-weight: var(--mod-button-font-weight, var(--spectrum-button-font-weight)); gap: var(--mod-button-padding-label-to-icon, var(--spectrum-button-padding-label-to-icon)); min-inline-size: var(--mod-button-min-width, var(--spectrum-button-min-width)); min-block-size: var(--mod-button-height, var(--spectrum-button-height)); - /* Start with text-only padding */ padding-block: 0; padding-inline: var(--mod-button-edge-to-text, var(--spectrum-button-edge-to-text)); position: relative; - /* let staticColor variants inherit their color */ - color: inherit; + background-color: var(--highcontrast-button-background-color-default, var(--mod-button-background-color-default, var(--spectrum-button-background-color-default))); + border-color: var(--highcontrast-button-border-color-default, var(--mod-button-border-color-default, var(--spectrum-button-border-color-default))); + color: var(--highcontrast-button-content-color-default, var(--mod-button-content-color-default, var(--spectrum-button-content-color-default))); + transition: border var(--mod-button-animation-duration, var(--spectrum-button-animation-duration, 130ms)) linear, + color var(--mod-button-animation-duration, var(--spectrum-button-animation-duration, 130ms)) linear, + background-color var(--mod-button-animation-duration, var(--spectrum-button-animation-duration, 130ms)) linear; margin-block: var(--mod-button-margin-block); margin-inline-end: var(--mod-button-margin-right); margin-inline-start: var(--mod-button-margin-left); - &:hover, - &:active { - box-shadow: none; - } - - &:active { - transform: perspective(var(--spectrum-downstate-perspective)) translateZ(var(--spectrum-component-size-difference-down)); - } - .spectrum-Icon { - /* stylelint-disable-next-line custom-property-pattern -- Any block-size difference between the intended workflow icon size and actual icon used. + /* Any block-size difference between the intended workflow icon size and actual icon used. Helps support any existing use of smaller UI icons instead of intended Workflow icons. */ - --_icon-size-difference: max(0px, var(--spectrum-button-intended-icon-size) - var(--spectrum-icon-block-size, var(--spectrum-button-intended-icon-size))); + --spectrum-button-icon-size-difference: max(0px, + var(--spectrum-button-intended-icon-size) - + var(--spectrum-icon-block-size, var(--spectrum-button-intended-icon-size)) + ); - /* stylelint-disable-next-line custom-property-pattern -- see note above */ - margin-block-start: var(--mod-button-icon-margin-block-start, max(0px, var(--mod-button-top-to-icon, var(--spectrum-button-top-to-icon)) - var(--mod-button-border-width, var(--spectrum-button-border-width)) + (var(--_icon-size-difference, 0px) / 2))); + margin-block-start: var(--mod-button-icon-margin-block-start, + max(0px, + var(--mod-button-top-to-icon, var(--spectrum-button-top-to-icon)) - + var(--mod-button-border-width, var(--spectrum-button-border-width)) + + (var(--spectrum-button-icon-size-difference, 0px) / 2) + ) + ); margin-inline-start: calc( var(--mod-button-edge-to-visual, var(--spectrum-button-edge-to-visual)) - @@ -158,91 +382,48 @@ governing permissions and limitations under the License. align-self: flex-start; } - /* correct focus indicator radius for t-shirt sizing */ - &::after { - border-radius: calc(var(--mod-button-border-radius, var(--spectrum-button-border-radius)) + var(--mod-focus-indicator-gap, var(--spectrum-focus-indicator-gap))); - } - - &.spectrum-Button--iconOnly { - min-inline-size: unset; - padding: calc(var(--mod-button-edge-to-visual-only, var(--spectrum-button-edge-to-visual-only)) - var(--mod-button-border-width, var(--spectrum-button-border-width))); - border-radius: 50%; - - .spectrum-Icon { - align-self: center; - margin-inline-start: 0; - margin-block-start: 0; - } - - &::after { - border-radius: 50%; - } - } -} - -a.spectrum-Button { - @extend %spectrum-AnchorButton; -} - -.spectrum-Button-label { - @extend %spectrum-ButtonLabel; - padding-block-start: calc(var(--mod-button-top-to-text, var(--spectrum-button-top-to-text)) - var(--mod-button-border-width, var(--spectrum-button-border-width))); - padding-block-end: calc(var(--mod-button-bottom-to-text, var(--spectrum-button-bottom-to-text)) - var(--mod-button-border-width, var(--spectrum-button-border-width))); - line-height: var(--mod-button-line-height, var(--spectrum-button-line-height)); - align-self: start; - text-align: var(--mod-button-text-align, center); -} - -.spectrum-Button .spectrum-Icon + .spectrum-Button-label { - text-align: var(--mod-button-text-align-with-icon, start); -} - -.spectrum-Button { - &:focus-visible, - &.is-focused { - &::after { - box-shadow: 0 0 0 var(--mod-button-focus-ring-thickness, var(--spectrum-button-focus-ring-thickness)) var(--mod-button-focus-ring-color, var(--spectrum-button-focus-indicator-color)); - } - } -} - -/* Special cases for focus indicator */ -.spectrum-Button { - transition: border-color var(--mod-button-animation-duration, var(--spectrum-button-animation-duration)) ease-in-out; - + /* Focus indicator */ &::after { position: absolute; inset: 0; - margin: calc((var(--mod-button-focus-ring-gap, var(--spectrum-button-focus-ring-gap)) + var(--mod-button-border-width, var(--spectrum-button-border-width))) * -1); - border-radius: var(--mod-button-focus-ring-border-radius, var(--spectrum-button-focus-ring-border-radius)); + margin: calc(( + var(--mod-button-focus-ring-gap, var(--spectrum-button-focus-ring-gap)) + + var(--mod-button-border-width, var(--spectrum-button-border-width)) + ) * -1 + ); + border-radius: var(--mod-button-focus-ring-border-radius, calc( + var(--mod-button-border-radius, var(--spectrum-button-border-radius)) + + var(--mod-button-focus-ring-gap, var(--spectrum-button-focus-ring-gap)) + )); transition: box-shadow var(--mod-button-animation-duration, var(--spectrum-button-animation-duration)) ease-in-out; pointer-events: none; content: ''; } - &:focus-visible { - /* Remove the default focus outline */ + &:focus-visible, + &.is-focused { box-shadow: none; outline: none; &::after { - box-shadow: 0 0 0 var(--mod-button-focus-ring-thickness, var(--spectrum-button-focus-ring-thickness)) var(--highcontrast-button-focus-ring-color, var(--mod-button-focus-ring-color, - var(--mod-button-focus-ring-color, var(--spectrum-button-focus-indicator-color)))); + box-shadow: 0 0 0 + var(--mod-button-focus-ring-thickness, var(--spectrum-button-focus-ring-thickness)) + var(--highcontrast-button-focus-ring-color, var(--mod-button-focus-ring-color, var(--spectrum-button-focus-indicator-color))); + + /* Margin is repeated to override declaration coming from the imported BaseButton. */ + margin: calc(( + var(--mod-button-focus-ring-gap, var(--spectrum-button-focus-ring-gap)) + + var(--mod-button-border-width, var(--spectrum-button-border-width)) + ) * -1 + ); } } -} - -/* Core Token Theming */ -/* former skin.css, applied / copied from actionbutton/index.css */ -.spectrum-Button { - @extend %spectrum-BaseButton; - background-color: var(--highcontrast-button-background-color-default, var(--mod-button-background-color-default, var(--spectrum-button-background-color-default))); - border-color: var(--highcontrast-button-border-color-default, var(--mod-button-border-color-default, var(--spectrum-button-border-color-default))); - color: var(--highcontrast-button-content-color-default, var(--mod-button-content-color-default, var(--spectrum-button-content-color-default))); - transition: border var(--mod-button-animation-duration, var(--spectrum-button-animation-duration, 130ms)) linear, - color var(--mod-button-animation-duration, var(--spectrum-button-animation-duration, 130ms)) linear, - background-color var(--mod-button-animation-duration, var(--spectrum-button-animation-duration, 130ms)) linear; + /* States and interaction */ + &:hover, + &:active { + box-shadow: none; + } &:hover { background-color: var(--highcontrast-button-background-color-hover, var(--mod-button-background-color-hover, var(--spectrum-button-background-color-hover))); @@ -260,6 +441,7 @@ a.spectrum-Button { background-color: var(--highcontrast-button-background-color-down, var(--mod-button-background-color-down, var(--spectrum-button-background-color-down))); border-color: var(--highcontrast-button-border-color-down, var(--mod-button-border-color-down, var(--spectrum-button-border-color-down))); color: var(--highcontrast-button-content-color-down, var(--mod-button-content-color-down, var(--spectrum-button-content-color-down))); + transform: perspective(var(--spectrum-downstate-perspective)) translateZ(var(--spectrum-component-size-difference-down)); } &:disabled, @@ -305,42 +487,75 @@ a.spectrum-Button { } } -/* Static color variants */ -.spectrum-Button--staticWhite { - --spectrum-button-focus-indicator-color: var(--mod-static-black-focus-indicator-color, var(--spectrum-static-black-focus-indicator-color)); +a.spectrum-Button { + @extend %spectrum-AnchorButton; } -.spectrum-Button--staticBlack { - --spectrum-button-focus-indicator-color: var(--mod-static-black-focus-indicator-color, var(--spectrum-static-black-focus-indicator-color)); +.spectrum-Button-label { + @extend %spectrum-ButtonLabel; + padding-block-start: calc(var(--mod-button-top-to-text, var(--spectrum-button-top-to-text)) - var(--mod-button-border-width, var(--spectrum-button-border-width))); + padding-block-end: calc(var(--mod-button-bottom-to-text, var(--spectrum-button-bottom-to-text)) - var(--mod-button-border-width, var(--spectrum-button-border-width))); + line-height: var(--mod-button-line-height, var(--spectrum-button-line-height)); + align-self: start; + text-align: var(--mod-button-text-align, center); +} + +.spectrum-Button .spectrum-Icon + .spectrum-Button-label { + text-align: var(--mod-button-text-align-with-icon, start); } -/* Windows High Contrast Mode */ +/* Icon only variant */ +.spectrum-Button.spectrum-Button--iconOnly { + min-inline-size: unset; + padding: var(--mod-button-edge-to-visual-only, var(--spectrum-button-edge-to-visual-only)); + + .spectrum-Icon { + align-self: center; + margin-inline-start: 0; + margin-block-start: 0; + } +} + +/* Forced colors / high contrast mode */ @media (forced-colors: active) { .spectrum-Button { --highcontrast-button-content-color-disabled: GrayText; --highcontrast-button-border-color-disabled: GrayText; + --highcontrast-button-background-color-disabled: ButtonFace; + --mod-progress-circle-track-border-color: ButtonText; --mod-progress-circle-track-border-color-over-background: ButtonText; --mod-progress-circle-thickness: var(--spectrum-progress-circle-thickness-medium); + --highcontrast-button-focus-ring-color: ButtonText; + &:focus-visible { &::after { + /* Make sure the box-shadow used for the focus indicator is displayed. */ forced-color-adjust: none; - box-shadow: 0 0 0 var(--mod-button-focus-ring-thickness, var(--spectrum-button-focus-ring-thickness)) ButtonText; } } - &.spectrum-Button--accent.spectrum-Button--fill { + &.spectrum-Button--accent, + &:not( + .spectrum-Button--primary, + .spectrum-Button--negative, + .spectrum-Button--secondary, + .spectrum-Button--staticBlack, + .spectrum-Button--staticWhite + ){ + /* The accent fill variant looks different than the other buttons. + It inverts the background and content colors. */ --highcontrast-button-background-color-default: ButtonText; --highcontrast-button-content-color-default: ButtonFace; - --highcontrast-button-background-color-disabled: ButtonFace; --highcontrast-button-background-color-hover: Highlight; --highcontrast-button-background-color-down: Highlight; --highcontrast-button-background-color-focus: Highlight; - --highcontrast-button-content-color-hover: ButtonFace; - --highcontrast-button-content-color-down: ButtonFace; - --highcontrast-button-content-color-focus: ButtonFace; + + --highcontrast-button-content-color-hover: HighlightText; + --highcontrast-button-content-color-down: HighlightText; + --highcontrast-button-content-color-focus: HighlightText; .spectrum-Button-label { forced-color-adjust: none; diff --git a/components/button/metadata/button-accent.yml b/components/button/metadata/button-accent.yml index 9870c50f9ec..234a4f5e360 100644 --- a/components/button/metadata/button-accent.yml +++ b/components/button/metadata/button-accent.yml @@ -8,29 +8,29 @@ sections: This component can be modified via its `--mod-*` prefixed custom properties. A list of those prefixed custom properties can be found here. - name: Migration Guide description: | - ### x/x/2024 - Version 13.0.0 + ### Version 13.0.0 #### Spectrum 2 release - Button now uses Spectrum 2 tokens and specifications. A few notable changes: - - The mod custom property `--mod-line-height-100` has been renamed to `--mod-button-line-height`. - - The mod custom property `--mod-sans-font-family-stack` has been renamed to `--mod-button-font-family`. - - The mod custom property `--mod-animation-duration-100` has been renamed to `--mod-button-animation-duration`. - - ### Versions prior to 13.0.0 - #### Fill or Outline class required - All buttons now require either the `.spectrum-Button--fill` or `.spectrum-Button--outline` class. - - #### CTA replaced by Accent with Fill - Replace all `.spectrum-Button--cta` with `.spectrum-Button--accent .spectrum-Button--fill`. + Button now uses Spectrum 2 tokens and specifications, which includes many color changes to all variants. A few other notable changes: + - Outline buttons are no longer available in accent and negative options — use the filled variant instead. + - Medium size is now the default. The class `.spectrum-Button--sizeM` is now unnecessary for this size, and has been removed. + - The `.spectrum-Button--fill` class is no longer needed and has been removed. + + The following `--mod` custom properties have been renamed: + - `--mod-line-height-100` has been renamed to `--mod-button-line-height`. + - `--mod-sans-font-family-stack` has been renamed to `--mod-button-font-family`. + - `--mod-animation-duration-100` has been renamed to `--mod-button-animation-duration`. + - `--mod-bold-font-weight` has been renamed to `--mod-button-font-weight`. + + ### Version 11.0.0 + #### Remove focus-ring class + We've migrated away from the focus-ring class in favor of the native `:focus-visible` pseudo-class due to changes in browser support. + ### Version 10.0.0 #### Icon Only Add the `.spectrum-Button--iconOnly` class to apply the correct styling when an icon is used without a label. Provide an `aria-label` on the button itself when using this variant for accessibility. - #### T-shirt sizing - Button now supports t-shirt sizing and requires that you specify the size of button by adding a `.spectrum-Button--size*` class. - #### Change workflow icon size - Previously, all Buttons used `.spectrum-Icon--sizeS`. This has changed: | Button classname | Workflow icon classname | @@ -40,8 +40,17 @@ sections: | `.spectrum-Button--sizeL` | `.spectrum-Icon--sizeL` | | `.spectrum-Button--sizeXL` | `.spectrum-Icon--sizeXL` | - #### Remove focus-ring class - We've migrated away from the focus-ring class in favor of the native `:focus-visible` pseudo-class due to changes in browser support. + ### Version 6.0.0 + #### Fill or Outline class required + All buttons now require either the `.spectrum-Button--fill` or `.spectrum-Button--outline` class. + + #### CTA replaced by Accent with Fill + Replace all `.spectrum-Button--cta` with `.spectrum-Button--accent .spectrum-Button--fill`. + + ### Version 3.0.0 + #### T-shirt sizing + Button now supports t-shirt sizing and requires that you specify the size of button by adding a `.spectrum-Button--size*` class. + examples: - id: button-accent name: Sizing @@ -50,18 +59,18 @@ examples: