sveltelean
Versionv0.2.0 GitHub

Definition

Tokens are custom properties on :root inside the slean.tokens cascade layer, defined in oklch. Component files reference tokens and define none of their own; every var(--slean-…) in the package resolves to a token on this page. An unlayered override in your application always wins:

app.css
/* A theme is a set of token values. Redefine them on :root to retheme every primitive. */
:root {
	--slean-accent: oklch(45% 0.13 150);
	--slean-accent-hover: oklch(40% 0.13 150);
	--slean-accent-active: oklch(36% 0.12 150);
	--slean-radius-md: 0.25rem;
	--slean-font-sans: 'IBM Plex Sans', system-ui, sans-serif;
}

Semantic tokens (--slean-bg, --slean-fg, --slean-border) reference the neutral scale, so changing the scale retints every surface. A swatch shows the resolved default of the package; the controls on this site read the site's own palette through a token bridge instead (Themes).

Shape and spacing

TokenLightDark
--slean-radius-sm0.375remsame as light
--slean-radius-md0.625remsame as light
--slean-radius-lg0.875remsame as light
--slean-radius-full9999pxsame as light
--slean-space-10.25remsame as light
--slean-space-20.5remsame as light
--slean-space-30.75remsame as light
--slean-space-41remsame as light
--slean-space-51.25remsame as light
--slean-space-61.5remsame as light
--slean-space-72remsame as light
--slean-space-82.5remsame as light

Control heights

sm 32px, md 36px (the default of every form control, button and bar), lg 44px. A coarse pointer raises them to 40, 44 and 48px.

TokenLightDark
--slean-control-height-sm2remsame as light
--slean-control-height-md2.25remsame as light
--slean-control-height-lg2.75remsame as light

Icons (ADR 0007)

16×16 SVG masks. A primitive paints one with `background: currentColor; mask: var(--slean-icon-…) center / contain no-repeat`, so it takes the text color and follows the theme. Replace a token to swap an icon set.

TokenLightDark
--slean-icon-chevron-downurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E")same as light
--slean-icon-chevron-upurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 10l4-4 4 4' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E")same as light
--slean-icon-chevron-lefturl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M10 4L6 8l4 4' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E")same as light
--slean-icon-chevron-righturl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 4l4 4-4 4' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E")same as light
--slean-icon-chevrons-lefturl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 4L4 8l4 4M12 4L8 8l4 4' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E")same as light
--slean-icon-chevrons-righturl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4l4 4-4 4M8 4l4 4-4 4' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E")same as light
--slean-icon-checkurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3 6-7' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E")same as light
--slean-icon-minusurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8h9' stroke='black' stroke-width='1.5' stroke-linecap='round' fill='none'/%3E%3C/svg%3E")same as light
--slean-icon-plusurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 3.5v9M3.5 8h9' stroke='black' stroke-width='1.5' stroke-linecap='round' fill='none'/%3E%3C/svg%3E")same as light
--slean-icon-closeurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4.5 4.5l7 7m0-7l-7 7' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E")same as light
--slean-icon-clearurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cdefs%3E%3Cmask id='m'%3E%3Crect width='16' height='16' fill='white'/%3E%3Cpath d='M6 6l4 4m0-4l-4 4' stroke='black' stroke-width='1.5' stroke-linecap='round'/%3E%3C/mask%3E%3C/defs%3E%3Ccircle cx='8' cy='8' r='6.5' mask='url(%23m)'/%3E%3C/svg%3E")same as light
--slean-icon-moreurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='3.5' cy='8' r='1.25'/%3E%3Ccircle cx='8' cy='8' r='1.25'/%3E%3Ccircle cx='12.5' cy='8' r='1.25'/%3E%3C/svg%3E")same as light
--slean-icon-searchurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'%3E%3Ccircle cx='7' cy='7' r='4.5'/%3E%3Cpath d='M10.5 10.5L14 14'/%3E%3C/g%3E%3C/svg%3E")same as light
--slean-icon-calendarurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'%3E%3Crect x='2.5' y='3.5' width='11' height='10' rx='1.5'/%3E%3Cpath d='M2.5 6.75h11M5.5 2v3M10.5 2v3'/%3E%3C/g%3E%3C/svg%3E")same as light
--slean-icon-arrow-righturl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2.5 8h11M10 4.5L13.5 8 10 11.5' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E")same as light
--slean-icon-infourl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'%3E%3Ccircle cx='8' cy='8' r='6.25'/%3E%3Cpath d='M8 7.5v3.5M8 5v.01'/%3E%3C/g%3E%3C/svg%3E")same as light
--slean-icon-successurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'%3E%3Ccircle cx='8' cy='8' r='6.25'/%3E%3Cpath d='M5.5 8.25l1.75 1.75 3.25-3.5'/%3E%3C/g%3E%3C/svg%3E")same as light
--slean-icon-warningurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'%3E%3Cpath d='M6.7 2.75a1.5 1.5 0 012.6 0l5.1 8.9a1.5 1.5 0 01-1.3 2.25H2.9a1.5 1.5 0 01-1.3-2.25z'/%3E%3Cpath d='M8 6.25v3M8 11.5v.01'/%3E%3C/g%3E%3C/svg%3E")same as light
--slean-icon-errorurl("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'%3E%3Ccircle cx='8' cy='8' r='6.25'/%3E%3Cpath d='M10 6l-4 4M6 6l4 4'/%3E%3C/g%3E%3C/svg%3E")same as light

