diff --git a/.changeset/serious-peas-explain.md b/.changeset/serious-peas-explain.md new file mode 100644 index 0000000000..8abdc012b1 --- /dev/null +++ b/.changeset/serious-peas-explain.md @@ -0,0 +1,5 @@ +--- +"@hashicorp/design-system-tokens": minor +--- + +refactored “focus-ring” tokens and CSS helpers to support both “action” and “critical“ colors diff --git a/.changeset/thirty-fireants-cheat.md b/.changeset/thirty-fireants-cheat.md new file mode 100644 index 0000000000..d1c3876e33 --- /dev/null +++ b/.changeset/thirty-fireants-cheat.md @@ -0,0 +1,5 @@ +--- +"@hashicorp/design-system-components": patch +--- + +refactored the “focus-ring” mixins to support both “action” (default) and “critical“ colors diff --git a/packages/components/app/styles/mixins/_focus-ring.scss b/packages/components/app/styles/mixins/_focus-ring.scss index 2ac34c3d73..135c25c1c0 100644 --- a/packages/components/app/styles/mixins/_focus-ring.scss +++ b/packages/components/app/styles/mixins/_focus-ring.scss @@ -2,14 +2,14 @@ // - https://github.com/hashicorp/design-system-components/issues/161 // - https://www.tpgi.com/focus-visible-and-backwards-compatibility/ -@mixin hds-focus-ring-basic() { +@mixin hds-focus-ring-basic($color: action) { outline-style: solid; // used to avoid double outline+focus-ring in Safari (see https://github.com/hashicorp/design-system-components/issues/161#issuecomment-1031548656) outline-color: transparent; // default focus for browsers that still rely on ":focus" &:focus, &.is-focus { - box-shadow: var(--token-focus-ring-box-shadow); + box-shadow: var(--token-focus-ring-#{$color}-box-shadow); } // undo the previous declaration for browsers that support ":focus-visible" but wouldn't normally show default focus styles &:focus:not(:focus-visible) { @@ -17,7 +17,7 @@ } // set focus for browsers that support ":focus-visible" &:focus-visible { - box-shadow: var(--token-focus-ring-box-shadow); + box-shadow: var(--token-focus-ring-#{$color}-box-shadow); } // remove the focus ring on "active + focused" state (by design) &:focus:active, @@ -26,7 +26,7 @@ } } -@mixin hds-focus-ring-with-pseudo-element($top: 0, $right: 0, $bottom: 0, $left: 0, $radius: 5px) { +@mixin hds-focus-ring-with-pseudo-element($top: 0, $right: 0, $bottom: 0, $left: 0, $radius: 5px, $color: action) { isolation: isolate; // used to create a new stacking context (needed to have the pseudo element below text/icon but not the parent container) outline-style: solid; // used to avoid double outline+focus-ring in Safari (see https://github.com/hashicorp/design-system-components/issues/161#issuecomment-1031548656) outline-color: transparent; @@ -48,7 +48,7 @@ &:focus, &.is-focus { &::before { - box-shadow: var(--token-focus-ring-box-shadow); + box-shadow: var(--token-focus-ring-#{$color}-box-shadow); } } // undo the previous declaration for browsers that support ":focus-visible" but wouldn't normally show default focus styles @@ -60,7 +60,7 @@ // set focus for browsers that support ":focus-visible" &:focus-visible { &::before { - box-shadow: var(--token-focus-ring-box-shadow); + box-shadow: var(--token-focus-ring-#{$color}-box-shadow); } } // remove the focus ring on "active + focused" state (by design) diff --git a/packages/components/tests/dummy/app/templates/foundations/focus-ring.hbs b/packages/components/tests/dummy/app/templates/foundations/focus-ring.hbs index 1aac56d2d8..c3a1e5e058 100644 --- a/packages/components/tests/dummy/app/templates/foundations/focus-ring.hbs +++ b/packages/components/tests/dummy/app/templates/foundations/focus-ring.hbs @@ -63,6 +63,49 @@ value). +

Sass mixins

+

