mirror of
https://github.com/tabler/tabler.git
synced 2026-10-14 06:07:07 +04:00
One focus-ring() mixin over a --focus-ring-box-shadow token (#3018)
This commit is contained in:
1 parent
504c8473ae
commit
a7f2be029a
18 files changed
+66
-37
No files matched your search
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Updated `focus-ring()` to be the single focus mixin and added a runtime `--focus-ring-box-shadow` token.
|
||||
@@ -253,6 +253,15 @@ of `color-scheme`, the token-dump verification harness) but not its code.
|
||||
- Decide on `$spacers`: adopting the v6 0–9 scale silently changes every `.p-3` / `.m-4` in every
|
||||
Tabler template. Recommendation: keep the v5 scale, add finer steps at new keys.
|
||||
- Replace all `$*-focus-box-shadow` with one `focus-ring()` mixin over `--focus-ring*` tokens.
|
||||
Done (#2972). Step 1: `focus-ring()` is the one implementation and every focus consumer calls it;
|
||||
the `$*-focus-box-shadow` variables stay as `!default` aliases; CSS byte-identical. Step 2: `:root`
|
||||
emits `--focus-ring-inner-width` and `--focus-ring-box-shadow`, the mixin reads the token so the
|
||||
ring retunes at runtime and per theme, and the `.focus-ring` helper stops referencing the phantom
|
||||
`--focus-ring-x/-y/-blur`; the Step 2 CSS diff is limited to focus declarations and the `:root`
|
||||
tokens. Tabler keeps the two-layer `box-shadow` look, not v6's `outline`, and the `forced-colors`
|
||||
fallback in `layout/_accessibility.scss` stays. `.form-select` stays a single-layer exception, and
|
||||
the three `outline: 2px solid` rules (`.btn-action`, `.date-item`, `.switch-icon`) are not
|
||||
converted — both are follow-ups.
|
||||
- Consider the layered shadow scale (`.shadow-xs`…`.shadow-xl`) and `.border-keyline`.
|
||||
- Skip the `.fs-*` renaming — it inverts the scale direction and breaks every page.
|
||||
|
||||
|
||||
@@ -1017,11 +1017,12 @@ $focus-ring-width: 0.25rem !default;
|
||||
$focus-ring-opacity: 0.25 !default;
|
||||
$focus-ring-color: color-mix(in srgb, var(--primary) #{math.percentage($focus-ring-opacity)}, transparent) !default;
|
||||
$focus-ring-blur: 0 !default;
|
||||
// Inner 2px solid ring keeps the indicator above the 3:1 non-text contrast minimum;
|
||||
// the translucent halo preserves the soft look
|
||||
$focus-ring-box-shadow:
|
||||
0 0 0 2px var(--primary),
|
||||
0 0 $focus-ring-blur $focus-ring-width $focus-ring-color !default;
|
||||
$focus-ring-inner-width: 2px !default;
|
||||
// The literal, emitted once as `--focus-ring-box-shadow` (`bootstrap/_root.scss`).
|
||||
$focus-ring-box-shadow-value:
|
||||
0 0 0 var(--focus-ring-inner-width) var(--primary),
|
||||
0 0 $focus-ring-blur var(--focus-ring-width) var(--focus-ring-color) !default;
|
||||
$focus-ring-box-shadow: var(--focus-ring-box-shadow) !default;
|
||||
|
||||
// Transitions
|
||||
$transition-base: all 0.2s ease-in-out !default;
|
||||
|
||||
@@ -41,8 +41,7 @@
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 0;
|
||||
box-shadow: $nav-link-focus-box-shadow;
|
||||
@include focus-ring($shadow: $nav-link-focus-box-shadow);
|
||||
}
|
||||
|
||||
// Disabled state lightens text
|
||||
|
||||
@@ -142,6 +142,8 @@
|
||||
--focus-ring-width: #{$focus-ring-width};
|
||||
--focus-ring-opacity: #{$focus-ring-opacity};
|
||||
--focus-ring-color: #{$focus-ring-color};
|
||||
--focus-ring-inner-width: #{$focus-ring-inner-width};
|
||||
--focus-ring-box-shadow: #{$focus-ring-box-shadow-value};
|
||||
// scss-docs-end root-focus-variables
|
||||
|
||||
// scss-docs-start root-form-validation-variables
|
||||
|
||||
@@ -61,8 +61,7 @@
|
||||
|
||||
&:focus {
|
||||
border-color: $form-check-input-focus-border;
|
||||
outline: 0;
|
||||
box-shadow: $form-check-input-focus-box-shadow;
|
||||
@include focus-ring($shadow: $form-check-input-focus-box-shadow);
|
||||
}
|
||||
|
||||
&:checked {
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
// Pseudo-elements must be split across multiple rulesets to have an effect.
|
||||
// No box-shadow() mixin for focus accessibility.
|
||||
&::-webkit-slider-thumb {
|
||||
box-shadow: $form-range-thumb-focus-box-shadow;
|
||||
@include focus-ring($shadow: $form-range-thumb-focus-box-shadow, $outline: null);
|
||||
}
|
||||
&::-moz-range-thumb {
|
||||
box-shadow: $form-range-thumb-focus-box-shadow;
|
||||
@include focus-ring($shadow: $form-range-thumb-focus-box-shadow, $outline: null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +141,5 @@
|
||||
//
|
||||
.focus-ring:focus {
|
||||
outline: 0;
|
||||
// By default, there is no `--bs-focus-ring-x`, `--bs-focus-ring-y`, or `--bs-focus-ring-blur`, but we provide CSS variables with fallbacks to initial `0` values
|
||||
box-shadow: var(--focus-ring-x, 0) var(--focus-ring-y, 0) var(--focus-ring-blur, 0) var(--focus-ring-width) var(--focus-ring-color);
|
||||
box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
|
||||
}
|
||||
@@ -77,14 +77,15 @@
|
||||
gap: var(--list-gap);
|
||||
}
|
||||
|
||||
@mixin focus-ring($show-border: false) {
|
||||
outline: 0;
|
||||
box-shadow:
|
||||
0 0 0 2px var(--primary),
|
||||
0 0 $focus-ring-blur $focus-ring-width color-transparent(var(--primary), 0.25);
|
||||
@mixin focus-ring($shadow: $focus-ring-box-shadow, $show-border: false, $outline: 0) {
|
||||
@if $outline != null {
|
||||
outline: $outline;
|
||||
}
|
||||
|
||||
@if ($show-border) {
|
||||
border-color: color-transparent(var(--primary), 0.25);
|
||||
box-shadow: $shadow;
|
||||
|
||||
@if $show-border {
|
||||
border-color: var(--focus-ring-color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
@use '../../settings' as *;
|
||||
@use '../../variables' as *;
|
||||
@use '../functions' as *;
|
||||
@use '../mixins' as *;
|
||||
@use 'breakpoints' as *;
|
||||
// This mixin uses an `if()` technique to be compatible with Dart Sass
|
||||
// See https://github.com/sass/sass/issues/1873#issuecomment-152293725 for more details
|
||||
@@ -70,7 +71,7 @@
|
||||
@if $enable-shadows {
|
||||
@include box-shadow($input-box-shadow, $focus-box-shadow);
|
||||
} @else {
|
||||
box-shadow: $focus-box-shadow;
|
||||
@include focus-ring($shadow: $focus-box-shadow, $outline: null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,7 +106,7 @@
|
||||
@if $enable-shadows {
|
||||
@include box-shadow($form-select-box-shadow, $focus-box-shadow);
|
||||
} @else {
|
||||
box-shadow: $focus-box-shadow;
|
||||
@include focus-ring($shadow: $focus-box-shadow, $outline: null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,7 +129,7 @@
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: $focus-box-shadow;
|
||||
@include focus-ring($shadow: $focus-box-shadow, $outline: null);
|
||||
}
|
||||
|
||||
~ .form-check-label {
|
||||
|
||||
@@ -55,6 +55,8 @@ exports[`css custom-property prefixing > leaves vendor-owned names alone and pre
|
||||
"--tblr-chart-3",
|
||||
"--tblr-chart-4",
|
||||
"--tblr-chart-5",
|
||||
"--tblr-focus-ring-box-shadow",
|
||||
"--tblr-focus-ring-color",
|
||||
"--tblr-font-sans-serif",
|
||||
"--tblr-font-size-h3",
|
||||
"--tblr-font-size-h5",
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
}
|
||||
|
||||
@include describe('focus-ring mixin') {
|
||||
@include it('outputs the ring without a border by default') {
|
||||
@include it('outputs the ring token without a border by default') {
|
||||
@include assert() {
|
||||
@include output() {
|
||||
.t {
|
||||
@@ -114,9 +114,7 @@
|
||||
@include expect() {
|
||||
.t {
|
||||
outline: 0;
|
||||
box-shadow:
|
||||
0 0 0 2px var(--primary),
|
||||
0 0 0 0.25rem color-mix(in srgb, var(--primary) 25%, transparent);
|
||||
box-shadow: var(--focus-ring-box-shadow);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,10 +130,23 @@
|
||||
@include expect() {
|
||||
.t {
|
||||
outline: 0;
|
||||
box-shadow:
|
||||
0 0 0 2px var(--primary),
|
||||
0 0 0 0.25rem color-mix(in srgb, var(--primary) 25%, transparent);
|
||||
border-color: color-mix(in srgb, var(--primary) 25%, transparent);
|
||||
box-shadow: var(--focus-ring-box-shadow);
|
||||
border-color: var(--focus-ring-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include it('passes $shadow through and skips the outline reset with $outline: null') {
|
||||
@include assert() {
|
||||
@include output() {
|
||||
.t {
|
||||
@include focus-ring($shadow: 0 0 0 1px red, $outline: null);
|
||||
}
|
||||
}
|
||||
@include expect() {
|
||||
.t {
|
||||
box-shadow: 0 0 0 1px red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ Input group
|
||||
|
||||
.input-group-flat {
|
||||
&:focus-within {
|
||||
box-shadow: $input-focus-box-shadow;
|
||||
@include focus-ring($shadow: $input-focus-box-shadow, $outline: null);
|
||||
@include border-radius($input-border-radius);
|
||||
|
||||
.form-control,
|
||||
|
||||
@@ -46,7 +46,7 @@ Color Input
|
||||
|
||||
.form-colorinput-input:focus ~ & {
|
||||
border-color: var(--primary);
|
||||
box-shadow: $input-btn-focus-box-shadow;
|
||||
@include focus-ring($shadow: $input-btn-focus-box-shadow, $outline: null);
|
||||
}
|
||||
|
||||
@at-root .form-colorinput-light & {
|
||||
|
||||
@@ -28,7 +28,7 @@ Image check
|
||||
|
||||
.form-imagecheck-input:focus ~ & {
|
||||
border-color: var(--primary);
|
||||
box-shadow: $input-btn-focus-box-shadow;
|
||||
@include focus-ring($shadow: $input-btn-focus-box-shadow, $outline: null);
|
||||
}
|
||||
|
||||
.form-imagecheck-input:checked ~ & {
|
||||
|
||||
@@ -111,7 +111,7 @@ Select group
|
||||
z-index: 2;
|
||||
color: var(--primary);
|
||||
border-color: var(--primary);
|
||||
box-shadow: $input-btn-focus-box-shadow;
|
||||
@include focus-ring($shadow: $input-btn-focus-box-shadow, $outline: null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+1
-1
@@ -17,7 +17,7 @@ input.clr-color {
|
||||
border-color: var(--border-color);
|
||||
|
||||
&:focus {
|
||||
@include focus-ring(true);
|
||||
@include focus-ring($show-border: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -43,7 +43,7 @@
|
||||
|
||||
&.noUi-active,
|
||||
&:focus {
|
||||
box-shadow: $form-range-thumb-focus-box-shadow;
|
||||
@include focus-ring($shadow: $form-range-thumb-focus-box-shadow, $outline: null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user