Foundations
Foundations
Choose tokens for color, type, spacing, shape, and motion. Use semantic tokens for interface roles and palette values when defining a theme.
Overview
Choose tokens by purpose
Use shared tokens such as --color__surface and--spacing__regular across components. Recipe properties such as--button__background apply to a single component; override them locally.
Your changes have passed every check.
Layout
Layout
Use .container to bound a page and .grid.responsive for cards that reflow with the available width.
Start with the layout primitives
<main class="stardwst">
<div class="container"
style="--container__max-width: 72rem;
--container__padding: clamp(1rem, 4vw, 3rem)">
<div class="grid responsive"
style="--grid__min-width: 18rem;
--grid__gap: var(--spacing__xl)">
<article class="card">...</article>
<article class="card">...</article>
</div>
</div>
</main>Color
Color
Use neutral surfaces for content, accent color for actions, and danger color for errors or destructive actions.
Choose semantic tokens before selecting a palette step. Pair accent backgrounds with --color__on-accent, and check text and control contrast on the actual surface. A darker or lighter step alone does not establish an accessible combination.
Pair status color with text, an icon, or another cue. Never make hue the only way to understand a state.
--color__white#ffffff--color__black#000000Brown
--color__brown-<step>Grey
--color__grey-<step>Blue Grey
--color__blue-grey-<step>Slate
--color__slate-<step>Zinc
--color__zinc-<step>Stone
--color__stone-<step>Red
--color__red-<step>Pink
--color__pink-<step>Purple
--color__purple-<step>Deep Purple
--color__deep-purple-<step>Indigo
--color__indigo-<step>Blue
--color__blue-<step>Light Blue
--color__light-blue-<step>Cyan
--color__cyan-<step>Teal
--color__teal-<step>Green
--color__green-<step>Light Green
--color__light-green-<step>Lime
--color__lime-<step>Yellow
--color__yellow-<step>Amber
--color__amber-<step>Orange
--color__orange-<step>Deep Orange
--color__deep-orange-<step>Palette names combine a family and a shade, such as --color__cyan-900. Higher numbers are darker. Accent shades use a capital A, as in --color__cyan-A400.
Semantic color scales
Primary uses Cyan, negative uses Red, and text uses Zinc. Use the role tokens below for common surfaces and states; choose a scale step when those roles do not cover the need.
Primary
--color__primary-<step>Negative
--color__negative-<step>Text
--color__text-<step>--color__backgroundvar(--color__zinc-50)--color__surfacevar(--color__white)--color__surface-subtlevar(--color__zinc-100)--color__surface-mutedvar(--color__slate-100)--color__border-subtlevar(--color__zinc-200)--color__bordervar(--color__zinc-300)--color__border-mutedvar(--color__slate-200)--color__border-strongvar(--color__slate-300)--color__accent-subtlevar(--color__primary-50)--color__accentvar(--color__primary-900)--color__accent-hovervar(--color__primary-800)--color__accent-focusvar(--color__primary-700)--color__info-subtlevar(--color__blue-50)--color__infovar(--color__blue-800)--color__info-strongvar(--color__blue-900)--color__on-infovar(--color__white)--color__success-subtlevar(--color__green-50)--color__successvar(--color__green-800)--color__success-strongvar(--color__green-900)--color__on-successvar(--color__white)--color__warning-subtlevar(--color__orange-50)--color__warningvar(--color__orange-900)--color__warning-strongvar(--color__deep-orange-900)--color__on-warningvar(--color__zinc-950)--color__danger-subtlevar(--color__negative-50)--color__dangervar(--color__negative-700)--color__danger-strongvar(--color__negative-800)--color__on-dangervar(--color__white)--color__on-accentvar(--color__white)--color__on-accent-mutedvar(--color__slate-50)--color__text-on-accent-subtlevar(--color__slate-600)Typography
Typography
Use display text for titles, sans-serif for body copy and controls, and monospace for code. Heading levels follow document structure, regardless of visual size.
The family tokens use generic browser fonts, so appearance varies by operating system. Use --tracking-label for compact uppercase labels.
--font-family__displayMake the important thing easy to find.
Tracking:--tracking-display--font-family__sans-serifBody text carries instructions and explanations. Keep line length comfortable and make the useful detail easy to scan.
Default line height: 1.6--font-family__monospacepnpm --dir design-system docs:build
Use for code, keyboard input, and fixed-width data.Spacing
Spacing
Keep labels close to controls and larger gaps between groups. For shared layout spacing, choose --spacing__narrow, --spacing__regular, or --spacing__wide.
--spacing__2xs0.25rem 4 px
--spacing__xs0.5rem 8 px
--spacing__sm0.75rem 12 px
--spacing__md1rem 16 px
--spacing__lg1.25rem 20 px
--spacing__xl1.5rem 24 px
--spacing__2xl1.75rem 28 px
Shape and depth
Shape and depth
Separate content with spacing and borders. Reserve stronger shadows for overlays; use full roundness for circles and pills.
Start with --roundness for corners and --shadow for depth. When surfaces overlap, use the shared --z-index__ scale to define their order.
--roundness__none--roundness--roundness__full--shadow__none--shadow__inner--shadow__level-1--shadow__level-2--shadow__level-3Motion
Motion
Motion should clarify a relationship or acknowledge an action. Stardwst pairs --transition__duration with --easing__out-expo for quick state changes. Hover the example to see the default transition.
--transition__duration175ms
Theming
Theming
Set data-theme on the island or an ancestor, then set any product-specific overrides on the .stardwst boundary that contains the interface. Dark mode changes semantic roles, while named palette values remain stable. Review the theme across buttons, fields, menus, and dialogs, including hover, focus, disabled, and error states.
The default theme uses compact corners, cyan accents, and light neutral surfaces.
<main data-theme="dark">
<section class="stardwst product-theme">
<button class="button filled">Save</button>
</section>
</main>
<style>
.product-theme {
--roundness: var(--roundness__sm);
}
</style>The ancestor supplies the dark semantic roles; the island keeps the product's shape choice local. Use a recipe override only when the adjustment belongs to that one component.
Token reference
Look up a token
Find exact names and values for typography, spacing, shape, motion, and accessibility. For color tokens, use the palette swatches above.
Typography
--font__ratio1.618--font-family__displaysans-serif--font-family__serifserif--font-family__sans-serifsans-serif--font-family__monospacemonospace--font-size__2xs0.5rem--font-size__xs0.75rem--font-size__sm0.875rem--font-size__md1rem--font-size__lg1.25rem--font-size__xl1.75rem--font-size__2xl2.5rem--font-size__3xl3.5rem--tracking-display-0.025em--tracking-label0.08em
Spacing
--spacing__2xs0.25rem--spacing__xs0.5rem--spacing__sm0.75rem--spacing__md1rem--spacing__lg1.25rem--spacing__xl1.5rem--spacing__2xl1.75rem--spacing__narrowvar(--spacing__sm)--spacing__regularvar(--spacing__md)--spacing__widevar(--spacing__lg)
Shape and depth
--roundness__none0--roundness__full9999px--roundness__2xs0.125rem--roundness__xs0.25rem--roundness__sm0.375rem--roundness__md0.5rem--roundness__lg0.625rem--roundness__xl0.75rem--roundness__2xl0.875rem--shadow__none0 0 #0000--shadow__innerinset 0 2px 4px 0 rgb(0 0 0 / 0.05)--shadow__level-10 1px 2px 0 rgb(0 0 0 / 0.05)--shadow__level-20 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)--shadow__level-30 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)--z-index__autoauto--z-index__00--z-index__1010--z-index__2020--z-index__3030--z-index__4040--z-index__5050--z-index__-50-50--z-index__-40-40--z-index__-30-30--z-index__-20-20--z-index__-10-10--roundnessvar(--roundness__2xs)--thickness1px--shadowvar(--shadow__level-1)
Motion
--easing__in-sinecubic-bezier(0.12, 0, 0.39, 0)--easing__out-sinecubic-bezier(0.61, 1, 0.88, 1)--easing__in-out-sinecubic-bezier(0.37, 0, 0.63, 1)--easing__in-quadcubic-bezier(0.11, 0, 0.5, 0)--easing__out-quadcubic-bezier(0.5, 1, 0.89, 1)--easing__in-out-quadcubic-bezier(0.45, 0, 0.55, 1)--easing__in-cubiccubic-bezier(0.32, 0, 0.67, 0)--easing__out-cubiccubic-bezier(0.33, 1, 0.68, 1)--easing__in-out-cubiccubic-bezier(0.65, 0, 0.35, 1)--easing__in-quartcubic-bezier(0.5, 0, 0.75, 0)--easing__out-quartcubic-bezier(0.25, 1, 0.5, 1)--easing__in-out-quartcubic-bezier(0.76, 0, 0.24, 1)--easing__in-quintcubic-bezier(0.64, 0, 0.78, 0)--easing__out-quintcubic-bezier(0.22, 1, 0.36, 1)--easing__in-out-quintcubic-bezier(0.83, 0, 0.17, 1)--easing__in-expocubic-bezier(0.7, 0, 0.84, 0)--easing__out-expocubic-bezier(0.16, 1, 0.3, 1)--easing__in-out-expocubic-bezier(0.87, 0, 0.13, 1)--easing__in-circcubic-bezier(0.55, 0, 1, 0.45)--easing__out-circcubic-bezier(0, 0.55, 0.45, 1)--easing__in-out-circcubic-bezier(0.85, 0, 0.15, 1)--easing__in-backcubic-bezier(0.36, 0, 0.66, -0.56)--easing__out-backcubic-bezier(0.34, 1.56, 0.64, 1)--easing__in-out-backcubic-bezier(0.68, -0.6, 0.32, 1.6)--transition__easingvar(--easing__out-expo)--transition__duration175ms
Accessibility
--disabled-opacity0.5
Accessibility
Accessibility
The foundation supplies visible keyboard focus, scoped selection colors, reduced-motion behavior, and a visually hidden utility. These defaults help, but each component still needs meaningful structure, labels, and states.
Use --disabled-opacity for a consistent disabled appearance. Preserve the native disabled state and explain why an action is unavailable when it may be unclear.
Keep focus visible
The default focus ring is 2 px with a 3 px offset. Check that it stays visible against each surface and is not clipped by surrounding containers.
Respect motion preferences
When reduced motion is requested, the base styles shorten CSS animation and transition durations. Keep state changes understandable without movement and check any custom JavaScript animation separately.
Preserve accessible names
Use .visually-hidden when useful text should remain available to assistive technology.
Test every combination
Complete the task with a keyboard and at 200% zoom. Check contrast in every theme and state, then review names, reading order, and announcements with a screen reader.