Modes
Theme, density, the cut, motion and direction are classes or attributes. Set one on <html> for the whole app, or on any element for the region inside it. Menus and popups opened from that region follow it.
Loading the live example…
Overview
Modes change how Keyline is tuned, not what it is: border weights, square corners and the signal colours' jobs stay the same in every mode.
Dark mode
Keyline follows a .dark or .light class on an ancestor. It does not read prefers-color-scheme itself. shadcn's dark-mode setups (next-themes with attribute="class", or its Vite theme provider) already set that class, so nothing else is needed.
Dark is tuned, not mirrored. Surfaces lift off black, primary text stops short of white, edges step down in tone by role, and the inverse fill is a light grey rather than white.
Density
Density sets control height, row height, inset, gutter, base type size and the cut's sizes. It never changes border weights. The figures below are control height · row height · inset · gutter · type size.
Each density states all of its sizes, so a compact region inside a comfortable page does not inherit the page's 16px gutter.
Cut
The cut is an optional diagonal accent on frames and controls, off by default. data-kl-cut sets it for a region, or set --kl-cut directly: 0 off, 0.5 quiet, 1 full.
Outside Chromium the cut is drawn with clip-path, and a focus outline stops at the diagonal instead of following it.
Right to left
Keyline's CSS and its components that read layout from the DOM (Toolbar, Slider, Scroll Area, Carousel) follow the DOM's dir. Base UI decides which side a tooltip, popover, hover card or menu opens on, and which way its arrow keys go, from its own provider. DirectionProvider sets both and adds no box:
Reduced motion
data-kl-motion="reduce" on a region, or prefers-reduced-motion: reduce in the reader's system, sets every motion duration to zero. State still changes, at once: a band jumps instead of stretching, a panel opens without unfolding.
Timings are tokens too (--kl-t-flood, --kl-t-unfold, --kl-stretch-lead, …), and two set a behaviour you can turn off for one region:
A mode for one region
Every mode composes on one element. Overlays opened from inside the region (select lists, menus, popovers, dialogs, tooltips, toasts) render under <body> but carry the region's theme, density, motion, direction and tokens with them. There is no provider to add.
To change the palette or fonts of a region as well, make it a configuration scope (see Configuration).