diff --git a/.changeset/red-kiwis-flash.md b/.changeset/red-kiwis-flash.md new file mode 100644 index 00000000000..c9a914f0e7f --- /dev/null +++ b/.changeset/red-kiwis-flash.md @@ -0,0 +1,32 @@ +--- +"@spectrum-css/toast": major +--- + +#### S2 toast migration + +This migrates the `toast` component to S2. Custom properties have been remapped per the design spec. Mods have been added and placeholder icons have been updated from the new workflow icons. The toast no longer supports a divider. + +##### Tokens + +| Before | After | +| ---------------------------- | ---------------------------- | +| --spectrum-corner-radius-100 | --spectrum-corner-radius-800 | + +##### Mods + +The following mods have been added. + +`--mod-toast-font-family` +`--mod-toast-font-style` +`--mod-toast-icon-block-size` +`--mod-toast-spacing-action-button-to-close` +`--mod-toast-spacing-bottom-edge-to-close-button` +`--mod-toast-spacing-close-button-to-edge` +`--mod-toast-spacing-text-to-close-button` +`--mod-toast-spacing-top-edge-to-close-button` + +##### Passthroughs + +The following passthrough has been added. + +`--mod-closebutton-icon-color-default` diff --git a/components/toast/dist/metadata.json b/components/toast/dist/metadata.json index 853a11f961a..50e0b73d5b1 100644 --- a/components/toast/dist/metadata.json +++ b/components/toast/dist/metadata.json @@ -2,80 +2,74 @@ "sourceFile": "index.css", "selectors": [ ".spectrum-Toast", + ".spectrum-Toast .spectrum-Button", + ".spectrum-Toast .spectrum-CloseButton", ".spectrum-Toast--info", - ".spectrum-Toast--info .spectrum-Toast-closeButton:focus-visible:not(:active)", ".spectrum-Toast--negative", - ".spectrum-Toast--negative .spectrum-Toast-closeButton:focus-visible:not(:active)", ".spectrum-Toast--positive", - ".spectrum-Toast--positive .spectrum-Toast-closeButton:focus-visible:not(:active)", ".spectrum-Toast-body", - ".spectrum-Toast-body + .spectrum-Toast-buttons", - ".spectrum-Toast-body .spectrum-Button", - ".spectrum-Toast-body .spectrum-Button:dir(rtl)", - ".spectrum-Toast-buttons", - ".spectrum-Toast-buttons .spectrum-CloseButton", ".spectrum-Toast-content", ".spectrum-Toast-content:lang(ja)", ".spectrum-Toast-content:lang(ko)", ".spectrum-Toast-content:lang(zh)", + ".spectrum-Toast-text", ".spectrum-Toast-typeIcon", - "[dir=\"rtl\"] .spectrum-Toast-body .spectrum-Button" + ".spectrum-Toast.spectrum-Toast--noButton", + ".spectrum-Toast:not(:has(.spectrum-Button))" ], "modifiers": [ "--mod-toast-background-color-default", - "--mod-toast-block-size", - "--mod-toast-border-width", "--mod-toast-corner-radius", - "--mod-toast-divider-color", + "--mod-toast-font-family", "--mod-toast-font-size", + "--mod-toast-font-style", "--mod-toast-font-weight", + "--mod-toast-icon-block-size", "--mod-toast-informative-background-color-default", "--mod-toast-line-height", "--mod-toast-line-height-cjk", "--mod-toast-max-inline-size", + "--mod-toast-min-block-size", "--mod-toast-negative-background-color-default", "--mod-toast-positive-background-color-default", - "--mod-toast-spacing-block-end", - "--mod-toast-spacing-block-start", - "--mod-toast-spacing-bottom-edge-to-divider", - "--mod-toast-spacing-bottom-edge-to-text", - "--mod-toast-spacing-close-button", + "--mod-toast-spacing-block-close-button", + "--mod-toast-spacing-button-to-close-button-horizontal", + "--mod-toast-spacing-close-button-to-end-edge", "--mod-toast-spacing-icon-to-text", "--mod-toast-spacing-start-edge-to-text-and-icon", - "--mod-toast-spacing-text-and-action-button-to-divider", - "--mod-toast-spacing-text-to-action-button-horizontal", - "--mod-toast-spacing-top-edge-to-divider", - "--mod-toast-spacing-top-edge-to-icon", - "--mod-toast-spacing-top-edge-to-text", + "--mod-toast-spacing-text-to-button-vertical", + "--mod-toast-spacing-text-to-close-button", + "--mod-toast-spacing-toast-to-edge", "--mod-toast-text-and-icon-color" ], "component": [ "--spectrum-toast-background-color-default", - "--spectrum-toast-block-size", - "--spectrum-toast-border-width", "--spectrum-toast-bottom-to-text", "--spectrum-toast-corner-radius", - "--spectrum-toast-divider-color", + "--spectrum-toast-font-family", "--spectrum-toast-font-size", + "--spectrum-toast-font-style", "--spectrum-toast-font-weight", "--spectrum-toast-height", + "--spectrum-toast-icon-block-size", "--spectrum-toast-informative-background-color-default", "--spectrum-toast-line-height", "--spectrum-toast-line-height-cjk", "--spectrum-toast-max-inline-size", "--spectrum-toast-maximum-width", + "--spectrum-toast-min-block-size", "--spectrum-toast-negative-background-color-default", "--spectrum-toast-positive-background-color-default", - "--spectrum-toast-spacing-block-end", - "--spectrum-toast-spacing-block-start", - "--spectrum-toast-spacing-bottom-edge-to-divider", + "--spectrum-toast-spacing-block-close-button", "--spectrum-toast-spacing-bottom-edge-to-text", - "--spectrum-toast-spacing-close-button", + "--spectrum-toast-spacing-button-to-close-button-horizontal", + "--spectrum-toast-spacing-close-button-to-end-edge", + "--spectrum-toast-spacing-edge-to-button-vertical", "--spectrum-toast-spacing-icon-to-text", "--spectrum-toast-spacing-start-edge-to-text-and-icon", - "--spectrum-toast-spacing-text-and-action-button-to-divider", - "--spectrum-toast-spacing-text-to-action-button-horizontal", - "--spectrum-toast-spacing-top-edge-to-divider", + "--spectrum-toast-spacing-text-to-button-horizontal", + "--spectrum-toast-spacing-text-to-close-button", + "--spectrum-toast-spacing-toast-to-edge", "--spectrum-toast-spacing-top-edge-to-icon", "--spectrum-toast-spacing-top-edge-to-text", "--spectrum-toast-text-and-icon-color", @@ -83,9 +77,9 @@ "--spectrum-toast-top-to-workflow-icon" ], "global": [ - "--spectrum-border-width-100", "--spectrum-cjk-line-height-100", - "--spectrum-corner-radius-100", + "--spectrum-corner-radius-800", + "--spectrum-default-font-style", "--spectrum-font-size-100", "--spectrum-informative-background-color-default", "--spectrum-line-height-100", @@ -93,12 +87,15 @@ "--spectrum-neutral-subdued-background-color-default", "--spectrum-positive-background-color-default", "--spectrum-regular-font-weight", + "--spectrum-sans-font-family-stack", "--spectrum-spacing-100", + "--spectrum-spacing-200", "--spectrum-spacing-300", - "--spectrum-text-to-visual-100", - "--spectrum-transparent-white-400", - "--spectrum-white" + "--spectrum-spacing-400", + "--spectrum-text-to-visual-300", + "--spectrum-white", + "--spectrum-workflow-icon-size-100" ], - "passthroughs": [], - "high-contrast": ["--highcontrast-toast-border-color"] + "passthroughs": ["--mod-closebutton-icon-color-default"], + "high-contrast": [] } diff --git a/components/toast/index.css b/components/toast/index.css index b8156dc08b9..1072f5a2cb7 100644 --- a/components/toast/index.css +++ b/components/toast/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 @@ -12,59 +12,43 @@ */ .spectrum-Toast { - --spectrum-toast-background-color-default: var(--spectrum-neutral-subdued-background-color-default); - --spectrum-toast-divider-color: var(--spectrum-transparent-white-400); - - /* Hardcoded variables */ + /* Font */ + --spectrum-toast-font-family: var(--spectrum-sans-font-family-stack); + --spectrum-toast-font-style: var(--spectrum-default-font-style); + --spectrum-toast-font-size: var(--spectrum-font-size-100); --spectrum-toast-font-weight: var(--spectrum-regular-font-weight); /* Size */ - - --spectrum-toast-font-size: var(--spectrum-font-size-100); - --spectrum-toast-corner-radius: var(--spectrum-corner-radius-100); - --spectrum-toast-block-size: var(--spectrum-toast-height); + --spectrum-toast-corner-radius: var(--spectrum-corner-radius-800); + --spectrum-toast-icon-block-size: var(--spectrum-workflow-icon-size-100); + --spectrum-toast-min-block-size: var(--spectrum-toast-height); --spectrum-toast-max-inline-size: var(--spectrum-toast-maximum-width); - --spectrum-toast-border-width: var(--spectrum-border-width-100); --spectrum-toast-line-height: var(--spectrum-line-height-100); --spectrum-toast-line-height-cjk: var(--spectrum-cjk-line-height-100); /* Space */ - - --spectrum-toast-spacing-icon-to-text: var(--spectrum-text-to-visual-100); - + --spectrum-toast-spacing-toast-to-edge: var(--spectrum-spacing-300); + --spectrum-toast-spacing-block-close-button: var(--spectrum-spacing-200); + --spectrum-toast-spacing-close-button-to-end-edge: var(--spectrum-spacing-100); + --spectrum-toast-spacing-text-to-close-button: var(--spectrum-spacing-300); + --spectrum-toast-spacing-edge-to-button-vertical: var(--spectrum-spacing-200); + --spectrum-toast-spacing-text-to-button-horizontal: var(--spectrum-spacing-400); + --spectrum-toast-spacing-button-to-close-button-horizontal: var(--spectrum-spacing-200); + --spectrum-toast-spacing-icon-to-text: var(--spectrum-text-to-visual-300); --spectrum-toast-spacing-start-edge-to-text-and-icon: var(--spectrum-spacing-300); - --spectrum-toast-spacing-text-and-action-button-to-divider: var(--spectrum-spacing-300); - - --spectrum-toast-spacing-top-edge-to-divider: var(--spectrum-spacing-100); - --spectrum-toast-spacing-bottom-edge-to-divider: var(--spectrum-spacing-100); - --spectrum-toast-spacing-top-edge-to-icon: var(--spectrum-toast-top-to-workflow-icon); - - --spectrum-toast-spacing-text-to-action-button-horizontal: var(--spectrum-spacing-300); - --spectrum-toast-spacing-close-button: var(--spectrum-spacing-100); - - --spectrum-toast-spacing-block-start: var(--spectrum-spacing-100); - --spectrum-toast-spacing-block-end: var(--spectrum-spacing-100); - --spectrum-toast-spacing-top-edge-to-text: var(--spectrum-toast-top-to-text); --spectrum-toast-spacing-bottom-edge-to-text: var(--spectrum-toast-bottom-to-text); /* Color */ + --spectrum-toast-background-color-default: var(--spectrum-neutral-subdued-background-color-default); --spectrum-toast-negative-background-color-default: var(--spectrum-negative-background-color-default); --spectrum-toast-positive-background-color-default: var(--spectrum-positive-background-color-default); --spectrum-toast-informative-background-color-default: var(--spectrum-informative-background-color-default); - --spectrum-toast-text-and-icon-color: var(--spectrum-white); -} - -@media (forced-colors: active) { - .spectrum-Toast { - /* Border is visible in high contrast mode */ - --highcontrast-toast-border-color: ButtonText; - border: var(--mod-toast-border-width, var(--spectrum-toast-border-width)) solid var(--highcontrast-toast-border-color, transparent); - } + --mod-closebutton-icon-color-default: var(--mod-toast-text-and-icon-color, var(--spectrum-toast-text-and-icon-color)); } .spectrum-Toast { @@ -72,76 +56,81 @@ display: inline-flex; flex-direction: row; align-items: stretch; - min-block-size: var(--mod-toast-block-size, var(--spectrum-toast-block-size)); + margin: var(--mod-toast-spacing-toast-to-edge, var(--spectrum-toast-spacing-toast-to-edge)); + min-block-size: var(--mod-toast-min-block-size, var(--spectrum-toast-min-block-size)); max-inline-size: var(--mod-toast-max-inline-size, var(--spectrum-toast-max-inline-size)); border-radius: var(--mod-toast-corner-radius, var(--spectrum-toast-corner-radius)); padding-inline-start: var(--mod-toast-spacing-start-edge-to-text-and-icon, var(--spectrum-toast-spacing-start-edge-to-text-and-icon)); + font-family: var(--mod-toast-font-family, var(--spectrum-toast-font-family)); font-size: var(--mod-toast-font-size, var(--spectrum-toast-font-size)); + font-style: var(--mod-toast-font-style, var(--spectrum-toast-font-style)); font-weight: var(--mod-toast-font-weight, var(--spectrum-toast-font-weight)); -webkit-font-smoothing: antialiased; background-color: var(--mod-toast-background-color-default, var(--spectrum-toast-background-color-default)); - color: var(--mod-toast-background-color-default, var(--spectrum-toast-background-color-default)); + color: var(--mod-toast-text-and-icon-color, var(--spectrum-toast-text-and-icon-color)); overflow-wrap: anywhere; + + &.spectrum-Toast--noButton, + &:not(:has(.spectrum-Button)) { + column-gap: var(--mod-toast-spacing-text-to-close-button, var(--spectrum-toast-spacing-text-to-close-button)); + } + + .spectrum-CloseButton { + margin-block: var(--mod-toast-spacing-block-close-button, var(--spectrum-toast-spacing-block-close-button)); + margin-inline-end: var(--mod-toast-spacing-close-button-to-end-edge, var(--spectrum-toast-spacing-close-button-to-end-edge)); + flex-shrink: 0; + } } .spectrum-Toast--negative { background-color: var(--mod-toast-negative-background-color-default, var(--spectrum-toast-negative-background-color-default)); - color: var(--mod-toast-negative-background-color-default, var(--spectrum-toast-negative-background-color-default)); - - .spectrum-Toast-closeButton:focus-visible:not(:active) { - color: var(--mod-toast-negative-background-color-default, var(--spectrum-toast-negative-background-color-default)); - } } .spectrum-Toast--info { background-color: var(--mod-toast-informative-background-color-default, var(--spectrum-toast-informative-background-color-default)); - color: var(--mod-toast-informative-background-color-default, var(--spectrum-toast-informative-background-color-default)); - - .spectrum-Toast-closeButton:focus-visible:not(:active) { - color: var(--mod-toast-informative-background-color-default, var(--spectrum-toast-informative-background-color-default)); - } } .spectrum-Toast--positive { background-color: var(--mod-toast-positive-background-color-default, var(--spectrum-toast-positive-background-color-default)); - color: var(--mod-toast-positive-background-color-default, var(--spectrum-toast-positive-background-color-default)); - - .spectrum-Toast-closeButton:focus-visible:not(:active) { - color: var(--mod-toast-positive-background-color-default, var(--spectrum-toast-positive-background-color-default)); - } } .spectrum-Toast-typeIcon { flex-shrink: 0; flex-grow: 0; - margin-block-start: var(--mod-toast-spacing-top-edge-to-icon, var(--spectrum-toast-spacing-top-edge-to-icon)); + block-size: var(--mod-toast-icon-block-size, var(--spectrum-toast-icon-block-size)); + + /* Similar to the spectrum-Toast-text calc, now the icon only has an extra margin to add the difference between spacing-200 (which is now around the entire toast) and the requested toast-top-to-workflow-icon token. */ + margin-block-start: calc(var(--spectrum-toast-spacing-top-edge-to-icon) - var(--spectrum-toast-spacing-edge-to-button-vertical)); margin-inline-end: var(--mod-toast-spacing-icon-to-text, var(--spectrum-toast-spacing-icon-to-text)); margin-inline-start: 0; +} - color: var(--mod-toast-text-and-icon-color, var(--spectrum-toast-text-and-icon-color)); +.spectrum-Toast .spectrum-Button { + margin-inline-end: var(--mod-toast-spacing-button-to-close-button-horizontal, var(--spectrum-toast-spacing-button-to-close-button-horizontal)); +} + +.spectrum-Toast-body { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + flex: 1 1 auto; + padding-block: var(--mod-toast-spacing-text-to-button-vertical, var(--spectrum-toast-spacing-edge-to-button-vertical)); + column-gap: var(--spectrum-toast-spacing-text-to-button-horizontal); } .spectrum-Toast-content { flex: 1 1 auto; - display: inline-block; + display: inline-flex; + align-items: start; box-sizing: border-box; - - padding-block-start: calc(var(--mod-toast-spacing-top-edge-to-text, var(--spectrum-toast-spacing-top-edge-to-text)) - var(--mod-toast-spacing-block-start, var(--spectrum-toast-spacing-block-start))); - padding-block-end: calc(var(--mod-toast-spacing-bottom-edge-to-text, var(--spectrum-toast-spacing-bottom-edge-to-text)) - var(--mod-toast-spacing-block-end, var(--spectrum-toast-spacing-block-end))); - - padding-inline-end: var(--mod-toast-spacing-text-to-action-button-horizontal, var(--spectrum-toast-spacing-text-to-action-button-horizontal)); - padding-inline-start: 0; - line-height: var(--mod-toast-line-height, var(--spectrum-toast-line-height)); - text-align: start; - color: var(--mod-toast-text-and-icon-color, var(--spectrum-toast-text-and-icon-color)); &:lang(ja), @@ -151,47 +140,11 @@ } } -.spectrum-Toast-buttons { - display: flex; - flex: 0 0 auto; - align-items: flex-start; - - margin-block-start: var(--mod-toast-spacing-top-edge-to-divider, var(--spectrum-toast-spacing-top-edge-to-divider)); - margin-block-end: var(--mod-toast-spacing-bottom-edge-to-divider, var(--spectrum-toast-spacing-bottom-edge-to-divider)); - - /* Divider color for Text | Action Button */ - border-inline-start-color: var(--mod-toast-divider-color, var(--spectrum-toast-divider-color)); - padding-inline-end: var(--mod-toast-spacing-close-button, var(--spectrum-toast-spacing-close-button)); +.spectrum-Toast-text { + /* The toast itself has spacing-200 spacing on the top and bottom. That ensures that the spectrum-Button has the requested spacing-200 token, but poses a problem for the text, which is smaller in height than the button. So this padding for this text is the difference between the requested toast-top-to-text/toast-bottom-to-text tokens and the spacing-200. - .spectrum-CloseButton { - align-self: flex-start; - } -} - -.spectrum-Toast-body { - display: flex; - flex-wrap: wrap; - align-items: center; - flex: 1 1 auto; - align-self: center; - - padding-block-start: var(--mod-toast-spacing-block-start, var(--spectrum-toast-spacing-block-start)); - padding-block-end: var(--mod-toast-spacing-block-end, var(--spectrum-toast-spacing-block-end)); - - .spectrum-Button { - margin-inline-start: auto; - margin-inline-end: var(--mod-toast-spacing-text-and-action-button-to-divider, var(--spectrum-toast-spacing-text-and-action-button-to-divider)); - - &:dir(rtl) { - margin-inline-end: auto; - margin-inline-end: var(--mod-toast-spacing-text-and-action-button-to-divider, var(--spectrum-toast-spacing-text-and-action-button-to-divider)); - } - } - - & + .spectrum-Toast-buttons { - padding-inline-start: var(--mod-toast-spacing-close-button, var(--spectrum-toast-spacing-close-button)); - - border-inline-start-width: 1px; - border-inline-start-style: solid; - } + This padding + the spacing-200 should equal the requested toast-top-to-text/toast-bottom-to-text tokens. */ + padding-block-start: calc(var(--spectrum-toast-spacing-top-edge-to-text) - var(--spectrum-toast-spacing-edge-to-button-vertical)); + padding-block-end: calc(var(--spectrum-toast-spacing-bottom-edge-to-text) - var(--spectrum-toast-spacing-edge-to-button-vertical)); + margin: 0; } diff --git a/components/toast/stories/template.js b/components/toast/stories/template.js index 6bf43215408..33c65c376d0 100644 --- a/components/toast/stories/template.js +++ b/components/toast/stories/template.js @@ -13,14 +13,15 @@ import "../index.css"; export const Template = ({ rootClass = "spectrum-Toast", message, + hasButton, inlineButtonLabel, variant, customClasses = [], customStyles = {}, id = getRandomId("toast"), } = {}, context = {}) => { - let iconName = "Info"; - if (variant === "negative") iconName = "Alert"; + let iconName = "InfoCircle"; + if (variant === "negative") iconName = "AlertTriangle"; if (variant === "positive") iconName = "CheckmarkCircle"; if (variant === "neutral") iconName = undefined; @@ -34,17 +35,19 @@ export const Template = ({ id=${ifDefined(id)} style=${styleMap(customStyles)} > - ${when(variant, () => - Icon({ - iconName, - setName: "workflow", - size: "m", - customClasses: [`${rootClass}-typeIcon`], - }, context) - )}
-
${message}
- ${when(inlineButtonLabel, () => +
+ ${when(variant, () => + Icon({ + iconName, + setName: "workflow", + size: "m", + customClasses: [`${rootClass}-typeIcon`], + }, context) + )} +

${message}

+
+ ${when(hasButton && inlineButtonLabel, () => Button({ variant: "secondary", size: "m", @@ -54,13 +57,12 @@ export const Template = ({ }, context) )}
-
- ${CloseButton({ - size: "m", - staticColor: "white", - onclick, - }, context)} -
+ ${CloseButton({ + size: "m", + iconSize: "large", + staticColor: "white", + onclick, + }, context)} `; }; diff --git a/components/toast/stories/toast.stories.js b/components/toast/stories/toast.stories.js index 9271ef70225..2a63b88c875 100644 --- a/components/toast/stories/toast.stories.js +++ b/components/toast/stories/toast.stories.js @@ -30,6 +30,16 @@ export default { }, control: "text", }, + hasButton: { + name: "Has button", + description: "Adds a button that is directly related to the toast's message.", + type: { name: "boolean" }, + table: { + type: { summary: "boolean" }, + category: "Component", + }, + control: "boolean", + }, inlineButtonLabel: { name: "Inline button label", description: "Label for the inline button; if blank, no button is shown", @@ -39,6 +49,7 @@ export default { type: { summary: "string" }, }, control: "text", + if: { arg: "hasButton", truthy: true }, }, }, args: { @@ -64,6 +75,7 @@ export default { export const Default = ToastGroup.bind({}); Default.args = { message: "File has been archived", + hasButton: true, inlineButtonLabel: "Undo", variant: "neutral" }; @@ -142,7 +154,7 @@ Wrapping.parameters = { }; /** - * A toast can have up to one action: [a static white, secondary, outline button](?path=/docs/components-button--docs#static-white---secondary). This label should be kept concise, and it should only be used when there’s a direct action available that is related to the toast text. + * A toast can have up to one button: [a static white, secondary, outline button](?path=/docs/components-button--docs#static-white---secondary). That button's label should be kept concise, and it should only be used when there’s a direct action available that is related to the toast text. */ export const Action = ActionTemplate.bind({}); diff --git a/components/toast/stories/toast.test.js b/components/toast/stories/toast.test.js index 7e784b44980..ef23bab9eb1 100644 --- a/components/toast/stories/toast.test.js +++ b/components/toast/stories/toast.test.js @@ -34,14 +34,14 @@ export const ToastGroup = Variants({ { testHeading: "Wrapping without button", variant: "info", - message: "A new version of Lightroom Classic is now available. Use the Update button below to start using the new version.", - inlineButtonLabel: undefined + message: "A new version of Lightroom Classic is now available.", + hasButton: false }, { testHeading: "Short message, no required action", variant: "neutral", message: "The toast is done.", - inlineButtonLabel: undefined + hasButton: false }, ] });