Typography

Controls inherit the page font; apply --slean-font-sans to the page yourself.

TokenLightDark
--slean-font-sansInter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serifsame as light
--slean-font-monoui-monospace, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospacesame as light
--slean-text-xs0.75remsame as light
--slean-text-sm0.875remsame as light
--slean-text-md1remsame as light
--slean-text-lg1.125remsame as light
--slean-leading1.5same as light
--slean-font-weight-medium500same as light
--slean-font-weight-semibold600same as light

Motion

The indicator duration is one turn of a loading indicator (the busy button and the spinner); reduced motion slows it instead of stopping it, so a still ring never reads as a stuck page.

TokenLightDark
--slean-duration-fast100mssame as light
--slean-duration-normal160mssame as light
--slean-duration-slow240mssame as light
--slean-duration-indicator750mssame as light
--slean-easecubic-bezier(0.2, 0, 0, 1)same as light

Focus ring geometry

used by every :focus-visible outline.

TokenLightDark
--slean-focus-ring-width2pxsame as light
--slean-focus-ring-offset2pxsame as light

Inputs a behavior writes as inline styles on its root

not theme tokens: the range slider's two values and the splitter's first pane, as percentages without the unit.

TokenLightDark
--slean-range-start0same as light
--slean-range-end100same as light
--slean-split50same as light
--slean-color-schemelightdark

Neutral scale

1 = page background, 12 = strongest text. 8 is the control border, at least 3:1 against the surface and the page background in both themes.

TokenLightDark
--slean-neutral-1oklch(99.5% 0.002 260)oklch(16.5% 0.008 260)
--slean-neutral-2oklch(98.2% 0.003 260)oklch(19.5% 0.009 260)
--slean-neutral-3oklch(95.8% 0.004 260)oklch(23% 0.01 260)
--slean-neutral-4oklch(93.2% 0.005 260)oklch(26% 0.011 260)
--slean-neutral-5oklch(90.5% 0.006 260)oklch(29.5% 0.012 260)
--slean-neutral-6oklch(87.2% 0.007 260)oklch(33.5% 0.013 260)
--slean-neutral-7oklch(80.8% 0.009 260)oklch(39.5% 0.014 260)
--slean-neutral-8oklch(63.5% 0.012 260)oklch(53% 0.015 260)
--slean-neutral-9oklch(55.2% 0.015 260)oklch(58% 0.015 260)
--slean-neutral-10oklch(50.8% 0.015 260)oklch(63% 0.015 260)
--slean-neutral-11oklch(44.6% 0.014 260)oklch(74% 0.012 260)
--slean-neutral-12oklch(20.5% 0.012 260)oklch(95% 0.005 260)

Accent

TokenLightDark
--slean-accentoklch(54% 0.19 258)oklch(56% 0.18 258)
--slean-accent-hoveroklch(49% 0.19 258)oklch(61% 0.18 258)
--slean-accent-activeoklch(45% 0.18 258)oklch(52% 0.18 258)
--slean-accent-fgoklch(100% 0 0)oklch(100% 0 0)
--slean-accent-softoklch(95% 0.03 258)oklch(28% 0.07 258)
--slean-accent-soft-fgoklch(42% 0.17 258)oklch(85% 0.09 258)

Status

TokenLightDark
--slean-successoklch(55% 0.15 150)oklch(58% 0.15 150)
--slean-success-fgoklch(100% 0 0)oklch(100% 0 0)
--slean-success-softoklch(95.5% 0.04 150)oklch(27% 0.07 150)
--slean-success-soft-fgoklch(40% 0.12 150)oklch(85% 0.12 150)
--slean-warningoklch(76% 0.16 80)oklch(80% 0.16 80)
--slean-warning-fgoklch(25% 0.05 80)oklch(20% 0.05 80)
--slean-warning-softoklch(96% 0.05 85)oklch(28% 0.07 80)
--slean-warning-soft-fgoklch(45% 0.12 75)oklch(87% 0.12 85)
--slean-dangeroklch(55% 0.2 25)oklch(58% 0.19 25)
--slean-danger-hoveroklch(50% 0.2 25)oklch(63% 0.19 25)
--slean-danger-fgoklch(100% 0 0)oklch(100% 0 0)
--slean-danger-softoklch(95.5% 0.03 25)oklch(27% 0.08 25)
--slean-danger-soft-fgoklch(45% 0.18 25)oklch(85% 0.1 25)

