Skip to content

Commit

Permalink
Merge pull request #98 from hashicorp/focus-ring-mixin-refactoring
Browse files Browse the repository at this point in the history
Refactor "focus-ring" tokens and mixins to support both "active" and "critical" colors
  • Loading branch information
didoo committed Mar 21, 2022
2 parents 541469c + 411cd9b commit 7fe1ac1
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 50 deletions.
5 changes: 5 additions & 0 deletions .changeset/serious-peas-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hashicorp/design-system-tokens": minor
---

refactored “focus-ring” tokens and CSS helpers to support both “action” and “critical“ colors
5 changes: 5 additions & 0 deletions .changeset/thirty-fireants-cheat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hashicorp/design-system-components": patch
---

refactored the “focus-ring” mixins to support both “action” (default) and “critical“ colors
12 changes: 6 additions & 6 deletions packages/components/app/styles/mixins/_focus-ring.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@
// - 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) {
box-shadow: none;
}
// 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,
Expand All @@ -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;
Expand All @@ -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
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,77 @@
value).</li>
</ul>

<h4 class="dummy-h4">Sass mixins</h4>
<p class="dummy-paragraph">We have also created two
<strong>Sass mixins</strong>
<code class="dummy-code">hds-focus-ring-basic</code>
and
<code class="dummy-code">hds-focus-ring-with-pseudo-element</code>
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
<code class="dummy-code">:focus/:focus-visible</code>
for different browsers.
</p>
<p class="dummy-paragraph">To use these mixins you have to import the Sass file
<code class="dummy-code">packages/components/app/styles/mixins/_focus-ring.scss</code>
contained in the
<code class="dummy-code">@hashicorp/design-system</code>
monorepo or the same file
<code class="dummy-code">app/styles/mixins/_focus-ring.scss</code>
distributed in the
<code class="dummy-code">@hashicorp/design-system-components</code>
package.</p>
<p class="dummy-paragraph">Then the mixins can be invoked in this way:</p>
{{! prettier-ignore-start }}
<CodeBlock
@language="css"
@code="
/* include the mixin file via @use (path will depend on your context) */
@use '../mixins/focus-ring' as *;
/* apply the focus-ring as box-shadow ('action' will be the default color ) */
.your-selector {
[...your CSS declarations]
@include hds-focus-ring-basic();
}
/* apply the focus-ring as pseudo-element (with 'critical' color ) */
.your-selector {
[...your CSS declarations]
@include hds-focus-ring-with-pseudo-element($top: 0, $right: 0, $bottom: 0, $left: 0, $radius: 5px, $color: critical);
}
"
/>
{{! prettier-ignore-end }}

</section>

<section data-test-percy>
<h3 class="dummy-h3">Showcase</h3>
<h4 class="dummy-h4">Focus ring:</h4>
<p class="dummy-paragraph">Standalone "focus ring" effect</p>
<div class="dummy-focus-ring-samples">
<div class="dummy-focus-ring-sample hds-focus-ring-box-shadow">
<div class="dummy-focus-ring-sample hds-focus-ring-action-box-shadow">
<DummyPlaceholder @text="no radius" @width="100" @height="100" @background="transparent" />
</div>
<div class="dummy-focus-ring-sample dummy-focus-ring-sample--border-radius hds-focus-ring-box-shadow">
<div class="dummy-focus-ring-sample dummy-focus-ring-sample--border-radius hds-focus-ring-action-box-shadow">
<DummyPlaceholder @text="with border radius" @width="100" @height="100" @background="transparent" />
</div>
</div>
<div class="dummy-focus-ring-samples">
<div class="dummy-focus-ring-sample">
<span class="dummy-text-small">action</span>
<br />
<div class="hds-focus-ring-action-box-shadow">
<DummyPlaceholder @text="with border radius" @width="100" @height="100" @background="transparent" />
</div>
</div>
<div class="dummy-focus-ring-sample">
<span class="dummy-text-small">critical</span>
<br />
<div class="hds-focus-ring-critical-box-shadow">
<DummyPlaceholder @text="with border radius" @width="100" @height="100" @background="transparent" />
</div>
</div>
</div>
</section>
5 changes: 3 additions & 2 deletions packages/tokens/dist/devdot/css/helpers/focus-ring.css
Original file line number Diff line number Diff line change
@@ -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); }
5 changes: 3 additions & 2 deletions packages/tokens/dist/devdot/css/tokens.css
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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;
Expand Down
25 changes: 22 additions & 3 deletions packages/tokens/dist/docs/devdot/tokens.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
]
},
Expand Down
25 changes: 22 additions & 3 deletions packages/tokens/dist/docs/products/tokens.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
]
},
Expand Down
5 changes: 3 additions & 2 deletions packages/tokens/dist/products/css/helpers/focus-ring.css
Original file line number Diff line number Diff line change
@@ -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); }
5 changes: 3 additions & 2 deletions packages/tokens/dist/products/css/tokens.css
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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;
Expand Down
14 changes: 7 additions & 7 deletions packages/tokens/scripts/build-parts/generateFocusRingHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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];
}
33 changes: 12 additions & 21 deletions packages/tokens/src/global/focus-ring.json
Original file line number Diff line number Diff line change
@@ -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}"
}
}
}

2 comments on commit 7fe1ac1

@vercel
Copy link

@vercel vercel bot commented on 7fe1ac1 Mar 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 7fe1ac1 Mar 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.