Write shared color tokens once to cut 72 kB from tabler.min.css (#3141)

This commit is contained in:
Paweł Kuna authored and GitHub committed 2026-09-23 13:21:22 +02:00
1 parent 04602910c4
commit 3b8bf55c42
5 files changed
+174 -72

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
---
"@tabler/core": patch
---
Updated the button, list group, `bg-pattern-*` and color utility styles to cut 72 kB from `tabler.min.css`.
+41 -3
View File
@@ -1,3 +1,4 @@
@use 'sass:list';
@use 'sass:map'; @use 'sass:map';
@use 'settings' as *; @use 'settings' as *;
@use 'variables' as *; @use 'variables' as *;
@@ -21,6 +22,25 @@ $utilities-border-colors: map-loop(
'border' 'border'
) !default; ) !default;
// `utils/_colors.scss` emits `.text-*`, `.bg-*` and `.border-*` for these colors
// later in the file, with the same specificity, which always overrides the
// utilities generated here. The API only keeps what that file does not
// cover: the `--bg-opacity: 1` / `--border-opacity: 1` reset, which has to
// stay ahead of the `.bg-opacity-*` / `.border-opacity-*` classes.
$utilities-colors-overridden-text: map.keys($theme-colors);
$utilities-colors-overridden: list.join(map.keys($theme-colors), ('white'), comma);
// `(color: 1)` for every overridden color the given utility map generates.
@function utilities-opacity-reset($utility-colors) {
$map: ();
@each $color in $utilities-colors-overridden {
@if map.has-key($utility-colors, $color) {
$map: map.merge($map, (#{$color}: 1));
}
}
@return $map;
}
// Utilities // Utilities
$utilities: () !default; $utilities: () !default;
@@ -201,7 +221,13 @@ $utilities: map.merge(
local-vars: ( local-vars: (
'border-opacity': 1, 'border-opacity': 1,
), ),
values: $utilities-border-colors, values: map.remove($utilities-border-colors, $utilities-colors-overridden...),
),
'border-color-opacity': (
css-var: true,
css-variable-name: border-opacity,
class: border,
values: utilities-opacity-reset($utilities-border-colors),
), ),
'subtle-border-color': ( 'subtle-border-color': (
property: border-color, property: border-color,
@@ -687,7 +713,8 @@ $utilities: map.merge(
local-vars: ( local-vars: (
'text-opacity': 1, 'text-opacity': 1,
), ),
values: map.merge( values: map.remove(
map.merge(
$utilities-text-colors, $utilities-text-colors,
( (
'muted': var(--secondary-color), 'muted': var(--secondary-color),
@@ -702,6 +729,8 @@ $utilities: map.merge(
'reset': inherit, 'reset': inherit,
) )
), ),
$utilities-colors-overridden-text...
),
), ),
'text-opacity': ( 'text-opacity': (
css-var: true, css-var: true,
@@ -772,7 +801,8 @@ $utilities: map.merge(
local-vars: ( local-vars: (
'bg-opacity': 1, 'bg-opacity': 1,
), ),
values: map.merge( values: map.remove(
map.merge(
$utilities-bg-colors, $utilities-bg-colors,
( (
'transparent': transparent, 'transparent': transparent,
@@ -780,6 +810,14 @@ $utilities: map.merge(
'body-tertiary': color-transparent(var(--tertiary-bg), calc(var(--bg-opacity) * 100%)), 'body-tertiary': color-transparent(var(--tertiary-bg), calc(var(--bg-opacity) * 100%)),
) )
), ),
$utilities-colors-overridden...
),
),
'background-color-opacity': (
css-var: true,
css-variable-name: bg-opacity,
class: bg,
values: utilities-opacity-reset($utilities-bg-colors),
), ),
'bg-opacity': ( 'bg-opacity': (
css-var: true, css-var: true,
+26 -12
View File
@@ -1,3 +1,4 @@
@use 'sass:list';
@use 'sass:map'; @use 'sass:map';
// Base class // Base class
@@ -190,22 +191,35 @@
// and the subtle/emphasis maps only cover the latter, so upstream's version // and the subtle/emphasis maps only cover the latter, so upstream's version
// left `.list-group-item-azure` and twelve more reading tokens nobody defines. // left `.list-group-item-azure` and twelve more reading tokens nobody defines.
// The tint also matches the `bg-{color}-lt` utilities used elsewhere. // The tint also matches the `bg-{color}-lt` utilities used elsewhere.
// Each color class only points the --list-group-variant* tokens at its palette
// colors; one shared rule turns them into the list group tokens, so the token
// list is written once instead of once per color.
$list-group-variant-selectors: ();
@each $state in map.keys($theme-colors) { @each $state in map.keys($theme-colors) {
$list-group-variant-selectors: list.append($list-group-variant-selectors, '.list-group-item-#{$state}', $separator: comma);
.list-group-item-#{$state} { .list-group-item-#{$state} {
--list-group-color: var(--#{$state}); --list-group-variant: var(--#{$state});
--list-group-bg: var(--#{$state}-lt); --list-group-variant-lt: var(--#{$state}-lt);
--list-group-border-color: #{color-transparent(var(--#{$state}), $list-group-variant-border-alpha)}; --list-group-variant-fg: var(--#{$state}-fg);
--list-group-action-color: var(--#{$state}); }
--list-group-action-hover-color: var(--#{$state}); }
--list-group-action-hover-bg: #{color-transparent(var(--#{$state}), $list-group-variant-hover-alpha)};
--list-group-action-active-color: var(--#{$state}-fg); #{$list-group-variant-selectors} {
--list-group-action-active-bg: var(--#{$state}); --list-group-color: var(--list-group-variant);
--list-group-bg: var(--list-group-variant-lt);
--list-group-border-color: #{color-transparent(var(--list-group-variant), $list-group-variant-border-alpha)};
--list-group-action-color: var(--list-group-variant);
--list-group-action-hover-color: var(--list-group-variant);
--list-group-action-hover-bg: #{color-transparent(var(--list-group-variant), $list-group-variant-hover-alpha)};
--list-group-action-active-color: var(--list-group-variant-fg);
--list-group-action-active-bg: var(--list-group-variant);
// The selected row keeps the tint: `.list-group-item.active` paints its own // The selected row keeps the tint: `.list-group-item.active` paints its own
// neutral highlight, so a solid fill here would only show through as text // neutral highlight, so a solid fill here would only show through as text
// on a background it was never matched against. // on a background it was never matched against.
--list-group-active-color: var(--#{$state}); --list-group-active-color: var(--list-group-variant);
--list-group-active-bg: var(--#{$state}-lt); --list-group-active-bg: var(--list-group-variant-lt);
--list-group-active-border-color: #{color-transparent(var(--#{$state}), $list-group-variant-border-alpha)}; --list-group-active-border-color: #{color-transparent(var(--list-group-variant), $list-group-variant-border-alpha)};
}
} }
// scss-docs-end list-group-modifiers // scss-docs-end list-group-modifiers
+64 -40
View File
@@ -1,3 +1,4 @@
@use 'sass:list';
@use 'sass:map'; @use 'sass:map';
// //
@@ -93,63 +94,86 @@
--btn-hover-color: var(--body-color); --btn-hover-color: var(--body-color);
} }
@each $color, $value in map.merge($theme-colors, $social-colors) { // Each color class only points the --btn-variant* tokens at its palette
.btn-#{$color} { // colors; the shared rules below turn them into the button tokens. The rules
@if $color == 'dark' { // are grouped by variant (solid, outline, ghost) rather than by color, so each
--btn-border-color: var(--dark-mode-border-color); // token list is written once instead of once per color.
--btn-hover-border-color: var(--dark-mode-border-active-color); $btn-colors: map.keys(map.merge($theme-colors, $social-colors));
--btn-active-border-color: var(--dark-mode-border-active-color);
} @else { @function btn-color-selectors($patterns...) {
$selectors: ();
@each $pattern in $patterns {
@each $color in $btn-colors {
$selectors: list.append($selectors, str-replace($pattern, '{c}', '#{$color}'), $separator: comma);
}
}
@return $selectors;
}
@each $color in $btn-colors {
.btn-#{$color},
.btn-outline-#{$color},
.btn-ghost-#{$color} {
--btn-variant: var(--#{$color});
--btn-variant-fg: var(--#{$color}-fg);
--btn-variant-darken: var(--#{$color}-darken);
}
}
#{btn-color-selectors('.btn-{c}')} {
--btn-border-color: transparent; --btn-border-color: transparent;
--btn-hover-border-color: transparent; --btn-hover-border-color: transparent;
--btn-active-border-color: transparent; --btn-active-border-color: transparent;
} --btn-color: var(--btn-variant-fg, #{$white});
--btn-bg: var(--btn-variant);
--btn-color: var(--#{$color}-fg, #{$white}); --btn-hover-color: var(--btn-variant-fg);
--btn-bg: var(--#{$color}); --btn-hover-bg: var(--btn-variant-darken);
--btn-hover-color: var(--#{$color}-fg); --btn-active-color: var(--btn-variant-fg);
--btn-hover-bg: var(--#{$color}-darken); --btn-active-bg: var(--btn-variant-darken);
--btn-active-color: var(--#{$color}-fg); --btn-disabled-bg: var(--btn-variant);
--btn-active-bg: var(--#{$color}-darken); --btn-disabled-color: var(--btn-variant-fg);
--btn-disabled-bg: var(--#{$color});
--btn-disabled-color: var(--#{$color}-fg);
--btn-box-shadow: var(--shadow-input); --btn-box-shadow: var(--shadow-input);
} }
.btn-outline-#{$color}, @if map.has-key($theme-colors, 'dark') {
.btn-outline.btn-#{$color} { .btn-dark {
--btn-color: var(--#{$color}); --btn-border-color: var(--dark-mode-border-color);
--btn-bg: transparent; --btn-hover-border-color: var(--dark-mode-border-active-color);
--btn-border-color: var(--#{$color}); --btn-active-border-color: var(--dark-mode-border-active-color);
--btn-hover-color: var(--#{$color}-fg); }
--btn-hover-border-color: transparent;
--btn-hover-bg: var(--#{$color});
--btn-active-color: var(--#{$color}-fg);
--btn-active-bg: var(--#{$color});
--btn-active-border-color: var(--#{$color});
--btn-disabled-color: var(--#{$color});
--btn-disabled-border-color: var(--#{$color});
} }
.btn-ghost-#{$color}, #{btn-color-selectors('.btn-outline-{c}', '.btn-outline.btn-{c}')} {
.btn-ghost.btn-#{$color} { --btn-color: var(--btn-variant);
--btn-color: var(--#{$color}); --btn-bg: transparent;
--btn-border-color: var(--btn-variant);
--btn-hover-color: var(--btn-variant-fg);
--btn-hover-border-color: transparent;
--btn-hover-bg: var(--btn-variant);
--btn-active-color: var(--btn-variant-fg);
--btn-active-bg: var(--btn-variant);
--btn-active-border-color: var(--btn-variant);
--btn-disabled-color: var(--btn-variant);
--btn-disabled-border-color: var(--btn-variant);
}
#{btn-color-selectors('.btn-ghost-{c}', '.btn-ghost.btn-{c}')} {
--btn-color: var(--btn-variant);
--btn-bg: transparent; --btn-bg: transparent;
--btn-border-color: transparent; --btn-border-color: transparent;
--btn-hover-color: var(--#{$color}-fg); --btn-hover-color: var(--btn-variant-fg);
--btn-hover-bg: var(--#{$color}); --btn-hover-bg: var(--btn-variant);
--btn-hover-border-color: var(--#{$color}); --btn-hover-border-color: var(--btn-variant);
--btn-active-color: var(--#{$color}-fg); --btn-active-color: var(--btn-variant-fg);
--btn-active-bg: var(--#{$color}); --btn-active-bg: var(--btn-variant);
--btn-active-border-color: transparent; --btn-active-border-color: transparent;
--btn-active-shadow: #{$btn-active-box-shadow}; --btn-active-shadow: #{$btn-active-box-shadow};
--btn-disabled-color: var(--#{$color}); --btn-disabled-color: var(--btn-variant);
--btn-disabled-bg: transparent; --btn-disabled-bg: transparent;
--btn-disabled-border-color: transparent; --btn-disabled-border-color: transparent;
--gradient: none; --gradient: none;
--btn-box-shadow: none; --btn-box-shadow: none;
} }
}
// //
// Button sizes // Button sizes
+38 -17
View File
@@ -8,26 +8,37 @@
background-clip: padding-box; background-clip: padding-box;
} }
.bg-pattern-transparent { // The shared tokens are written once for every pattern through @extend; a
// pattern with a different opacity only overrides --pattern-opacity.
%pattern-base {
@include pattern-base(); @include pattern-base();
}
@mixin pattern-opacity($opacity) {
--pattern-opacity: calc(var(--pattern-opacity-factor, #{$pattern-opacity-factor}) * #{$opacity});
}
.bg-pattern-transparent {
@extend %pattern-base;
background-image: repeating-conic-gradient(var(--pattern-fill) 0% 25%, transparent 0% 50%); background-image: repeating-conic-gradient(var(--pattern-fill) 0% 25%, transparent 0% 50%);
background-size: calc(var(--pattern-size) * 2) calc(var(--pattern-size) * 2); background-size: calc(var(--pattern-size) * 2) calc(var(--pattern-size) * 2);
} }
.bg-pattern-diagonal { .bg-pattern-diagonal {
@include pattern-base(); @extend %pattern-base;
background-image: repeating-linear-gradient(-45deg, var(--pattern-fill) 0 1px, transparent 0 50%); background-image: repeating-linear-gradient(-45deg, var(--pattern-fill) 0 1px, transparent 0 50%);
background-size: var(--pattern-size) var(--pattern-size); background-size: var(--pattern-size) var(--pattern-size);
} }
.bg-pattern-diagonal-2 { .bg-pattern-diagonal-2 {
@include pattern-base(); @extend %pattern-base;
background-image: repeating-linear-gradient(45deg, var(--pattern-fill) 0 1px, transparent 0 50%); background-image: repeating-linear-gradient(45deg, var(--pattern-fill) 0 1px, transparent 0 50%);
background-size: var(--pattern-size) var(--pattern-size); background-size: var(--pattern-size) var(--pattern-size);
} }
.bg-pattern-dots { .bg-pattern-dots {
@include pattern-base(20%); @extend %pattern-base;
@include pattern-opacity(20%);
--pattern-dot: max(1px, calc(var(--pattern-size) * 0.1)); --pattern-dot: max(1px, calc(var(--pattern-size) * 0.1));
background-image: radial-gradient(circle, var(--pattern-fill) var(--pattern-dot), transparent calc(var(--pattern-dot) + 0.5px)), radial-gradient(circle, var(--pattern-fill) var(--pattern-dot), transparent calc(var(--pattern-dot) + 0.5px)); background-image: radial-gradient(circle, var(--pattern-fill) var(--pattern-dot), transparent calc(var(--pattern-dot) + 0.5px)), radial-gradient(circle, var(--pattern-fill) var(--pattern-dot), transparent calc(var(--pattern-dot) + 0.5px));
background-position: background-position:
@@ -37,7 +48,8 @@
} }
.bg-pattern-rectangles { .bg-pattern-rectangles {
@include pattern-base(3%); @extend %pattern-base;
@include pattern-opacity(3%);
background-image: repeating-linear-gradient(45deg, var(--pattern-fill) 25%, transparent 25%, transparent 75%, var(--pattern-fill) 75%, var(--pattern-fill)), repeating-linear-gradient(45deg, var(--pattern-fill) 25%, transparent 25%, transparent 75%, var(--pattern-fill) 75%, var(--pattern-fill)); background-image: repeating-linear-gradient(45deg, var(--pattern-fill) 25%, transparent 25%, transparent 75%, var(--pattern-fill) 75%, var(--pattern-fill)), repeating-linear-gradient(45deg, var(--pattern-fill) 25%, transparent 25%, transparent 75%, var(--pattern-fill) 75%, var(--pattern-fill));
background-position: background-position:
-1px -1px, -1px -1px,
@@ -46,21 +58,24 @@
} }
.bg-pattern-lines { .bg-pattern-lines {
@include pattern-base(6%); @extend %pattern-base;
@include pattern-opacity(6%);
background-image: repeating-linear-gradient(0deg, var(--pattern-fill), var(--pattern-fill) 1px, transparent 1px, transparent); background-image: repeating-linear-gradient(0deg, var(--pattern-fill), var(--pattern-fill) 1px, transparent 1px, transparent);
background-position: -1px -1px; background-position: -1px -1px;
background-size: var(--pattern-size) var(--pattern-size); background-size: var(--pattern-size) var(--pattern-size);
} }
.bg-pattern-lines-vertical { .bg-pattern-lines-vertical {
@include pattern-base(6%); @extend %pattern-base;
@include pattern-opacity(6%);
background-image: repeating-linear-gradient(90deg, var(--pattern-fill), var(--pattern-fill) 1px, transparent 1px, transparent); background-image: repeating-linear-gradient(90deg, var(--pattern-fill), var(--pattern-fill) 1px, transparent 1px, transparent);
background-position: -1px -1px; background-position: -1px -1px;
background-size: var(--pattern-size) var(--pattern-size); background-size: var(--pattern-size) var(--pattern-size);
} }
.bg-pattern-grid { .bg-pattern-grid {
@include pattern-base(6%); @extend %pattern-base;
@include pattern-opacity(6%);
background-image: linear-gradient(to right, var(--pattern-fill) 1px, transparent 1px), linear-gradient(to bottom, var(--pattern-fill) 1px, transparent 1px); background-image: linear-gradient(to right, var(--pattern-fill) 1px, transparent 1px), linear-gradient(to bottom, var(--pattern-fill) 1px, transparent 1px);
background-position: background-position:
-1px -1px, -1px -1px,
@@ -69,14 +84,15 @@
} }
.bg-pattern-grid-diagonal { .bg-pattern-grid-diagonal {
@include pattern-base(); @extend %pattern-base;
background-image: linear-gradient(45deg, transparent 49%, var(--pattern-fill) 49%, var(--pattern-fill) 51%, transparent 51%), linear-gradient(-45deg, transparent 49%, var(--pattern-fill) 49%, var(--pattern-fill) 51%, transparent 51%); background-image: linear-gradient(45deg, transparent 49%, var(--pattern-fill) 49%, var(--pattern-fill) 51%, transparent 51%), linear-gradient(-45deg, transparent 49%, var(--pattern-fill) 49%, var(--pattern-fill) 51%, transparent 51%);
background-position: center center; background-position: center center;
background-size: calc(var(--pattern-size) * 2) calc(var(--pattern-size) * 2); background-size: calc(var(--pattern-size) * 2) calc(var(--pattern-size) * 2);
} }
.bg-pattern-blueprint { .bg-pattern-blueprint {
@include pattern-base(6%); @extend %pattern-base;
@include pattern-opacity(6%);
--pattern-line: var(--pattern-fill); --pattern-line: var(--pattern-fill);
background-image: linear-gradient(var(--pattern-line) 2px, transparent 2px), linear-gradient(90deg, var(--pattern-line) 2px, transparent 2px), linear-gradient(var(--pattern-line) 1px, transparent 1px), linear-gradient(90deg, var(--pattern-line) 1px, transparent 1px); background-image: linear-gradient(var(--pattern-line) 2px, transparent 2px), linear-gradient(90deg, var(--pattern-line) 2px, transparent 2px), linear-gradient(var(--pattern-line) 1px, transparent 1px), linear-gradient(90deg, var(--pattern-line) 1px, transparent 1px);
background-position: background-position:
@@ -92,7 +108,7 @@
} }
.bg-pattern-cross-dots { .bg-pattern-cross-dots {
@include pattern-base(); @extend %pattern-base;
background-image: radial-gradient(var(--pattern-fill) 1px, transparent 1px), radial-gradient(var(--pattern-fill) 1px, transparent 1px); background-image: radial-gradient(var(--pattern-fill) 1px, transparent 1px), radial-gradient(var(--pattern-fill) 1px, transparent 1px);
background-position: background-position:
0 0, 0 0,
@@ -101,7 +117,7 @@
} }
.bg-pattern-circles { .bg-pattern-circles {
@include pattern-base(); @extend %pattern-base;
background-image: background-image:
radial-gradient(circle at center top, transparent 9%, var(--pattern-fill) 10%, var(--pattern-fill) 15%, transparent 16%), radial-gradient(circle at center bottom, transparent 9%, var(--pattern-fill) 10%, var(--pattern-fill) 15%, transparent 16%), radial-gradient(circle at center top, transparent 9%, var(--pattern-fill) 10%, var(--pattern-fill) 15%, transparent 16%), radial-gradient(circle at center bottom, transparent 9%, var(--pattern-fill) 10%, var(--pattern-fill) 15%, transparent 16%),
radial-gradient(circle at right center, transparent 9%, var(--pattern-fill) 10%, var(--pattern-fill) 15%, transparent 16%), radial-gradient(circle at left center, transparent 9%, var(--pattern-fill) 10%, var(--pattern-fill) 15%, transparent 16%); radial-gradient(circle at right center, transparent 9%, var(--pattern-fill) 10%, var(--pattern-fill) 15%, transparent 16%), radial-gradient(circle at left center, transparent 9%, var(--pattern-fill) 10%, var(--pattern-fill) 15%, transparent 16%);
@@ -110,19 +126,22 @@
} }
.bg-pattern-diagonal-stripes { .bg-pattern-diagonal-stripes {
@include pattern-base(5%); @extend %pattern-base;
@include pattern-opacity(5%);
background-image: repeating-linear-gradient(45deg, transparent, transparent var(--pattern-size), var(--pattern-fill) var(--pattern-size), var(--pattern-fill) calc(2 * var(--pattern-size))); background-image: repeating-linear-gradient(45deg, transparent, transparent var(--pattern-size), var(--pattern-fill) var(--pattern-size), var(--pattern-fill) calc(2 * var(--pattern-size)));
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.bg-pattern-diagonal-stripes-2 { .bg-pattern-diagonal-stripes-2 {
@include pattern-base(5%); @extend %pattern-base;
@include pattern-opacity(5%);
background-image: repeating-linear-gradient(-45deg, transparent, transparent var(--pattern-size), var(--pattern-fill) var(--pattern-size), var(--pattern-fill) calc(2 * var(--pattern-size))); background-image: repeating-linear-gradient(-45deg, transparent, transparent var(--pattern-size), var(--pattern-fill) var(--pattern-size), var(--pattern-fill) calc(2 * var(--pattern-size)));
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.bg-pattern-zigzag { .bg-pattern-zigzag {
@include pattern-base(5%); @extend %pattern-base;
@include pattern-opacity(5%);
background: background:
linear-gradient(135deg, var(--pattern-fill) 25%, transparent 25%) calc(-1 * var(--pattern-size)) 0, linear-gradient(135deg, var(--pattern-fill) 25%, transparent 25%) calc(-1 * var(--pattern-size)) 0,
linear-gradient(225deg, var(--pattern-fill) 25%, transparent 25%) calc(-1 * var(--pattern-size)) 0, linear-gradient(225deg, var(--pattern-fill) 25%, transparent 25%) calc(-1 * var(--pattern-size)) 0,
@@ -133,12 +152,14 @@
} }
.bg-pattern-vertical-stripes { .bg-pattern-vertical-stripes {
@include pattern-base(5%); @extend %pattern-base;
@include pattern-opacity(5%);
background-image: repeating-linear-gradient(90deg, transparent, transparent var(--pattern-size), var(--pattern-fill) var(--pattern-size), var(--pattern-fill) calc(2 * var(--pattern-size))); background-image: repeating-linear-gradient(90deg, transparent, transparent var(--pattern-size), var(--pattern-fill) var(--pattern-size), var(--pattern-fill) calc(2 * var(--pattern-size)));
} }
.bg-pattern-horizontal-stripes { .bg-pattern-horizontal-stripes {
@include pattern-base(5%); @extend %pattern-base;
@include pattern-opacity(5%);
background-image: repeating-linear-gradient(0deg, transparent, transparent var(--pattern-size), var(--pattern-fill) var(--pattern-size), var(--pattern-fill) calc(2 * var(--pattern-size))); background-image: repeating-linear-gradient(0deg, transparent, transparent var(--pattern-size), var(--pattern-fill) var(--pattern-size), var(--pattern-fill) calc(2 * var(--pattern-size)));
background-position: -1px -1px; background-position: -1px -1px;
} }