Surfaces that differ between the themes

TokenLightDark
--slean-surfaceoklch(100% 0 0)var(--slean-neutral-2)
--slean-mutedvar(--slean-neutral-3)var(--slean-neutral-4)
--slean-muted-hovervar(--slean-neutral-4)var(--slean-neutral-5)
--slean-overlayoklch(0% 0 0 / 0.4)oklch(0% 0 0 / 0.6)
--slean-shadow-sm0 1px 2px oklch(0% 0 0 / 0.08)0 1px 2px oklch(0% 0 0 / 0.4)
--slean-shadow-md0 4px 12px oklch(0% 0 0 / 0.1), 0 1px 3px oklch(0% 0 0 / 0.08)0 4px 12px oklch(0% 0 0 / 0.5), 0 1px 3px oklch(0% 0 0 / 0.4)
--slean-shadow-lg0 16px 40px oklch(0% 0 0 / 0.18), 0 2px 6px oklch(0% 0 0 / 0.08)0 16px 40px oklch(0% 0 0 / 0.6), 0 2px 6px oklch(0% 0 0 / 0.4)

Semantic surfaces and text

TokenLightDark
--slean-bgvar(--slean-neutral-1)same as light
--slean-fgvar(--slean-neutral-12)same as light
--slean-fg-mutedvar(--slean-neutral-11)same as light
--slean-bordervar(--slean-neutral-6)same as light
--slean-border-strongvar(--slean-neutral-8)same as light

Info follows the accent unless a theme gives it a color of its own

TokenLightDark
--slean-infovar(--slean-accent)same as light
--slean-info-softvar(--slean-accent-soft)same as light
--slean-info-soft-fgvar(--slean-accent-soft-fg)same as light

Control shell (ADR 0007)

the field every form control shares (input, select, combobox, date picker and the other fields). The border is at least 3:1 against the surface; hover and focus take the accent and the focus ring is a soft halo of it; a disabled control sits on the muted surface.

TokenLightDark
--slean-control-bgvar(--slean-surface)same as light
--slean-control-bg-disabledvar(--slean-muted)same as light
--slean-control-border-disabledvar(--slean-border)same as light
--slean-control-bordervar(--slean-border-strong)same as light
--slean-control-border-hovervar(--slean-accent)same as light
--slean-control-border-focusvar(--slean-accent)same as light
--slean-control-ring0 0 0 3px color-mix(in oklch, var(--slean-accent) 22%, transparent)same as light
--slean-control-ring-danger0 0 0 3px color-mix(in oklch, var(--slean-danger) 22%, transparent)same as light
--slean-control-ring-warning0 0 0 3px color-mix(in oklch, var(--slean-warning) 28%, transparent)same as light
--slean-control-iconvar(--slean-fg-muted)same as light
--slean-option-activevar(--slean-muted)same as light
--slean-option-selectedvar(--slean-accent-soft)same as light
--slean-option-selected-fgvar(--slean-accent-soft-fg)same as light
--slean-popup-radiusvar(--slean-radius-md)same as light
--slean-popup-shadowvar(--slean-shadow-lg)same as light

Focus ring

used by every :focus-visible outline.

TokenLightDark
--slean-focus-ring-colorvar(--slean-accent)same as light
--slean-focus-ringvar(--slean-focus-ring-width) solid var(--slean-focus-ring-color)same as light

Media adjustments

Three media queries in the same file change token values for the whole document. They are listed here from the file as well.

Forced colors

The platform replaces most colors itself; only the tokens that stay author-controlled are mapped to system colors. Query: @media (forced-colors: active).

TokenValue under the query
--slean-focus-ring-colorHighlight
--slean-borderCanvasText
--slean-border-strongCanvasText
--slean-shadow-smnone
--slean-shadow-mdnone
--slean-shadow-lgnone

Reduced motion

Every duration becomes zero. Component files read the duration tokens and never a raw millisecond value, so every transition stops without a second rule. Query: @media (prefers-reduced-motion: reduce).

TokenValue under the query
--slean-duration-fast0ms
--slean-duration-normal0ms
--slean-duration-slow0ms
--slean-duration-indicator1600ms

Coarse pointer

The small control height grows to the pointer target size; checkbox and switch add an invisible hit area of their own. Query: @media (pointer: coarse).

TokenValue under the query
--slean-control-height-sm2.5rem
--slean-control-height-md2.75rem
--slean-control-height-lg3rem

Source

packages/styles/css/tokens.css is the file this page is generated from; its parser is apps/docs/src/lib/data/tokens.ts. The package's static check (scripts/check.mjs) fails when a component file defines a token, references one that does not exist, or when the two dark blocks differ. Measured size of the file, minified: 2204 B gzip · 1895 B brotli.