Skip to content
weftGitHub

Styling

Design language

An app with warp has one design language: @weft-js/warp's primitives and components, on warp's tokens. Name what a thing is, and the look follows the theme, the dials and the density.

tsx
import { Button, Card, Heading, Input, Row, Stack, Text } from '@weft-js/warp'export function Billing() {  return (    <Stack as="section" gap="section">      <Heading level={1} role="title">Billing</Heading>      <Card title="Card on file">        <Stack gap="related">          <Text subtle>Visa ending 4242</Text>          <Input label="Billing email" type="email" />          <Row gap="tight" justify="end">            <Button emphasis="ghost">Cancel</Button>            <Button>Save</Button>          </Row>        </Stack>      </Card>    </Stack>  )}

Vocabulary

ThingUse
Vertical flowStack gap align divided
Horizontal clusterRow gap justify align wrap reflow (reflow stacks it below a width step)
ColumnsGrid min cols gap
Side + mainSplit side width at gap
Measured columnCenter max gutter intrinsic
Full-screen, one centred childCover, with data-part="center" on the child
Media boxFrame ratio
Push to the far endSpacer
Sunken regionInset pad
Raised boxCard (warp's surface: <Surface> is weft's canvas)
HeadingHeading level role: level is the outline and picks the look (title for h1, heading for h2 and h3, label below); role overrides it
TextText role tone subtle faint inline
LinkLink href subtle external; a bare <a> still gets warp's colour

gap: none hair tight related group section page, a relationship and not a size: related inside a thing, group between things, section between sections. as picks the element: div section article main header footer nav aside form ul ol. There are no breakpoint props, since boxes answer to their container. @weft-js/core/ds exports these names as constants and types.

style={{ … }} and class still work; the D-codes below tell you when they leave the system. For a named look of your own, use a style group (weft docs style), not a class list.

D-codes

weft check reports them. weft fix applies the safe autofixes. A fix that changes an element is a suggested edit in fix.edits; a raw colour has none, since a token follows the theme and the raw value didn't.

Where the app has warp's tokens (@weft-js/warp in package.json; headless @weft-js/warp-core ships none):

CodeCatchesFix
D001Raw colour, palette classA token or tone
D002Spacing off the scale, or a step by handAutofix when exactly a step
D003Raw type, radius, shadowHeading, Text, radius and elevation tokens; autofix for an exact radius
D004Layout spelled out on an elementStack, Row (suggested edit)
D040The style gate (data-weft="styled") on main content or an h1A secondary part, or no marker
D005A browser-painted control: <button>, <select>, <textarea>, an input type such as date, number or range, or a title tooltipThe warp component (suggested edit for a button)
D006One heading level at two roles across the app, or a bare <hN> beside <Heading>Match the level's main role (suggested edit at each site)
D007A bare <a href><Link>, or Shell's nav (suggested edit)

In every app:

CodeCatchesFix
D011A literal colour pair below 4.5:1Tokens, or better colours
D030A form control with no label<label>, aria-label, warp's label
D031A button or link with no nameText, aria-label, warp's label
D032<img> with no altDescribe it; alt="" for decoration
D033onClick on a non-interactive element<button type="button"> (suggested edit)
D034A control inside a controlOne control
D035A heading level that jumpsThe next level
D036Focus ring removedRemove the override, or add a focus-visible: style
D037Positive tabindex0 (autofix)
D038Two solid Buttons side by sideOne primary action per region
D039<html> with no langSet it

D010 is warp's contrast gate on the seed and tokens. D020–D025 are style groups.

// weft-allow D001: <reason> on the line above keeps one site; the reason is required. check: { design: false } in the config turns these off.

Tokens

The theme is warp({ seed, dials, radius, fonts, tokens }): every value goes through the contrast check. weft tokens writes the resolved tokens to .weft/tokens/ as DTCG 2025.10, one file per theme × expression plus a resolver, for Figma, Style Dictionary or Terrazzo.