blob: d9404a9ec87bb1cd444ca0abdfb54e4a0bb8ff00 [file] [edit]
@use "sass:map";
@use "config" as *;
@function theme-color-values($key) {
$result: ();
@each $color-name, $color-map in $theme-colors {
@if map.has-key($color-map, $key) {
$result: map.merge($result, ($color-name: map.get($color-map, $key)));
}
}
@return $result;
}
// Themes map sub-keys
//
// Return var() references to root tokens instead of raw values.
// Ex: theme-color-refs("bg") => (primary: var(--primary-bg), accent: var(--accent-bg), ...)
@function theme-color-refs($key) {
$result: ();
@each $color-name, $color-map in $theme-colors {
@if map.has-key($color-map, $key) {
$result: map.merge($result, ($color-name: var(--#{$color-name}-#{$key})));
}
}
@return $result;
}
// Theme token to root tokens
//
// Returns the global :root token reference for a given a given token map, prefix, and key.
// Ex: theme-token-refs($theme-bgs, "bg") => (body: var(--bg-body), 1: var(--bg-1), ...)
// Skips `inherit` since it's a CSS-wide keyword that can't be stored in a custom property.
@function theme-token-refs($map, $prefix) {
$result: ();
@each $key, $value in $map {
@if $value != inherit {
$result: map.merge($result, ($key: var(--#{$prefix}-#{$key})));
}
}
@return $result;
}
// Generate opacity values using color-mix()
// $fallback lets the referenced $color-var fall back to another color (e.g. currentcolor)
// when it hasn't been set by a companion color utility.
@function theme-opacity-values($color-var, $fallback: null, $opacities: $util-opacity) {
$result: ();
// stylelint-disable-next-line scss/at-function-named-arguments, @stylistic/function-whitespace-after
$color: if(sass($fallback): var($color-var, $fallback); else: var($color-var));
@each $key, $value in $opacities {
@if $key == 100 {
// For 100%, use direct variable reference (more efficient)
$result: map.merge($result, ($key: $color));
} @else {
// For other values, use color-mix()
$percentage: $key * 1%;
$result: map.merge($result, ($key: color-mix(in oklch, $color $percentage, transparent)));
}
}
@return $result;
}
// Set each --theme-* token to `initial` so descendants drop inherited theme colors.
// Use `initial`, not `unset`. `unset` inherits from the parent again.
// scss-docs-start generate-theme-reset
@mixin generate-theme-reset() {
.theme-reset {
$keys: ();
@each $color-map in map.values($theme-colors) {
@each $key in map.keys($color-map) {
$keys: map.merge($keys, ($key: true));
}
}
@each $key in map.keys($keys) {
--theme-#{$key}: initial;
}
}
}
// scss-docs-end generate-theme-reset
// Generate theme classes dynamically based on the keys in each theme color map
@mixin generate-theme-classes() {
@each $color-name, $color-map in $theme-colors {
.theme-#{$color-name} {
@each $key, $value in $color-map {
--theme-#{$key}: var(--#{$color-name}-#{$key});
}
}
}
@include generate-theme-reset();
}
// Theme maps use the `defaults()` pattern so `@use ... with (...)` merges custom
// values on top of the built-ins instead of replacing the whole map. Set a key
// to `null` to remove it. See scss/_config.scss for `defaults()`.
// scss-docs-start theme-colors
$theme-colors: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$theme-colors: defaults(
(
"primary": (
"base": var(--blue-500),
"fg": light-dark(var(--blue-600), var(--blue-400)),
"fg-emphasis": light-dark(var(--blue-800), var(--blue-200)),
"bg": var(--blue-500),
"bg-subtle": light-dark(var(--blue-100), var(--blue-900)),
"bg-muted": light-dark(var(--blue-200), var(--blue-800)),
"border": light-dark(var(--blue-300), var(--blue-600)),
"focus-ring": light-dark(color-mix(in oklch, var(--blue-500) 50%, var(--bg-body)), color-mix(in oklch, var(--blue-500) 75%, var(--bg-body))),
"contrast": var(--white)
),
"accent": (
"base": var(--indigo-500),
"fg": light-dark(var(--indigo-600), color-mix(in oklch, var(--indigo-400), var(--indigo-300))),
"fg-emphasis": light-dark(var(--indigo-800), var(--indigo-300)),
"bg": var(--indigo-500),
"bg-subtle": light-dark(var(--indigo-100), var(--indigo-900)),
"bg-muted": light-dark(var(--indigo-200), var(--indigo-800)),
"border": light-dark(var(--indigo-300), var(--indigo-600)),
"focus-ring": light-dark(color-mix(in oklch, var(--indigo-500) 50%, var(--bg-body)), color-mix(in oklch, var(--indigo-500) 75%, var(--bg-body))),
"contrast": var(--white)
),
"success": (
"base": var(--green-500),
"fg": light-dark(var(--green-600), var(--green-400)),
"fg-emphasis": light-dark(var(--green-800), var(--green-300)),
"bg": var(--green-500),
"bg-subtle": light-dark(var(--green-100), var(--green-900)),
"bg-muted": light-dark(var(--green-200), var(--green-800)),
"border": light-dark(var(--green-300), var(--green-600)),
"focus-ring": light-dark(color-mix(in oklch, var(--green-500) 50%, var(--bg-body)), color-mix(in oklch, var(--green-500) 75%, var(--bg-body))),
"contrast": var(--white)
),
"danger": (
"base": var(--red-500),
"fg": light-dark(var(--red-600), var(--red-400)),
"fg-emphasis": light-dark(var(--red-800), var(--red-300)),
"bg": var(--red-500),
"bg-subtle": light-dark(var(--red-100), var(--red-900)),
"bg-muted": light-dark(var(--red-200), var(--red-800)),
"border": light-dark(var(--red-300), var(--red-600)),
"focus-ring": light-dark(color-mix(in oklch, var(--red-500) 50%, var(--bg-body)), color-mix(in oklch, var(--red-500) 75%, var(--bg-body))),
"contrast": var(--white)
),
"warning": (
"base": var(--yellow-500),
"fg": light-dark(var(--yellow-700), var(--yellow-400)),
"fg-emphasis": light-dark(var(--yellow-800), var(--yellow-300)),
"bg": var(--yellow-500),
"bg-subtle": light-dark(var(--yellow-100), var(--yellow-900)),
"bg-muted": light-dark(var(--yellow-200), var(--yellow-800)),
"border": light-dark(var(--yellow-300), var(--yellow-600)),
"focus-ring": light-dark(color-mix(in oklch, var(--yellow-500) 50%, var(--bg-body)), color-mix(in oklch, var(--yellow-400) 85%, var(--bg-body))),
"contrast": var(--gray-900)
),
"info": (
"base": var(--cyan-500),
"fg": light-dark(var(--cyan-600), var(--cyan-400)),
"fg-emphasis": light-dark(var(--cyan-800), var(--cyan-300)),
"bg": var(--cyan-500),
"bg-subtle": light-dark(var(--cyan-100), var(--cyan-900)),
"bg-muted": light-dark(var(--cyan-200), var(--cyan-800)),
"border": light-dark(var(--cyan-300), var(--cyan-600)),
"focus-ring": light-dark(color-mix(in oklch, var(--cyan-500) 50%, var(--bg-body)), color-mix(in oklch, var(--cyan-500) 75%, var(--bg-body))),
"contrast": var(--gray-900)
),
"inverse": (
"base": var(--gray-900),
"fg": light-dark(var(--gray-900), var(--gray-200)),
"fg-emphasis": light-dark(var(--gray-975), var(--white)),
"bg": light-dark(var(--gray-900), var(--gray-025)),
"bg-subtle": light-dark(var(--gray-100), var(--gray-900)),
"bg-muted": light-dark(var(--gray-200), var(--gray-300)),
"border": light-dark(var(--gray-400), var(--gray-100)),
"focus-ring": color-mix(in oklch, light-dark(var(--gray-900), var(--gray-100)) 50%, var(--bg-body)),
"contrast": light-dark(var(--white), var(--gray-900))
),
"secondary": (
"base": var(--gray-200),
"fg": light-dark(var(--gray-600), var(--gray-400)),
"fg-emphasis": light-dark(var(--gray-800), var(--gray-200)),
"bg": light-dark(var(--gray-100), var(--gray-600)),
"bg-subtle": light-dark(var(--gray-050), var(--gray-800)),
"bg-muted": light-dark(var(--gray-100), var(--gray-700)),
"border": light-dark(var(--gray-300), var(--gray-600)),
"focus-ring": color-mix(in oklch, light-dark(var(--gray-500), var(--gray-300)) 50%, var(--bg-body)),
"contrast": light-dark(var(--gray-900), var(--white))
)
),
$theme-colors
);
// scss-docs-end theme-colors
$theme-bgs: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$theme-bgs: defaults(
(
"body": light-dark(var(--white), var(--gray-975)),
"1": light-dark(var(--gray-025), var(--gray-950)),
"2": light-dark(var(--gray-050), var(--gray-900)),
"3": light-dark(var(--gray-100), var(--gray-800)),
"4": light-dark(var(--gray-200), var(--gray-700)),
"fg": var(--fg-body),
"white": var(--white),
"black": var(--black),
"transparent": transparent,
"inherit": inherit,
),
$theme-bgs
);
$theme-fgs: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$theme-fgs: defaults(
(
"body": light-dark(var(--gray-900), var(--gray-050)),
"1": light-dark(var(--gray-800), var(--gray-200)),
"2": light-dark(var(--gray-700), var(--gray-300)),
"3": light-dark(var(--gray-600), var(--gray-500)),
"4": light-dark(var(--gray-500), var(--gray-600)),
"bg": var(--bg-body),
"white": var(--white),
"black": var(--black),
"inherit": inherit,
),
$theme-fgs
);
$theme-borders: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$theme-borders: defaults(
(
"bg": var(--bg-body),
"body": light-dark(var(--gray-300), var(--gray-800)),
"muted": light-dark(var(--gray-200), var(--gray-800)),
"subtle": light-dark(color-mix(in oklch, var(--gray-100), var(--gray-200)), color-mix(in oklch, var(--gray-800), var(--gray-900))),
"emphasized": light-dark(var(--gray-400), var(--gray-600)),
"white": var(--white),
"black": var(--black),
),
$theme-borders
);
$util-opacity: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$util-opacity: defaults(
(
10: .1,
20: .2,
30: .3,
40: .4,
50: .5,
60: .6,
70: .7,
80: .8,
90: .9,
100: 1
),
$util-opacity
);