We have also created two + Sass mixins + hds-focus-ring-basic + and + hds-focus-ring-with-pseudo-element + but they're mainly used for internal use (to the design system codebase). These mixins do more than just apply the + focus style: they also take care of all the different way to declare the + :focus/:focus-visible + for different browsers. +

+

To use these mixins you have to import the Sass file + packages/components/app/styles/mixins/_focus-ring.scss + contained in the + @hashicorp/design-system + monorepo or the same file + app/styles/mixins/_focus-ring.scss + distributed in the + @hashicorp/design-system-components + package.

+

Then the mixins can be invoked in this way:

+ {{! prettier-ignore-start }} + + {{! prettier-ignore-end }} +
@@ -70,11 +113,27 @@

Focus ring:

Standalone "focus ring" effect

-
+
-
+
+
+
+ action +
+
+ +
+
+
+ critical +
+
+ +
+
+
\ No newline at end of file diff --git a/packages/tokens/dist/devdot/css/helpers/focus-ring.css b/packages/tokens/dist/devdot/css/helpers/focus-ring.css index 176f913a06..a6f0aa4412 100644 --- a/packages/tokens/dist/devdot/css/helpers/focus-ring.css +++ b/packages/tokens/dist/devdot/css/helpers/focus-ring.css @@ -1,6 +1,7 @@ /** * Do not edit directly - * Generated on Tue, 22 Feb 2022 21:05:19 GMT + * Generated on Fri, 18 Mar 2022 20:06:01 GMT */ -.hds-focus-ring-box-shadow { box-shadow: var(--token-focus-ring-box-shadow); } +.hds-focus-ring-action-box-shadow { box-shadow: var(--token-focus-ring-action-box-shadow); } +.hds-focus-ring-critical-box-shadow { box-shadow: var(--token-focus-ring-critical-box-shadow); } diff --git a/packages/tokens/dist/devdot/css/tokens.css b/packages/tokens/dist/devdot/css/tokens.css index 9c27583a17..91b061d5d6 100644 --- a/packages/tokens/dist/devdot/css/tokens.css +++ b/packages/tokens/dist/devdot/css/tokens.css @@ -1,6 +1,6 @@ /** * Do not edit directly - * Generated on Thu, 17 Mar 2022 08:19:13 GMT + * Generated on Fri, 18 Mar 2022 20:06:01 GMT */ :root { @@ -238,7 +238,8 @@ --token-surface-high-box-shadow: 0 0 0 1px #656a7640, 0px 2px 3px 0px #656a7626, 0px 16px 16px -10px #656a7633; --token-surface-higher-box-shadow: 0 0 0 1px #656a7633, 0px 2px 3px 0px #656a761a, 0px 12px 28px 0px #656a7640; --token-surface-overlay-box-shadow: 0 0 0 1px #3b3d4566, 0px 2px 3px 0px #3b3d4580, 0px 12px 24px 0px #3b3d4599; - --token-focus-ring-box-shadow: inset 0 0 0 1px #0c56e9, 0 0 0 3px #5990ff; + --token-focus-ring-action-box-shadow: inset 0 0 0 1px #0c56e9, 0 0 0 3px #5990ff; + --token-focus-ring-critical-box-shadow: inset 0 0 0 1px #c00005, 0 0 0 3px #dd7578; --token-typography-font-stack-display: -apple-system, BlinkMacSystemFont, SF Pro Display, Segoe UI Display, Ubuntu, sans-serif; --token-typography-font-stack-text: -apple-system, BlinkMacSystemFont, SF Pro Text, Segoe UI Text, Ubuntu, sans-serif; --token-typography-font-stack-code: SF Mono, Consolas, Ubuntu Mono, monospace; diff --git a/packages/tokens/dist/docs/devdot/tokens.json b/packages/tokens/dist/docs/devdot/tokens.json index f7f482351c..d424502e31 100644 --- a/packages/tokens/dist/docs/devdot/tokens.json +++ b/packages/tokens/dist/docs/devdot/tokens.json @@ -5288,15 +5288,34 @@ { "value": "inset 0 0 0 1px #0c56e9, 0 0 0 3px #5990ff", "original": { - "value": "{focus-ring.internal.box-shadow.value}, {focus-ring.external.box-shadow.value}" + "value": "{focus-ring.action.internal-box-shadow.value}, {focus-ring.action.external-box-shadow.value}" }, - "name": "token-focus-ring-box-shadow", + "name": "token-focus-ring-action-box-shadow", "attributes": { "category": "focus-ring", - "type": "box-shadow" + "type": "action", + "item": "box-shadow" }, "path": [ "focus-ring", + "action", + "box-shadow" + ] + }, + { + "value": "inset 0 0 0 1px #c00005, 0 0 0 3px #dd7578", + "original": { + "value": "{focus-ring.critical.internal-box-shadow.value}, {focus-ring.critical.external-box-shadow.value}" + }, + "name": "token-focus-ring-critical-box-shadow", + "attributes": { + "category": "focus-ring", + "type": "critical", + "item": "box-shadow" + }, + "path": [ + "focus-ring", + "critical", "box-shadow" ] }, diff --git a/packages/tokens/dist/docs/products/tokens.json b/packages/tokens/dist/docs/products/tokens.json index bbb184ffb0..6085af5fa9 100644 --- a/packages/tokens/dist/docs/products/tokens.json +++ b/packages/tokens/dist/docs/products/tokens.json @@ -5242,15 +5242,34 @@ { "value": "inset 0 0 0 1px #0c56e9, 0 0 0 3px #5990ff", "original": { - "value": "{focus-ring.internal.box-shadow.value}, {focus-ring.external.box-shadow.value}" + "value": "{focus-ring.action.internal-box-shadow.value}, {focus-ring.action.external-box-shadow.value}" }, - "name": "token-focus-ring-box-shadow", + "name": "token-focus-ring-action-box-shadow", "attributes": { "category": "focus-ring", - "type": "box-shadow" + "type": "action", + "item": "box-shadow" }, "path": [ "focus-ring", + "action", + "box-shadow" + ] + }, + { + "value": "inset 0 0 0 1px #c00005, 0 0 0 3px #dd7578", + "original": { + "value": "{focus-ring.critical.internal-box-shadow.value}, {focus-ring.critical.external-box-shadow.value}" + }, + "name": "token-focus-ring-critical-box-shadow", + "attributes": { + "category": "focus-ring", + "type": "critical", + "item": "box-shadow" + }, + "path": [ + "focus-ring", + "critical", "box-shadow" ] }, diff --git a/packages/tokens/dist/products/css/helpers/focus-ring.css b/packages/tokens/dist/products/css/helpers/focus-ring.css index 176f913a06..a6f0aa4412 100644 --- a/packages/tokens/dist/products/css/helpers/focus-ring.css +++ b/packages/tokens/dist/products/css/helpers/focus-ring.css @@ -1,6 +1,7 @@ /** * Do not edit directly - * Generated on Tue, 22 Feb 2022 21:05:19 GMT + * Generated on Fri, 18 Mar 2022 20:06:01 GMT */ -.hds-focus-ring-box-shadow { box-shadow: var(--token-focus-ring-box-shadow); } +.hds-focus-ring-action-box-shadow { box-shadow: var(--token-focus-ring-action-box-shadow); } +.hds-focus-ring-critical-box-shadow { box-shadow: var(--token-focus-ring-critical-box-shadow); } diff --git a/packages/tokens/dist/products/css/tokens.css b/packages/tokens/dist/products/css/tokens.css index 386e18bb15..2b2ca8a1f5 100644 --- a/packages/tokens/dist/products/css/tokens.css +++ b/packages/tokens/dist/products/css/tokens.css @@ -1,6 +1,6 @@ /** * Do not edit directly - * Generated on Mon, 07 Mar 2022 11:14:41 GMT + * Generated on Fri, 18 Mar 2022 20:06:01 GMT */ :root { @@ -236,7 +236,8 @@ --token-surface-high-box-shadow: 0 0 0 1px #656a7640, 0px 2px 3px 0px #656a7626, 0px 16px 16px -10px #656a7633; --token-surface-higher-box-shadow: 0 0 0 1px #656a7633, 0px 2px 3px 0px #656a761a, 0px 12px 28px 0px #656a7640; --token-surface-overlay-box-shadow: 0 0 0 1px #3b3d4566, 0px 2px 3px 0px #3b3d4580, 0px 12px 24px 0px #3b3d4599; - --token-focus-ring-box-shadow: inset 0 0 0 1px #0c56e9, 0 0 0 3px #5990ff; + --token-focus-ring-action-box-shadow: inset 0 0 0 1px #0c56e9, 0 0 0 3px #5990ff; + --token-focus-ring-critical-box-shadow: inset 0 0 0 1px #c00005, 0 0 0 3px #dd7578; --token-typography-font-stack-display: -apple-system, BlinkMacSystemFont, SF Pro Display, Segoe UI Display, Ubuntu, sans-serif; --token-typography-font-stack-text: -apple-system, BlinkMacSystemFont, SF Pro Text, Segoe UI Text, Ubuntu, sans-serif; --token-typography-font-stack-code: SF Mono, Consolas, Ubuntu Mono, monospace; diff --git a/packages/tokens/scripts/build-parts/generateFocusRingHelpers.ts b/packages/tokens/scripts/build-parts/generateFocusRingHelpers.ts index c2deb7573a..3cd616b458 100644 --- a/packages/tokens/scripts/build-parts/generateFocusRingHelpers.ts +++ b/packages/tokens/scripts/build-parts/generateFocusRingHelpers.ts @@ -6,15 +6,15 @@ type Helpers = string[]; export function generateFocusRingHelpers(tokens: TransformedTokens): Helpers { - // notice: even if the focus-ring case is much simpler than the other helpers I have - // maintained the same code structure for consistency so it's easier to compare and refactor if needed - const helpersFocusRing: Helpers = []; - if (tokens.hasOwnProperty('box-shadow')) { - const selector = `.${PREFIX}-focus-ring-box-shadow`; - helpersFocusRing.push(`${selector} { box-shadow: var(--token-focus-ring-box-shadow); }`); - } + Object.keys(tokens).forEach((key: string) => { + const color = key; + if (tokens[color].hasOwnProperty('box-shadow')) { + const selector = `.${PREFIX}-focus-ring-${color}-box-shadow`; + helpersFocusRing.push(`${selector} { box-shadow: var(--token-focus-ring-${color}-box-shadow); }`); + } + }); return [...helpersFocusRing]; } diff --git a/packages/tokens/src/global/focus-ring.json b/packages/tokens/src/global/focus-ring.json index fb4b9d16c2..9cc28fca40 100644 --- a/packages/tokens/src/global/focus-ring.json +++ b/packages/tokens/src/global/focus-ring.json @@ -1,39 +1,30 @@ { "focus-ring": { - "internal": { - "spread": { - "value": "1", - "type": "size", + "action": { + "internal-box-shadow": { + "value": "inset 0 0 0 1px {color.focus.action.internal.value}", "private": true }, - "color": { - "value": "{color.palette.blue-300.value}", - "type": "color", + "external-box-shadow": { + "value": "0 0 0 3px {color.focus.action.external.value}", "private": true }, "box-shadow": { - "value": "inset 0 0 0 {focus-ring.internal.spread.value} {focus-ring.internal.color.value}", - "private": true + "value": "{focus-ring.action.internal-box-shadow.value}, {focus-ring.action.external-box-shadow.value}" } }, - "external": { - "spread": { - "value": "3", - "type": "size", + "critical": { + "internal-box-shadow": { + "value": "inset 0 0 0 1px {color.focus.critical.internal.value}", "private": true }, - "color": { - "value": "{color.focus.action.external.value}", - "type": "color", + "external-box-shadow": { + "value": "0 0 0 3px {color.focus.critical.external.value}", "private": true }, "box-shadow": { - "value": "0 0 0 {focus-ring.external.spread.value} {focus-ring.external.color.value}", - "private": true + "value": "{focus-ring.critical.internal-box-shadow.value}, {focus-ring.critical.external-box-shadow.value}" } - }, - "box-shadow": { - "value": "{focus-ring.internal.box-shadow.value}, {focus-ring.external.box-shadow.value}" } } } \ No newline at end of file