diff --git a/clayui.com/content/docs/css/utilities/markup-accessibility.md b/clayui.com/content/docs/css/utilities/markup-accessibility.md
index 3354c2c9c2..c46a1efa23 100644
--- a/clayui.com/content/docs/css/utilities/markup-accessibility.md
+++ b/clayui.com/content/docs/css/utilities/markup-accessibility.md
@@ -10,6 +10,7 @@ title: 'Accessibility'
- [C Prefers Reduced Motion](#css-c-prefers-reduced-motion)
- [C Prefers Link Underline](#css-c-prefers-link-underline)
- [C Prefers Letter Spacing 1](#css-c-prefers-letter-spacing-1)
+- [C Prefers Focus](#css-c-prefers-focus)
@@ -87,3 +88,21 @@ The class `c-prefers-expanded-text` expands all truncated text to be visible.
+
+## C Prefers Focus(#css-c-prefers-focus)
+
+The class `c-prefers-focus` should be added to the `body` element to show the focus outline on mouse click. This is an accessibility feature for users who prefer this style of navigation.
+
+Focus Visible is now supported in all major browsers . We have enabled it by default in Clay CSS. Using the mouse to click on links, buttons, checkboxes, and other elements no longer show the focus outline. The focus outline will be shown when interacting with elements via keyboard.
+
+
+
+
+ To disable `:focus-visible`, set the Sass variable `$enable-focus-visible: false;`.
+
+
+
+ Toggle Focus
+
diff --git a/clayui.com/static/js/docs-site.js b/clayui.com/static/js/docs-site.js
index cda38c8f6c..385092441c 100644
--- a/clayui.com/static/js/docs-site.js
+++ b/clayui.com/static/js/docs-site.js
@@ -24,12 +24,18 @@ if (!Element.prototype.closest) {
document.addEventListener('click', function(event) {
var t = event.target;
- var a = t.tagName === 'a' ? t : t.closest('a');
+ var a = t.tagName === 'a' || t.tagName === 'button' ? t : t.closest('a') || t.closest('button');
if (a) {
if (a.getAttribute('href') === '#1') {
event.preventDefault();
}
+
+ var dataToggle = a.getAttribute('data-toggle');
+
+ if (dataToggle && dataToggle.startsWith('c-prefers')) {
+ document.querySelector('body').classList.toggle(a.getAttribute('data-toggle'));
+ }
}
});
})();
diff --git a/packages/clay-breadcrumb/src/__tests__/__snapshots__/index.tsx.snap b/packages/clay-breadcrumb/src/__tests__/__snapshots__/index.tsx.snap
index 3681da7eea..79dcfad618 100644
--- a/packages/clay-breadcrumb/src/__tests__/__snapshots__/index.tsx.snap
+++ b/packages/clay-breadcrumb/src/__tests__/__snapshots__/index.tsx.snap
@@ -9,7 +9,7 @@ exports[`ClayBreadcrumb calls callback when an item is clicked 1`] = `
@@ -59,7 +59,7 @@ exports[`ClayBreadcrumb renders 1`] = `
@@ -111,7 +111,7 @@ exports[`ClayBreadcrumb renders with properties passed by \`ellipsisProps\` 1`]
diff --git a/packages/clay-breadcrumb/src/index.tsx b/packages/clay-breadcrumb/src/index.tsx
index bc65c1bd48..ce402ca991 100644
--- a/packages/clay-breadcrumb/src/index.tsx
+++ b/packages/clay-breadcrumb/src/index.tsx
@@ -84,7 +84,6 @@ const ClayBreadcrumb = ({
setCollapsed(!collapsed)}
size="xs"
diff --git a/packages/clay-css/src/scss/atlas/variables/_custom-forms.scss b/packages/clay-css/src/scss/atlas/variables/_custom-forms.scss
index 77af1c517d..edb979725f 100644
--- a/packages/clay-css/src/scss/atlas/variables/_custom-forms.scss
+++ b/packages/clay-css/src/scss/atlas/variables/_custom-forms.scss
@@ -10,8 +10,7 @@ $custom-control-indicator-focus-box-shadow: $component-focus-box-shadow !default
$custom-control-indicator-active-bg: $white !default;
$custom-control-indicator-active-border-color: $custom-control-indicator-border-color !default;
-$custom-control-indicator-active-box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1),
- $custom-control-indicator-focus-box-shadow !default;
+$custom-control-indicator-active-box-shadow: c-unset !default;
$custom-control-indicator-disabled-bg: if(
variable-exists(input-disabled-bg),
diff --git a/packages/clay-css/src/scss/atlas/variables/_globals.scss b/packages/clay-css/src/scss/atlas/variables/_globals.scss
index f37cd39df1..f1b6c04f92 100644
--- a/packages/clay-css/src/scss/atlas/variables/_globals.scss
+++ b/packages/clay-css/src/scss/atlas/variables/_globals.scss
@@ -13,9 +13,17 @@ $clay-unset-placeholder: clay-unset-placeholder !default;
$atlas-theme: true !default;
$enable-bs4-deprecated: true !default;
+$enable-c-inner: true !default;
+$enable-focus-visible: true !default;
+
+$focus-visible-selector: if(
+ $enable-focus-visible,
+ '&:focus-visible',
+ '&:focus'
+) !default;
+
$enable-lexicon-flat-colors: true !default;
$enable-scaling-components: true !default;
-$enable-c-inner: true !default;
$scaling-breakpoint-down: sm !default;
// This enables Clay color functions to get the fallback color of a CSS Custom Property, convert it to the correct Sass type color, then process it using the corresponding Sass color function. The Clay color function will return a CSS color value. Set this variable to `false` if you want the Clay color function to return the CSS Custom Property without any modifications.
diff --git a/packages/clay-css/src/scss/cadmin/variables/_custom-forms.scss b/packages/clay-css/src/scss/cadmin/variables/_custom-forms.scss
index d1ab2da41b..18f0fb5892 100644
--- a/packages/clay-css/src/scss/cadmin/variables/_custom-forms.scss
+++ b/packages/clay-css/src/scss/cadmin/variables/_custom-forms.scss
@@ -17,9 +17,7 @@ $cadmin-custom-control-indicator-focus-border-color: $cadmin-custom-control-indi
$cadmin-custom-control-indicator-focus-box-shadow: $cadmin-component-focus-box-shadow !default;
$cadmin-custom-control-indicator-active-bg: $cadmin-white !default;
-$cadmin-custom-control-indicator-active-box-shadow: inset 0 0 0 1px
- rgba(0, 0, 0, 0.1),
- $cadmin-custom-control-indicator-focus-box-shadow !default;
+$cadmin-custom-control-indicator-active-box-shadow: c-unset !default;
$cadmin-custom-control-indicator-active-border-color: $cadmin-custom-control-indicator-border-color !default;
$cadmin-custom-control-indicator-active-color: $cadmin-component-active-color !default;
diff --git a/packages/clay-css/src/scss/cadmin/variables/_globals.scss b/packages/clay-css/src/scss/cadmin/variables/_globals.scss
index 1ee6d81a98..46c227c4ca 100644
--- a/packages/clay-css/src/scss/cadmin/variables/_globals.scss
+++ b/packages/clay-css/src/scss/cadmin/variables/_globals.scss
@@ -13,6 +13,15 @@ $cadmin-clay-unset-placeholder: clay-unset-placeholder !default;
$cadmin-enable-lexicon-flat-colors: true !default;
$cadmin-enable-scaling-components: true !default;
$cadmin-enable-c-inner: true !default;
+
+$cadmin-enable-focus-visible: true !default;
+
+$focus-visible-selector: if(
+ $cadmin-enable-focus-visible,
+ '&:focus-visible',
+ '&:focus'
+) !default;
+
$cadmin-scaling-breakpoint-down: sm !default;
// This enables Clay color functions to get the fallback color of a CSS Custom Property, convert it to the correct Sass type color, then process it using the corresponding Sass color function. The Clay color function will return a CSS color value. Set this variable to `false` if you want the Clay color function to return the CSS Custom Property without any modifications.
diff --git a/packages/clay-css/src/scss/mixins/_buttons.scss b/packages/clay-css/src/scss/mixins/_buttons.scss
index c9b9b9bb5f..c806169f1f 100644
--- a/packages/clay-css/src/scss/mixins/_buttons.scss
+++ b/packages/clay-css/src/scss/mixins/_buttons.scss
@@ -250,6 +250,31 @@
$breakpoint-down: map-get($map, breakpoint-down);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+
+ $_c-prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
+ @if (variable-exists(cadmin-enable-focus-visible)) and
+ ($_enable-focus-visible)
+ {
+ $_c-prefers-focus-selector: clay-insert-before(
+ '.cadmin',
+ '.c-prefers-focus '
+ );
+ }
+
$base: map-merge(
$map,
(
@@ -704,48 +729,51 @@
}
}
- &:focus,
- &.focus {
- @include clay-css($focus);
-
- &::before {
- @include clay-css(map-deep-get($map, focus, before));
- }
-
- &::after {
- @include clay-css(map-deep-get($map, focus, after));
- }
-
- &:hover {
- @include clay-css(map-deep-get($map, focus, hover));
+ @at-root {
+ &.focus,
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css($focus);
&::before {
- @include clay-css(
- map-deep-get($map, focus, hover, before)
- );
+ @include clay-css(map-deep-get($map, focus, before));
}
&::after {
- @include clay-css(
- map-deep-get($map, focus, hover, after)
- );
+ @include clay-css(map-deep-get($map, focus, after));
}
- }
- .inline-item {
- @include clay-css(map-get($focus, inline-item));
- }
+ &:hover {
+ @include clay-css(map-deep-get($map, focus, hover));
- .inline-item-before {
- @include clay-css(map-get($focus, inline-item-before));
- }
+ &::before {
+ @include clay-css(
+ map-deep-get($map, focus, hover, before)
+ );
+ }
- .inline-item-middle {
- @include clay-css(map-get($focus, inline-item-middle));
- }
+ &::after {
+ @include clay-css(
+ map-deep-get($map, focus, hover, after)
+ );
+ }
+ }
- .inline-item-after {
- @include clay-css(map-get($focus, inline-item-after));
+ .inline-item {
+ @include clay-css(map-get($focus, inline-item));
+ }
+
+ .inline-item-before {
+ @include clay-css(map-get($focus, inline-item-before));
+ }
+
+ .inline-item-middle {
+ @include clay-css(map-get($focus, inline-item-middle));
+ }
+
+ .inline-item-after {
+ @include clay-css(map-get($focus, inline-item-after));
+ }
}
}
@@ -760,19 +788,22 @@
@include clay-css(map-deep-get($map, active, after));
}
- &:focus {
- @include clay-css($active-focus);
+ @at-root {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css($active-focus);
- &::before {
- @include clay-css(
- map-deep-get($map, active, focus, before)
- );
- }
+ &::before {
+ @include clay-css(
+ map-deep-get($map, active, focus, before)
+ );
+ }
- &::after {
- @include clay-css(
- map-deep-get($map, active, focus, after)
- );
+ &::after {
+ @include clay-css(
+ map-deep-get($map, active, focus, after)
+ );
+ }
}
}
@@ -804,8 +835,13 @@
@include clay-css(map-get($map, active-class-after));
}
- &:focus {
- @include clay-css(map-deep-get($map, active-class, focus));
+ @at-root {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css(
+ map-deep-get($map, active-class, focus)
+ );
+ }
}
.inline-item {
@@ -843,19 +879,22 @@
@include clay-css(map-deep-get($map, disabled, after));
}
- &:focus {
- @include clay-css(map-get($disabled, focus));
+ @at-root {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css(map-get($disabled, focus));
- &::before {
- @include clay-css(
- map-deep-get($map, disabled, focus, before)
- );
- }
+ &::before {
+ @include clay-css(
+ map-deep-get($map, disabled, focus, before)
+ );
+ }
- &::after {
- @include clay-css(
- map-deep-get($map, disabled, focus, after)
- );
+ &::after {
+ @include clay-css(
+ map-deep-get($map, disabled, focus, after)
+ );
+ }
}
}
diff --git a/packages/clay-css/src/scss/mixins/_cards.scss b/packages/clay-css/src/scss/mixins/_cards.scss
index 37fc04bd7c..cb49bfc69e 100644
--- a/packages/clay-css/src/scss/mixins/_cards.scss
+++ b/packages/clay-css/src/scss/mixins/_cards.scss
@@ -297,6 +297,31 @@
@if (type-of($map) == 'map') {
$enabled: setter(map-get($map, enabled), true);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+
+ $_c-prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
+ @if (variable-exists(cadmin-enable-focus-visible)) and
+ ($_enable-focus-visible)
+ {
+ $_c-prefers-focus-selector: clay-insert-before(
+ '.cadmin',
+ '.c-prefers-focus '
+ );
+ }
+
$base: map-merge(
$map,
(
@@ -708,28 +733,31 @@
}
}
- &:focus,
- &.focus {
- @include clay-css($focus);
+ @at-root {
+ &.focus,
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css($focus);
- &::after {
- @include clay-css(map-get($focus, after));
- }
+ &::after {
+ @include clay-css(map-get($focus, after));
+ }
- .card-title {
- @include clay-link($focus-card-title);
- }
+ .card-title {
+ @include clay-link($focus-card-title);
+ }
- .card-subtitle {
- @include clay-link($focus-card-subtitle);
- }
+ .card-subtitle {
+ @include clay-link($focus-card-subtitle);
+ }
- .card-text {
- @include clay-link($focus-card-text);
- }
+ .card-text {
+ @include clay-link($focus-card-text);
+ }
- .card-link {
- @include clay-link($focus-card-link);
+ .card-link {
+ @include clay-link($focus-card-link);
+ }
}
}
diff --git a/packages/clay-css/src/scss/mixins/_close.scss b/packages/clay-css/src/scss/mixins/_close.scss
index a9502c7e3d..23a026b286 100644
--- a/packages/clay-css/src/scss/mixins/_close.scss
+++ b/packages/clay-css/src/scss/mixins/_close.scss
@@ -67,6 +67,31 @@
@if (type-of($map) == 'map') {
$enabled: setter(map-get($map, enabled), true);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+
+ $_c-prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
+ @if (variable-exists(cadmin-enable-focus-visible)) and
+ ($_enable-focus-visible)
+ {
+ $_c-prefers-focus-selector: clay-insert-before(
+ '.cadmin',
+ '.c-prefers-focus '
+ );
+ }
+
$base: map-merge(
$map,
(
@@ -356,14 +381,19 @@
@at-root {
button#{&} {
- &:focus {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
@include clay-css($btn-focus);
}
}
}
- &:focus {
- @include clay-css($focus);
+ @at-root {
+ &.focus,
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css($focus);
+ }
}
&:active {
diff --git a/packages/clay-css/src/scss/mixins/_custom-forms.scss b/packages/clay-css/src/scss/mixins/_custom-forms.scss
index 5b1a18e3e6..b4c3231f17 100644
--- a/packages/clay-css/src/scss/mixins/_custom-forms.scss
+++ b/packages/clay-css/src/scss/mixins/_custom-forms.scss
@@ -103,6 +103,31 @@
@if (type-of($map) == 'map') {
$enabled: setter(map-get($map, enabled), true);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+
+ $_c-prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
+ @if (variable-exists(cadmin-enable-focus-visible)) and
+ ($_enable-focus-visible)
+ {
+ $_c-prefers-focus-selector: clay-insert-before(
+ '.cadmin',
+ '.c-prefers-focus '
+ );
+ }
+
@if ($enabled) {
@include clay-css($map);
@@ -140,21 +165,36 @@
}
}
- &:focus {
- ~ .custom-control-label::before {
- @include clay-css(
- map-deep-get($map, focus, custom-control-label, before)
- );
- }
-
- ~ .custom-control-label::after {
- @include clay-css(
- map-deep-get($map, focus, custom-control-label, after)
- );
- }
-
- ~ .card {
- @include clay-card-variant(map-deep-get($map, focus, card));
+ @at-root {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ ~ .custom-control-label::before {
+ @include clay-css(
+ map-deep-get(
+ $map,
+ focus,
+ custom-control-label,
+ before
+ )
+ );
+ }
+
+ ~ .custom-control-label::after {
+ @include clay-css(
+ map-deep-get(
+ $map,
+ focus,
+ custom-control-label,
+ after
+ )
+ );
+ }
+
+ ~ .card {
+ @include clay-card-variant(
+ map-deep-get($map, focus, card)
+ );
+ }
}
}
@@ -384,35 +424,40 @@
}
}
- &:checked:focus {
- ~ .custom-control-label::before {
- @include clay-css(
- map-deep-get(
- $map,
- checked,
- focus,
- custom-control-label,
- before
- )
- );
- }
-
- ~ .custom-control-label::after {
- @include clay-css(
- map-deep-get(
- $map,
- checked,
- focus,
- custom-control-label,
- after
- )
- );
- }
-
- ~ .card {
- @include clay-card-variant(
- map-deep-get($map, checked, focus, card)
- );
+ @at-root {
+ &:checked {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ ~ .custom-control-label::before {
+ @include clay-css(
+ map-deep-get(
+ $map,
+ checked,
+ focus,
+ custom-control-label,
+ before
+ )
+ );
+ }
+
+ ~ .custom-control-label::after {
+ @include clay-css(
+ map-deep-get(
+ $map,
+ checked,
+ focus,
+ custom-control-label,
+ after
+ )
+ );
+ }
+
+ ~ .card {
+ @include clay-card-variant(
+ map-deep-get($map, checked, focus, card)
+ );
+ }
+ }
}
}
@@ -609,35 +654,40 @@
}
}
- &:indeterminate:focus {
- ~ .custom-control-label::before {
- @include clay-css(
- map-deep-get(
- $map,
- indeterminate,
- focus,
- custom-control-label,
- before
- )
- );
- }
-
- ~ .custom-control-label::after {
- @include clay-css(
- map-deep-get(
- $map,
- indeterminate,
- focus,
- custom-control-label,
- after
- )
- );
- }
-
- ~ .card {
- @include clay-card-variant(
- map-deep-get($map, indeterminate, focus, card)
- );
+ @at-root {
+ &:indeterminate {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ ~ .custom-control-label::before {
+ @include clay-css(
+ map-deep-get(
+ $map,
+ indeterminate,
+ focus,
+ custom-control-label,
+ before
+ )
+ );
+ }
+
+ ~ .custom-control-label::after {
+ @include clay-css(
+ map-deep-get(
+ $map,
+ indeterminate,
+ focus,
+ custom-control-label,
+ after
+ )
+ );
+ }
+
+ ~ .card {
+ @include clay-card-variant(
+ map-deep-get($map, indeterminate, focus, card)
+ );
+ }
+ }
}
}
diff --git a/packages/clay-css/src/scss/mixins/_dropdown-menu.scss b/packages/clay-css/src/scss/mixins/_dropdown-menu.scss
index 84ba31292c..322faed2d7 100644
--- a/packages/clay-css/src/scss/mixins/_dropdown-menu.scss
+++ b/packages/clay-css/src/scss/mixins/_dropdown-menu.scss
@@ -354,6 +354,26 @@
setter(map-get($map, hover-c-kbd-inline), ())
);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+ $_focus-selector: if(
+ $_enable-focus-visible,
+ '&:focus-visible',
+ '&:focus'
+ );
+ $_prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
$focus: setter(map-get($map, focus), ());
$focus: map-deep-merge(
$focus,
@@ -624,20 +644,23 @@
}
}
- &:focus,
- &.focus {
- @include clay-css($focus);
+ @at-root {
+ &.focus,
+ #{$_focus-selector},
+ #{$_prefers-focus-selector} {
+ @include clay-css($focus);
- &::before {
- @include clay-css(map-get($focus, before));
- }
+ &::before {
+ @include clay-css(map-get($focus, before));
+ }
- &::after {
- @include clay-css(map-get($focus, after));
- }
+ &::after {
+ @include clay-css(map-get($focus, after));
+ }
- .c-kbd-inline {
- @include clay-css($focus-c-kbd-inline);
+ .c-kbd-inline {
+ @include clay-css($focus-c-kbd-inline);
+ }
}
}
@@ -702,10 +725,13 @@
// Overwrite Bootstrap's Ensure active button styles are not applied to disabled buttons
// https://github.com/twbs/bootstrap/commit/de3973b5e74058e37fd15fecc4cb7b9fd3409def
- &.btn:not([disabled]):not(.disabled):active,
- &.btn:not([disabled]):not(.disabled).active {
- &:focus {
- box-shadow: map-get($focus, box-shadow);
+ @at-root {
+ &.btn:not([disabled]):not(.disabled):active,
+ &.btn:not([disabled]):not(.disabled).active {
+ #{$_focus-selector},
+ #{$_prefers-focus-selector} {
+ box-shadow: map-get($focus, box-shadow);
+ }
}
}
diff --git a/packages/clay-css/src/scss/mixins/_forms.scss b/packages/clay-css/src/scss/mixins/_forms.scss
index 9732109e49..bfe75d935a 100644
--- a/packages/clay-css/src/scss/mixins/_forms.scss
+++ b/packages/clay-css/src/scss/mixins/_forms.scss
@@ -297,6 +297,31 @@
@if (type-of($map) == 'map') {
$enabled: setter(map-get($map, enabled), true);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+
+ $_c-prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
+ @if (variable-exists(cadmin-enable-focus-visible)) and
+ ($_enable-focus-visible)
+ {
+ $_c-prefers-focus-selector: clay-insert-before(
+ '.cadmin',
+ '.c-prefers-focus '
+ );
+ }
+
$base: setter($map, ());
$base: map-merge(
$map,
@@ -558,18 +583,21 @@
}
}
- &:focus,
- &.focus {
- @include clay-css($focus);
+ @at-root {
+ &.focus,
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css($focus);
- &::placeholder {
- @include clay-css($focus-placeholder);
- }
+ &::placeholder {
+ @include clay-css($focus-placeholder);
+ }
- ~ .input-group-inset-item {
- @include clay-css(
- map-deep-get($map, focus, input-group-inset-item)
- );
+ ~ .input-group-inset-item {
+ @include clay-css(
+ map-deep-get($map, focus, input-group-inset-item)
+ );
+ }
}
}
@@ -713,6 +741,31 @@
@if (type-of($map) == 'map') {
$enabled: setter(map-get($map, enabled), true);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+
+ $_c-prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
+ @if (variable-exists(cadmin-enable-focus-visible)) and
+ ($_enable-focus-visible)
+ {
+ $_c-prefers-focus-selector: clay-insert-before(
+ '.cadmin',
+ '.c-prefers-focus '
+ );
+ }
+
$base: map-merge(
$map,
(
@@ -888,21 +941,24 @@
}
}
- &:focus,
- &.focus {
- @include clay-css($focus);
+ @at-root {
+ &.focus,
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css($focus);
- > option {
- $focus-option: setter(map-get($focus, option), ());
+ > option {
+ $focus-option: setter(map-get($focus, option), ());
- @include clay-css($focus-option);
+ @include clay-css($focus-option);
- &:hover {
- @include clay-css(map-get($focus-option, hover));
- }
+ &:hover {
+ @include clay-css(map-get($focus-option, hover));
+ }
- &:checked {
- @include clay-css(map-get($focus-option, checked));
+ &:checked {
+ @include clay-css(map-get($focus-option, checked));
+ }
}
}
}
@@ -1020,30 +1076,36 @@
}
}
- &:focus,
- &.focus {
- $ff-only-focus: setter(map-get($ff-only, focus), ());
-
- @include clay-css($ff-only-focus);
-
- > option {
- $ff-only-focus-option: setter(
- map-get($ff-only-focus, option),
+ @at-root {
+ &.focus,
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ $ff-only-focus: setter(
+ map-get($ff-only, focus),
()
);
- @include clay-css($ff-only-focus-option);
+ @include clay-css($ff-only-focus);
- &:hover {
- @include clay-css(
- map-get($ff-only-focus-option, hover)
+ > option {
+ $ff-only-focus-option: setter(
+ map-get($ff-only-focus, option),
+ ()
);
- }
- &:checked {
- @include clay-css(
- map-get($ff-only-focus-option, checked)
- );
+ @include clay-css($ff-only-focus-option);
+
+ &:hover {
+ @include clay-css(
+ map-get($ff-only-focus-option, hover)
+ );
+ }
+
+ &:checked {
+ @include clay-css(
+ map-get($ff-only-focus-option, checked)
+ );
+ }
}
}
}
@@ -1553,6 +1615,31 @@
@if (type-of($map) == 'map') {
$enabled: setter(map-get($map, enabled), true);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+
+ $_c-prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
+ @if (variable-exists(cadmin-enable-focus-visible)) and
+ ($_enable-focus-visible)
+ {
+ $_c-prefers-focus-selector: clay-insert-before(
+ '.cadmin',
+ '.c-prefers-focus '
+ );
+ }
+
$clay-range-thumb: setter(map-get($map, clay-range-thumb), ());
$clay-range-thumb: map-merge(
$clay-range-thumb,
@@ -2432,51 +2519,54 @@
}
}
- &:focus,
- &.focus {
- @include clay-css($focus);
+ @at-root {
+ &.focus,
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css($focus);
- ~ .clay-range-track {
- @include clay-css(
- map-deep-get(
- $map,
- form-control-range,
- focus,
- clay-range-track
- )
- );
- }
+ ~ .clay-range-track {
+ @include clay-css(
+ map-deep-get(
+ $map,
+ form-control-range,
+ focus,
+ clay-range-track
+ )
+ );
+ }
- ~ .clay-range-progress {
- @include clay-css(
- map-deep-get(
- $map,
- form-control-range,
- focus,
- clay-range-progress
- )
- );
+ ~ .clay-range-progress {
+ @include clay-css(
+ map-deep-get(
+ $map,
+ form-control-range,
+ focus,
+ clay-range-progress
+ )
+ );
- .clay-range-thumb {
- @include clay-css($focus-clay-range-thumb);
- }
+ .clay-range-thumb {
+ @include clay-css($focus-clay-range-thumb);
+ }
- .tooltip {
- visibility: visible;
- opacity: 1;
+ .tooltip {
+ visibility: visible;
+ opacity: 1;
+ }
}
- }
- &::-moz-range-thumb {
- @include clay-css($focus-clay-range-thumb);
- }
+ &::-moz-range-thumb {
+ @include clay-css($focus-clay-range-thumb);
+ }
- &::-ms-thumb {
- @include clay-css($focus-clay-range-thumb);
- }
+ &::-ms-thumb {
+ @include clay-css($focus-clay-range-thumb);
+ }
- &::-webkit-slider-thumb {
- @include clay-css($focus-clay-range-thumb);
+ &::-webkit-slider-thumb {
+ @include clay-css($focus-clay-range-thumb);
+ }
}
}
diff --git a/packages/clay-css/src/scss/mixins/_links.scss b/packages/clay-css/src/scss/mixins/_links.scss
index d233be5c64..371765ab32 100644
--- a/packages/clay-css/src/scss/mixins/_links.scss
+++ b/packages/clay-css/src/scss/mixins/_links.scss
@@ -253,6 +253,31 @@
@if (type-of($map) == 'map') {
$enabled: setter(map-get($map, enabled), true);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+
+ $_c-prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
+ @if (variable-exists(cadmin-enable-focus-visible)) and
+ ($_enable-focus-visible)
+ {
+ $_c-prefers-focus-selector: clay-insert-before(
+ '.cadmin',
+ '.c-prefers-focus '
+ );
+ }
+
$base: map-merge(
$map,
(
@@ -649,32 +674,35 @@
}
}
- &.focus,
- &:focus {
- @include clay-css($focus);
+ @at-root {
+ &.focus,
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css($focus);
- &::before {
- @include clay-css(map-get($focus, before));
- }
+ &::before {
+ @include clay-css(map-get($focus, before));
+ }
- &::after {
- @include clay-css(map-get($focus, after));
- }
+ &::after {
+ @include clay-css(map-get($focus, after));
+ }
- .inline-item {
- @include clay-css(map-get($focus, inline-item));
- }
+ .inline-item {
+ @include clay-css(map-get($focus, inline-item));
+ }
- .inline-item-before {
- @include clay-css(map-get($focus, inline-item-before));
- }
+ .inline-item-before {
+ @include clay-css(map-get($focus, inline-item-before));
+ }
- .inline-item-middle {
- @include clay-css(map-get($focus, inline-item-middle));
- }
+ .inline-item-middle {
+ @include clay-css(map-get($focus, inline-item-middle));
+ }
- .inline-item-after {
- @include clay-css(map-get($focus, inline-item-after));
+ .inline-item-after {
+ @include clay-css(map-get($focus, inline-item-after));
+ }
}
}
@@ -689,17 +717,20 @@
@include clay-css(map-get($active, after));
}
- &:focus {
- $_active-focus: setter(map-get($active, focus), ());
+ @at-root {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ $_active-focus: setter(map-get($active, focus), ());
- @include clay-css($_active-focus);
+ @include clay-css($_active-focus);
- &::before {
- @include clay-css(map-get($_active-focus, before));
- }
+ &::before {
+ @include clay-css(map-get($_active-focus, before));
+ }
- &::after {
- @include clay-css(map-get($_active-focus, after));
+ &::after {
+ @include clay-css(map-get($_active-focus, after));
+ }
}
}
@@ -731,22 +762,27 @@
@include clay-css(map-get($active-class, after));
}
- &:focus {
- $_active-class-focus: setter(
- map-get($active-class, focus),
- ()
- );
+ @at-root {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ $_active-class-focus: setter(
+ map-get($active-class, focus),
+ ()
+ );
- @include clay-css($_active-class-focus);
+ @include clay-css($_active-class-focus);
- &::before {
- @include clay-css(
- map-get($_active-class-focus, before)
- );
- }
+ &::before {
+ @include clay-css(
+ map-get($_active-class-focus, before)
+ );
+ }
- &::after {
- @include clay-css(map-get($_active-class-focus, after));
+ &::after {
+ @include clay-css(
+ map-get($_active-class-focus, after)
+ );
+ }
}
}
@@ -785,17 +821,22 @@
@include clay-css(map-get($disabled, after));
}
- &:focus {
- $_disabled-focus: setter(map-get($disabled, focus), ());
+ @at-root {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ $_disabled-focus: setter(map-get($disabled, focus), ());
- @include clay-css($_disabled-focus);
+ @include clay-css($_disabled-focus);
- &::before {
- @include clay-css(map-get($_disabled-focus, before));
- }
+ &::before {
+ @include clay-css(
+ map-get($_disabled-focus, before)
+ );
+ }
- &::after {
- @include clay-css(map-get($_disabled-focus, after));
+ &::after {
+ @include clay-css(map-get($_disabled-focus, after));
+ }
}
}
@@ -829,8 +870,11 @@
}
&[type] {
- &:focus {
- @include clay-css($btn-focus);
+ @at-root {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css($btn-focus);
+ }
}
}
@@ -860,17 +904,20 @@
}
}
- &:focus {
- $_show-focus: setter(map-get($show, focus), ());
+ @at-root {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ $_show-focus: setter(map-get($show, focus), ());
- @include clay-css($_show-focus);
+ @include clay-css($_show-focus);
- &::before {
- @include clay-css(map-get($_show-focus, before));
- }
+ &::before {
+ @include clay-css(map-get($_show-focus, before));
+ }
- &::after {
- @include clay-css(map-get($_show-focus, after));
+ &::after {
+ @include clay-css(map-get($_show-focus, after));
+ }
}
}
diff --git a/packages/clay-css/src/scss/mixins/_modals.scss b/packages/clay-css/src/scss/mixins/_modals.scss
index 86f0870933..312443e4a9 100644
--- a/packages/clay-css/src/scss/mixins/_modals.scss
+++ b/packages/clay-css/src/scss/mixins/_modals.scss
@@ -24,6 +24,31 @@
@if (type-of($map) == 'map') {
$enabled: setter(map-get($map, enabled), true);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+
+ $_c-prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
+ @if (variable-exists(cadmin-enable-focus-visible)) and
+ ($_enable-focus-visible)
+ {
+ $_c-prefers-focus-selector: clay-insert-before(
+ '.cadmin',
+ '.c-prefers-focus '
+ );
+ }
+
$header: setter(map-get($map, modal-header), map-get($map, header), ());
$header: map-merge(
$header,
@@ -144,10 +169,16 @@
@include clay-close($header-close);
}
- button.close {
- &:focus {
- box-shadow: map-get($header-close-btn-focus, box-shadow);
- outline: map-get($header-close-btn-focus, outline);
+ @at-root {
+ button.close {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ box-shadow: map-get(
+ $header-close-btn-focus,
+ box-shadow
+ );
+ outline: map-get($header-close-btn-focus, outline);
+ }
}
}
diff --git a/packages/clay-css/src/scss/mixins/_sidebar.scss b/packages/clay-css/src/scss/mixins/_sidebar.scss
index 91882edd6f..2b809d2b02 100644
--- a/packages/clay-css/src/scss/mixins/_sidebar.scss
+++ b/packages/clay-css/src/scss/mixins/_sidebar.scss
@@ -104,6 +104,31 @@
@if (type-of($map) == 'map') {
$enabled: setter(map-get($map, enabled), true);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+
+ $_c-prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
+ @if (variable-exists(cadmin-enable-focus-visible)) and
+ ($_enable-focus-visible)
+ {
+ $_c-prefers-focus-selector: clay-insert-before(
+ '.cadmin',
+ '.c-prefers-focus '
+ );
+ }
+
$base: map-merge(
$map,
(
@@ -239,8 +264,9 @@
@include clay-css($sidenav-start);
- &:focus,
- &.focus {
+ &.focus,
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
@include clay-css(map-get($sidenav-start, focus));
}
}
@@ -251,16 +277,20 @@
@include clay-css($sidenav-end);
- &:focus,
- &.focus {
+ &.focus,
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
@include clay-css(map-get($sidenav-end, focus));
}
}
}
- &:focus,
- &.focus {
- @include clay-css(map-get($map, focus));
+ @at-root {
+ &.focus,
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css(map-get($map, focus));
+ }
}
.component-link {
diff --git a/packages/clay-css/src/scss/mixins/_slideout.scss b/packages/clay-css/src/scss/mixins/_slideout.scss
index c797f6caf1..94d4c941c7 100644
--- a/packages/clay-css/src/scss/mixins/_slideout.scss
+++ b/packages/clay-css/src/scss/mixins/_slideout.scss
@@ -20,6 +20,31 @@
@if (type-of($map) == 'map') {
$enabled: setter(map-get($map, enabled), true);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+
+ $_c-prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
+ @if (variable-exists(cadmin-enable-focus-visible)) and
+ ($_enable-focus-visible)
+ {
+ $_c-prefers-focus-selector: clay-insert-before(
+ '.cadmin',
+ '.c-prefers-focus '
+ );
+ }
+
@if ($enabled) {
@include clay-css($map);
@@ -87,8 +112,13 @@
@include clay-css(map-get($_c-horizontal-resizer, hover));
}
- &:focus {
- @include clay-css(map-get($_c-horizontal-resizer, focus));
+ @at-root {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ @include clay-css(
+ map-get($_c-horizontal-resizer, focus)
+ );
+ }
}
}
}
diff --git a/packages/clay-css/src/scss/mixins/_toggle-switch.scss b/packages/clay-css/src/scss/mixins/_toggle-switch.scss
index 38a34211e3..7266019a08 100644
--- a/packages/clay-css/src/scss/mixins/_toggle-switch.scss
+++ b/packages/clay-css/src/scss/mixins/_toggle-switch.scss
@@ -646,6 +646,31 @@
$breakpoint-down: setter(map-get($map, breakpoint-down), sm);
$enabled: setter(map-get($map, enabled), true);
+ $_enable-focus-visible: if(
+ variable-exists(enable-focus-visible),
+ $enable-focus-visible,
+ if(
+ variable-exists(cadmin-enable-focus-visible),
+ $cadmin-enable-focus-visible,
+ true
+ )
+ );
+
+ $_c-prefers-focus-selector: if(
+ $_enable-focus-visible,
+ '.c-prefers-focus &:focus',
+ ''
+ );
+
+ @if (variable-exists(cadmin-enable-focus-visible)) and
+ ($_enable-focus-visible)
+ {
+ $_c-prefers-focus-selector: clay-insert-before(
+ '.cadmin',
+ '.c-prefers-focus '
+ );
+ }
+
@include clay-css($map);
@if ($enabled) {
@@ -661,10 +686,15 @@
);
}
- &:focus ~ .toggle-switch-bar {
- @include clay-toggle-switch-bar-variant(
- map-deep-get($map, focus, toggle-switch-bar)
- );
+ @at-root {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ ~ .toggle-switch-bar {
+ @include clay-toggle-switch-bar-variant(
+ map-deep-get($map, focus, toggle-switch-bar)
+ );
+ }
+ }
}
&:active ~ .toggle-switch-bar {
@@ -692,10 +722,22 @@
);
}
- &:checked:focus ~ .toggle-switch-bar {
- @include clay-toggle-switch-bar-variant(
- map-deep-get($map, checked, focus, toggle-switch-bar)
- );
+ @at-root {
+ &:checked {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ ~ .toggle-switch-bar {
+ @include clay-toggle-switch-bar-variant(
+ map-deep-get(
+ $map,
+ checked,
+ focus,
+ toggle-switch-bar
+ )
+ );
+ }
+ }
+ }
}
&:checked:active ~ .toggle-switch-bar {
@@ -723,10 +765,22 @@
);
}
- &:indeterminate:focus ~ .toggle-switch-bar {
- @include clay-toggle-switch-bar-variant(
- map-deep-get($map, indeterminate, focus, toggle-switch-bar)
- );
+ @at-root {
+ &:indeterminate {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ ~ .toggle-switch-bar {
+ @include clay-toggle-switch-bar-variant(
+ map-deep-get(
+ $map,
+ indeterminate,
+ focus,
+ toggle-switch-bar
+ )
+ );
+ }
+ }
+ }
}
&:indeterminate:active ~ .toggle-switch-bar {
@@ -762,10 +816,20 @@
);
}
- &:focus ~ .toggle-switch-bar {
- @include clay-toggle-switch-bar-variant(
- map-deep-get($map, mobile, focus, toggle-switch-bar)
- );
+ @at-root {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ ~ .toggle-switch-bar {
+ @include clay-toggle-switch-bar-variant(
+ map-deep-get(
+ $map,
+ mobile,
+ focus,
+ toggle-switch-bar
+ )
+ );
+ }
+ }
}
&:active ~ .toggle-switch-bar {
@@ -799,16 +863,23 @@
);
}
- &:checked:focus ~ .toggle-switch-bar {
- @include clay-toggle-switch-bar-variant(
- map-deep-get(
- $map,
- mobile,
- checked,
- focus,
- toggle-switch-bar
- )
- );
+ @at-root {
+ &:checked {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ ~ .toggle-switch-bar {
+ @include clay-toggle-switch-bar-variant(
+ map-deep-get(
+ $map,
+ mobile,
+ checked,
+ focus,
+ toggle-switch-bar
+ )
+ );
+ }
+ }
+ }
}
&:checked:active ~ .toggle-switch-bar {
@@ -859,16 +930,23 @@
);
}
- &:indeterminate:focus ~ .toggle-switch-bar {
- @include clay-toggle-switch-bar-variant(
- map-deep-get(
- $map,
- mobile,
- indeterminate,
- focus,
- toggle-switch-bar
- )
- );
+ @at-root {
+ &:indeterminate {
+ #{$focus-visible-selector},
+ #{$_c-prefers-focus-selector} {
+ ~ .toggle-switch-bar {
+ @include clay-toggle-switch-bar-variant(
+ map-deep-get(
+ $map,
+ mobile,
+ indeterminate,
+ focus,
+ toggle-switch-bar
+ )
+ );
+ }
+ }
+ }
}
&:indeterminate:active ~ .toggle-switch-bar {
diff --git a/packages/clay-css/src/scss/variables/_globals.scss b/packages/clay-css/src/scss/variables/_globals.scss
index d5a896923c..3daf34fce4 100644
--- a/packages/clay-css/src/scss/variables/_globals.scss
+++ b/packages/clay-css/src/scss/variables/_globals.scss
@@ -16,6 +16,14 @@ $clay-unset-placeholder: clay-unset-placeholder !default;
$enable-bs4-deprecated: true !default;
$enable-c-inner: true !default;
+$enable-focus-visible: true !default;
+
+$focus-visible-selector: if(
+ $enable-focus-visible,
+ '&:focus-visible',
+ '&:focus'
+) !default;
+
$enable-lexicon-flat-colors: false !default;
$enable-scaling-components: false !default;
$scaling-breakpoint-down: sm !default;