blob: 7e90de6e60b5b8278dc4f8399ca79c940b7c1e1d [file] [edit]
@use "sass:map";
@use "colors" as *;
@use "config" as *;
@use "functions" as *;
@use "theme" as *;
@use "mixins/tokens" as *;
@layer colors, config, root, reboot, layout, content, forms, components, custom, helpers, utilities;
$root-tokens: () !default;
// scss-docs-start root-tokens
// stylelint-disable @stylistic/value-list-max-empty-lines, @stylistic/function-max-empty-lines, custom-property-no-missing-var-function
// stylelint-disable-next-line scss/dollar-variable-default
$root-tokens: defaults(
(
--black: #{$black},
--white: #{$white},
--gradient: #{$gradient},
// scss-docs-start root-body-variables
// The stack omits system-ui. It resolves to the user interface font of the
// locale, which shows non-Latin text incorrectly. See twbs/bootstrap#42703.
--body-font-family: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', 'Noto Sans', 'Liberation Sans', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'",
--body-font-size: 1rem,
--body-font-weight: var(--font-weight-normal),
--body-line-height: 1.5,
// scss-docs-end root-body-variables
--heading-color: inherit,
--hr-border-color: var(--border-color),
--link-color: light-dark(var(--primary-base), var(--primary-fg)),
--link-decoration: underline,
--link-underline-offset: .2em,
--link-hover-color: color-mix(in oklch, var(--link-color) 90%, #000),
--font-mono: "ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Monaco, 'Cascadia Mono', Consolas, 'Liberation Mono', monospace",
--code-font-size: 95%,
--code-color: var(--fg-2),
// scss-docs-start root-border-var
--border-width: #{$border-width},
--border-width-keyline: .5px,
--border-style: #{$border-style},
--border-color: light-dark(var(--gray-200), var(--gray-700)),
--border-color-translucent: color-mix(in oklch, var(--fg-body) 15%, transparent),
// scss-docs-end root-border-var
// scss-docs-start root-box-shadow-variables
// --box-shadow* tokens are generated below (see root-box-shadow-loop) from
// the shared $shadows map in scss/_config.scss, which reads these two.
--shadow-color: #000,
--shadow-strength: 1,
// scss-docs-end root-box-shadow-variables
// scss-docs-start root-transition-variables
// Shared easing curve for overlay components (dialog, drawer, menu)
--transition-timing-overlay: cubic-bezier(.22, 1, .36, 1),
// scss-docs-end root-transition-variables
--spacer: 1rem,
// scss-docs-start root-focus-variables
--focus-ring-width: 3px,
--focus-ring-offset: 1px,
--focus-ring-color: var(--primary-focus-ring),
--focus-ring: var(--focus-ring-width) solid var(--focus-ring-color),
// scss-docs-end root-focus-variables
// scss-docs-start root-form-variables
--control-checked-bg: var(--primary-base),
--control-checked-border-color: var(--control-checked-bg),
--control-active-bg: var(--primary-base),
--control-active-border-color: var(--control-active-bg),
--control-disabled-bg: var(--bg-3),
--control-disabled-opacity: .65,
// Shared motion for checkbox/radio marks; slight overshoot so the mark pops in
--control-transition-duration: .15s,
--control-transition-timing: cubic-bezier(.34, 1.56, .64, 1),
--btn-input-fg: var(--fg-body),
--btn-input-bg: var(--bg-body),
--btn-input-gap: .375rem,
--btn-input-min-height: 2.375rem,
--btn-input-padding-y: .375rem,
--btn-input-padding-x: .75rem,
--btn-input-font-size: var(--body-font-size),
--btn-input-line-height: var(--body-line-height),
--btn-input-border-radius: var(--radius-5),
--btn-input-xs-gap: var(--spacer-1),
--btn-input-xs-min-height: 1.5rem,
--btn-input-xs-padding-y: .125rem,
--btn-input-xs-padding-x: .5rem,
--btn-input-xs-font-size: var(--font-size-xs),
--btn-input-xs-line-height: 1.125,
--btn-input-xs-border-radius: var(--radius-5),
--btn-input-sm-gap: .375rem,
--btn-input-sm-min-height: 2rem,
--btn-input-sm-padding-y: .25rem,
--btn-input-sm-padding-x: .625rem,
--btn-input-sm-font-size: var(--font-size-sm),
--btn-input-sm-line-height: var(--line-height-sm),
--btn-input-sm-border-radius: var(--radius-5),
--btn-input-lg-gap: .375rem,
--btn-input-lg-min-height: 2.75rem,
--btn-input-lg-padding-y: .5rem,
--btn-input-lg-padding-x: 1rem,
--btn-input-lg-font-size: var(--font-size-md),
--btn-input-lg-line-height: var(--line-height-md),
--btn-input-lg-border-radius: var(--radius-7),
// scss-docs-end root-form-variables
),
$root-tokens
);
// stylelint-enable @stylistic/value-list-max-empty-lines, @stylistic/function-max-empty-lines, custom-property-no-missing-var-function
// scss-docs-end root-tokens
// scss-docs-start root-font-size-loop
// Generate font-size and line-height tokens
@each $name, $props in $font-sizes {
$root-tokens: map.set($root-tokens, --font-size-#{$name}, map.get($props, "font-size"));
$root-tokens: map.set($root-tokens, --line-height-#{$name}, map.get($props, "line-height"));
}
// scss-docs-end root-font-size-loop
// scss-docs-start root-font-weight-loop
// Generate font-weight tokens
@each $name, $value in $font-weights {
$root-tokens: map.set($root-tokens, --font-weight-#{$name}, $value);
}
// scss-docs-end root-font-weight-loop
// scss-docs-start root-theme-tokens
// Generate semantic theme colors
@each $color-name, $color-map in $theme-colors {
@each $key, $value in $color-map {
$root-tokens: map.set($root-tokens, --#{$color-name}-#{$key}, $value);
}
}
// Generate background tokens
@each $key, $value in $theme-bgs {
$root-tokens: map.set($root-tokens, --bg-#{$key}, $value);
}
// Generate foreground tokens
@each $key, $value in $theme-fgs {
$root-tokens: map.set($root-tokens, --fg-#{$key}, $value);
}
// Generate border tokens
@each $key, $value in $theme-borders {
$root-tokens: map.set($root-tokens, --border-#{$key}, $value);
}
// scss-docs-end root-theme-tokens
// Generate breakpoint tokens
@each $name, $value in $breakpoints {
$root-tokens: map.set($root-tokens, --breakpoint-#{$name}, $value);
}
// Generate spacer tokens
// scss-docs-start root-spacer-loop
@each $key, $value in $spacers {
$root-tokens: map.set($root-tokens, --spacer-#{$key}, $value);
}
// scss-docs-end root-spacer-loop
// Generate radius tokens
// scss-docs-start root-radius-loop
@each $key, $value in $radii {
$root-tokens: map.set($root-tokens, --radius-#{$key}, $value);
}
// stylelint-disable-next-line scss/dollar-variable-default
$root-tokens: map.set($root-tokens, --radius-pill, 50rem);
// scss-docs-end root-radius-loop
// Generate box-shadow tokens
// scss-docs-start root-box-shadow-loop
@each $key, $value in $shadows {
@if $key == null {
$root-tokens: map.set($root-tokens, --box-shadow, $value);
} @else {
$root-tokens: map.set($root-tokens, --box-shadow-#{$key}, $value);
}
}
// scss-docs-end root-box-shadow-loop
// Generate z-index tokens
@each $key, $value in $zindex-levels {
$root-tokens: map.set($root-tokens, --z-#{$key}, $value);
}
:root,
:host {
@include tokens($root-tokens);
color-scheme: light dark;
// Always reserve the viewport scrollbar gutter so layout doesn't shift
// when overflow: hidden is applied (e.g. when a dialog opens on Windows).
scrollbar-gutter: stable;
}
// Deepen shadows in dark mode. The shadow-strength token is a plain number, so it
// can't use light-dark() (colors only); vary it alongside color-scheme instead.
@media (prefers-color-scheme: dark) {
:root,
:host {
--shadow-strength: 2.4;
}
}
[data-bs-theme="dark"] {
--shadow-strength: 2.4;
color-scheme: dark;
}
[data-bs-theme="light"] {
--shadow-strength: 1;
color-scheme: light;
}