Theming

Make the components look like your product (theme, colours, dark mode, CSS variables). Every colour, size, shadow and duration they draw with is a token, a --u-… custom property, and the tokens are the whole styling API: override one with ordinary CSS, for the application or for one region. The table lists each with its light and dark value.

The library writes its CSS in three cascade layers, umriss.tokens, umriss.base and umriss.components. CSS outside any layer wins over every layered rule, whatever its specificity and whatever order the stylesheets load in, so one unlayered :root { --u-color-accent: … } in your stylesheet is the whole override: no !important, no import order (ADR-0021). Inside a layer of your own it wins only if that layer was named after the library's.

Every token with two values is written light-dark(<light>, <dark>) and resolves against the color-scheme the element inherits. The library sets color-scheme nowhere: your html.dark { color-scheme: dark }, or your theme library's, switches the components, nothing set means light, and an element with its own color-scheme is a region in the other mode. An override written light-dark(…) follows the mode; a single colour holds in both.

Style through tokens only. The tokens in the table are the styling API and change only with an entry in the changelog; the data-* attributes and class names in the components' markup are internal and may change in any version (ADR-0045). Where no token reaches what you want to change, ask for one: a selector on the markup breaks without warning.

Examples

Accent for the application

One rule on :root, outside any cascade layer, gives the whole application its own accent: it wins over the library's tokens whatever order the stylesheets load in. Set the accent's seven tokens together, each with a light and a dark value.

import type { CSSProperties } from "react";
import { Badge, Button, Card, CardBody, CardHeader, Checkbox, Link, Stack, Switch, Text } from "@umriss-ui/core";

/* In an application this is one rule in its own stylesheet:

     :root {
       --u-color-accent: light-dark(#4338ca, #818cf8);
       --u-color-accent-hover: light-dark(#3730a3, #a5b4fc);
       --u-color-accent-subtle: light-dark(#eef0fb, #1e1f3d);
       --u-color-accent-subtle-pressed: light-dark(#dfe2f7, #282a52);
       --u-color-accent-text: light-dark(#4338ca, #a5b4fc);
       --u-color-on-accent: light-dark(#ffffff, #1e1b4b);
     }

   Here it is set on the example's root, so the rest of the page keeps the
   library's petrol. */
const INDIGO = {
  "--u-color-accent": "light-dark(#4338ca, #818cf8)",
  "--u-color-accent-hover": "light-dark(#3730a3, #a5b4fc)",
  "--u-color-accent-subtle": "light-dark(#eef0fb, #1e1f3d)",
  "--u-color-accent-subtle-pressed": "light-dark(#dfe2f7, #282a52)",
  "--u-color-accent-text": "light-dark(#4338ca, #a5b4fc)",
  "--u-color-on-accent": "light-dark(#ffffff, #1e1b4b)",
} as CSSProperties;

export default function AccentForTheApplication() {
  return (
    <div style={INDIGO}>
      <Card>
        <CardHeader
          eyebrow="Carrow & Lisle"
          title="Invoice INV-2026-0314"
          actions={<Badge tone="accent">Awaiting approval</Badge>}
        />
        <CardBody>
          <Stack gap={3} align="flex-start">
            <Text size="sm" tone="secondary">
              Marketing · 3 lines · due 31/03/2026 · <Link href="#/theming">Open the approval</Link>
            </Text>
            <Switch label="Remind the approver" defaultChecked />
            <Checkbox label="Copy the account owner" defaultChecked />
            <Button variant="ghost" size="sm">
              Approve
            </Button>
          </Stack>
        </CardBody>
      </Card>
    </div>
  );
}

A token for one region

A token is a custom property and cascades like one: set on a container, it holds for everything inside and nowhere else. The second card sets its own accent, with a light and a dark value.

import type { CSSProperties } from "react";
import { Card, CardBody, CardHeader, Checkbox, Grid, Stack, Switch } from "@umriss-ui/core";

/* In an application this is one rule on the region's class:

     .billing {
       --u-color-accent: light-dark(#7a3e9d, #b98ad6);
     }                                                    */
const BILLING = { "--u-color-accent": "light-dark(#7a3e9d, #b98ad6)" } as CSSProperties;

function Settings({ title }: { title: string }) {
  return (
    <Card>
      <CardHeader title={title} />
      <CardBody>
        <Stack gap={3}>
          <Switch label="Send a weekly summary" defaultChecked />
          <Checkbox label="Copy the account owner" defaultChecked />
        </Stack>
      </CardBody>
    </Card>
  );
}

export default function TokenForOneRegion() {
  return (
    <Grid columns={2} gap={4}>
      <Settings title="Notifications" />
      <div style={BILLING}>
        <Settings title="Billing" />
      </div>
    </Grid>
  );
}

A dark region

The tokens follow the color-scheme an element inherits, and the library sets it nowhere: one element with color-scheme: dark makes everything inside it dark, on a light page too. The first tour follows the page; the second is always dark.

import { Badge, Card, CardBody, CardHeader, Grid, Text } from "@umriss-ui/core";

/* The application's own switch is one CSS line, which its native controls
   need anyway:

     html.dark { color-scheme: dark; }
     :root { color-scheme: light dark; }  (or: follow the system)

   Nothing set means light. A region is the same line on its element:

     .dispatch-board { color-scheme: dark; background: var(--u-color-bg); } */
function Tour({ scheme }: { scheme?: "dark" }) {
  return (
    <div style={{ colorScheme: scheme, background: "var(--u-color-bg)", padding: 16, borderRadius: 8 }}>
      <Card>
        <CardHeader eyebrow="North depot" title="Tour T-03" actions={<Badge tone="warning">2 stops late</Badge>} />
        <CardBody>
          <Text size="sm" tone="secondary">
            FP 214 K · Martin Hale · 14 stops · 86 km
          </Text>
        </CardBody>
      </Card>
    </div>
  );
}

export default function ADarkRegion() {
  return (
    <Grid minItemWidth="240px" gap={4}>
      <Tour />
      <Tour scheme="dark" />
    </Grid>
  );
}

Tokens

Every token the components draw with, grouped as the stylesheet groups them. A swatch is drawn from the token itself, light in the light column and dark in the dark one; "same" means one value for both themes.

Neutral: Ink & Paper

TokenLightDarkDescription
--u-color-bg#fafafa#0f0f10—
--u-color-surface#ffffff#161618—
--u-color-surface-sunken#f4f4f5#1e1e21—
--u-color-surface-pressed#e9e9eb#28282cThe pressed step of a quiet key: what sinks to the sunken surface under the pointer sinks once more while it is pressed (the interaction-state canon). The three -pressed surfaces exist because a hover for each ground needs something stronger.
--u-color-text#171717#ededed—
--u-color-text-secondary#565656#a5a5ab—
--u-color-text-muted#8b8b8b#77777e—

Edges as shadows (instead of borders)

TokenLightDarkDescription
--u-edge-colorrgba(23, 23, 23, 0.08)rgba(255, 255, 255, 0.10)—
--u-edge-color-strongrgba(23, 23, 23, 0.17)rgba(255, 255, 255, 0.20)—
--u-edge0 0 0 1px var(--u-edge-color)same—
--u-edge-strong0 0 0 1px var(--u-edge-color-strong)same—
--u-hairlinergba(23, 23, 23, 0.06)rgba(255, 255, 255, 0.07)inner dividing lines
--u-color-edge-hovercolor-mix(in srgb, var(--u-color-text) 30%, transparent)sameThe edge of a field under the pointer.
--u-hairline-strongrgba(23, 23, 23, 0.12)rgba(255, 255, 255, 0.14)e.g. under table heads

Ink as interaction (the primary button)

TokenLightDarkDescription
--u-color-primary-bg#171717#ededed—
--u-color-primary-fg#ffffff#171717—
--u-color-primary-hover#2e2e2e#ffffff—
--u-color-primary-active#000000#d6d6d6—

Accent (petrol) - interactive things only

TokenLightDarkDescription
--u-color-accent#0e7d72#17a292—
--u-color-accent-hover#0a685f#1cb5a3—
--u-color-accent-subtle#e9f4f2#142e2b—
--u-color-accent-subtle-pressed#d5e9e6#1b3d39—
--u-color-accent-text#0b6a61#4cc4b5—
--u-color-on-accent#ffffff#072522—
--u-color-on-danger#ffffff#2b0f0dType on the danger surface, a token so that a contrast check sees it. Dark: White measures only 3.68:1 on the lighter danger surface. The polarity turns as it does for the accent: dark type on a light ground.

Semantics (muted)

TokenLightDarkDescription
--u-color-success#217a4b#4fae7c—
--u-color-success-subtle#e8f2ec#16241d—
--u-color-warning#8a5c00#d0a24dDarkened from #9a6700, which reached only 4.24:1 on its own pale surface and so missed the 4.5:1 for normal text; this reaches 4.97:1.
--u-color-warning-subtle#f7efdb#2b2415—
--u-color-danger#b13636#d0655c—
--u-color-danger-hover#9a2c2c#da7a72—
--u-color-danger-activecolor-mix(in srgb, var(--u-color-danger) 85%, #000000)color-mix(in srgb, var(--u-color-danger) 85%, #ffffff)Pressed: darker in the light theme. As a mixture rather than a value, so that it follows the ground; the dark theme turns the direction round.
--u-color-danger-subtle#f8eaea#2f1b1d—
--u-color-danger-subtle-pressed#f3dcdc#351e21—
--u-color-danger-text#b13636#d86f66Danger as type, beside the surface - the split the accent has with --u-color-accent-text. Dark: the surface value reached only 4.40:1 on the subtle danger surface; this one is lighter and holds 4.5:1 there and on every ground (tone-contrast). Light: the surface value already passes.

Focus: a crisp accent edge, two pixels, no glow

One look for every component. A soft glow would read as a second, shadowy border. On a field the ring lies where its edge lies, so the edge seems to grow. -danger for an invalid field, which keeps its colour.

TokenLightDarkDescription
--u-focus-ring0 0 0 2px var(--u-color-accent)same—
--u-focus-ring-danger0 0 0 2px var(--u-color-danger)same—

Typography

TokenLightDarkDescription
--u-font-sans"Geist Sans", "Geist", -apple-system, "Segoe UI", system-ui, sans-serifsame—
--u-font-mono"Geist Mono", ui-monospace, "Cascadia Mono", "Consolas", monospacesame—
--u-text-xs0.6875remsame—
--u-text-sm0.8125remsame—
--u-text-md0.875remsame—
--u-text-lg1remsame—
--u-text-xl1.1875remsame—
--u-text-2xl1.5remsame—
--u-text-mono0.75remsameFigures in Geist Mono inside a control or a cell, beside --u-text-sm set in Sans. The mono cut runs wider and taller, so one step down reads as the same size. It serves as a role: the date picker's value, days and time fields, the numeric field and input, the table's numeric cells.
--u-leading-none1sameA box as tall as its type: a badge, a tag, a count, a glyph. The height comes from the control or the padding, and the line adds no leading.
--u-leading-tight1.3same—
--u-leading-normal1.5same—
--u-weight-regular400same—
--u-weight-medium500same—
--u-weight-semibold600same—
--u-tracking-caps0.07emsame—
--u-tracking-display-0.022emsamelarge titles: slightly compressed
--u-tracking-tight-0.011emsamemedium titles (cards, dialogs)
--u-tracking-figures-0.01emsamefigures set in the mono face

Spacing and shape

TokenLightDarkDescription
--u-space-14pxsame—
--u-space-28pxsame—
--u-space-312pxsame—
--u-space-416pxsame—
--u-space-520pxsame—
--u-space-624pxsame—
--u-space-732pxsame—
--u-space-840pxsame—
--u-radius-xs4pxsame—
--u-radius-sm6pxsame—
--u-radius-md8pxsame—
--u-radius-lg12pxsame—
--u-radius-xl18pxsameOne step above the card, for the command palette. It is meant to be a system window and not a form panel, and the radius plays its part in that. Both themes share it - shape is not a question of theme. The sequence 4-6-8-12-18 continues the factor of 1.5 of the steps above.
--u-radius-full999pxsame—
--u-control-height32pxsame—
--u-control-height-sm26pxsame—
--u-control-height-xs18pxsameThe small control on a dense surface - a compact table's row draft and actions (dense in the shared own styles).
--u-icon-size14pxsameThe icon in a button, beside a label or alone (CONTEXT.md, "Icon"): the button decides its size, one step per control height.
--u-icon-size-sm12pxsame—
--u-button-padding10pxsameThe room left and right of a button's label, one step per control height. What stands beside a quiet button and has to align with its word hangs out by exactly this much (the date pickers' foot, the MultiSelect's quick keys) - so they read it here instead of repeating the number.
--u-button-padding-sm6pxsame—
--u-drawer-width400pxsameThe width of a drawer A token rather than a size prop: a detail beside a process picture wants one width across an application, and one drawer that needs another sets it in its style.

Toast

How far the toasts stand from the window's top and bottom edge and from its sides - set it to keep them clear of a fixed header, a toolbar at the bottom or a navigation rail at the side - and how wide a toast is. The region hangs in body, so set them on :root; a media query of your own may set another value per width. The center positions stand in the middle of the window whatever the side tokens are.

TokenLightDarkDescription
--u-toast-inset-topvar(--u-space-5)samefor the three top-* positions; var(--u-space-4) up to 600 px wide
--u-toast-inset-bottomvar(--u-space-5)samefor the three bottom-* positions; var(--u-space-4) up to 600 px wide
--u-toast-inset-startvar(--u-space-5)samefor the *-start positions, and on a phone the room at the start side; var(--u-space-4) up to 600 px wide
--u-toast-inset-endvar(--u-space-5)samefor the *-end positions, and on a phone the room at the end side; var(--u-space-4) up to 600 px wide
--u-toast-width360pxsamea plain length, read it to know whether the deck has room beside a surface; up to 600 px wide the toast takes the window's width less the side tokens instead

Shadow stacks: every step has one job

Card: edge, contact with the ground, soft depth. Overlay: edge, near shadow, depth.

TokenLightDarkDescription
--u-shadow-cardvar(--u-edge), 0 1px 2px rgba(23, 23, 23, 0.04), 0 8px 24px -12px rgba(23, 23, 23, 0.14)var(--u-edge), 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px -12px rgba(0, 0, 0, 0.6)—
--u-shadow-overlayvar(--u-edge), 0 4px 8px rgba(23, 23, 23, 0.06), 0 24px 48px -16px rgba(23, 23, 23, 0.24)var(--u-edge), 0 4px 8px rgba(0, 0, 0, 0.4), 0 24px 48px -16px rgba(0, 0, 0, 0.7)—
--u-shadow-stickyrgba(23, 23, 23, 0.09)rgba(0, 0, 0, 0.5)The shadow a sticking part casts on what scrolls under it - a pinned column block, a stuck group header - as the colour its gradient starts from. Dark is black at a higher opacity: the text colour at 9 % read as a glow on the dark ground.

Translucent material and scrim (ADR-0012)

An overlay meant to be a window ABOVE the application and not a card WITHIN it needs two things: the page behind it must be sensed, and it must never stay readable.

The alpha value is a FLOOR and not a matter of taste: the opaque colour carries legibility on its own, the transparency delivers atmosphere and never contrast. A panel that looks prettier at 0.55 is one whose type is legible by luck. The floor is open upwards, and in the light theme it lies higher than strictly necessary - see below.

Three tokens, because there are three jobs: - -fallback is the opaque colour underneath. It is really painted where backdrop-filter is missing or switched off, and it is what the contrast test checks (see tests-unit/contrast.test.ts). - --u-color-material is the same colour with the floor alpha. - --u-material-blur softens what shows through. Decoration under the same rule: the blur does not make the type legible.

The scrim dims the page behind an overlay. Dark gets its own values, chosen by eye: inverting a light surface lands wrong, because light type over a dark blur tolerates far less transparency than the other way round.

TokenLightDarkDescription
--u-color-material-fallback#fdfdfe#1f1f23The numbers were looked at, not calculated. In the light theme the scrim must dim less and the panel cover more: a scrim that presses the whole page to a middling grey leaves the panel a grey slab within it, legible but looking like a fault. The distance between the two carries the step. The dark theme needs no such correction: there the lightness already separates them. Dark: Chosen by eye, not derived from the light theme: the alpha floor lies higher here, because light type over a dark blur tolerates markedly less transparency.
--u-color-materialrgba(253, 253, 254, 0.86)rgba(31, 31, 35, 0.82)—
--u-material-blur24pxsame—
--u-color-scrimrgba(23, 23, 23, 0.30)rgba(0, 0, 0, 0.60)—

Motion: explains a change of state, does not decorate

The names follow the distinctions the library makes (visuelle-wertigkeit 02); a motion that fits none of them wants a new name here, not a number in its module.

Micro or path. A colour, an edge or an opacity changes in place: that is --u-transition. Something moves, turns or unfolds: that is --u-transition-path, or --u-duration-medium with --u-ease-out for a long way. A press is shorter than either.

Entry or exit. A surface enters on --u-ease-out from its motion origin; it leaves faster, on a curve that starts at once, and does not retrace the way it came - a symmetrical exit makes a surface feel sluggish.

Continuous process. A spinner or a shimmer has no start and no end; it runs steadily and long.

TokenLightDarkDescription
--u-ease-outcubic-bezier(0.22, 1, 0.36, 1)samedecisive, landing softly: entries and paths
--u-ease-exitcubic-bezier(0.2, 0.6, 0.4, 1)sameleaves at once, no wind-up
--u-transition120ms var(--u-ease-out)samemicro: hover, colour. It carried the CSS keyword ease-out and so kept the curve above from three quarters of the library's transitions. 0ms under reduced motion.
--u-duration-press80mssamethe press point of a button or glyph 0ms under reduced motion.
--u-transition-pressvar(--u-duration-press) var(--u-ease-out)same—
--u-duration-fast140mssameentry of a panel; a short path 0ms under reduced motion.
--u-transition-pathvar(--u-duration-fast) var(--u-ease-out)samea chevron turns, a thumb slides
--u-duration-medium240mssameentry of a sheet; a layout change 0ms under reduced motion.
--u-duration-draw320mssamea stroke drawn slowly enough to watch: the tick 0ms under reduced motion.
--u-delay-draw60mssamethe box fills first, then the tick is drawn 0ms under reduced motion.
--u-delay-stale200mssamecontent being reloaded dims only after this: a quick answer never flickers
--u-duration-exit-fast100mssameExits. The stylesheet drawing the movement and the code waiting for its end read the same tokens, so the two cannot drift apart. a panel or a tooltip goes 0ms under reduced motion.
--u-duration-exit160mssamea sheet takes its leave: modal 0ms under reduced motion.
--u-duration-exit-collapse200mssamea message goes and its place closes 0ms under reduced motion.
--u-duration-spin700mssameContinuous processes. They do NOT fall to zero under reduced motion - a spinner at 0ms says nothing; each module slows or stops its own.
--u-duration-shimmer1.6ssame—
--u-duration-sweep1.4ssamean indeterminate progress bar crosses its track
--u-ease-steadylinearsamea turn with no start and no end
--u-ease-swellease-in-outsamea shimmer that comes and goes

Stacking order

Popovers portal into the nearest <dialog> ancestor, and this scale orders the rest. The toasts also move into the topmost modal dialog. Inside a dialog the toasts and the tooltips stand in the top layer, which orders by the moment of showing and not by these numbers: a tooltip is shown after the toasts and lies above them, as the scale has it; popovers stay under the toasts.

TokenLightDarkDescription
--u-z-popover900same—
--u-z-toast1000same—
--u-z-tooltip1100same—

@umriss-ui/charts

The charts' own tokens, set on a chart's root. A token whose value names a core token takes that token, so theming core themes the charts; where core is not loaded, or has no such token (--u-chart-1 to --u-chart-6), the literal after it stands.

TokenLightDarkDescription
--uc-color-axisvar(--u-edge-color-strong, rgba(23, 23, 23, 0.17))same—
--uc-color-gridvar(--u-hairline, rgba(23, 23, 23, 0.06))same—
--uc-color-textvar(--u-color-text-muted, #71717a)same—
--uc-color-bgvar(--u-color-surface, #ffffff)same—
--uc-fontvar(--u-font-sans, "Geist Sans", "Geist", -apple-system, "Segoe UI", system-ui, sans-serif)same—
--uc-font-monovar(--u-font-mono, "Geist Mono", ui-monospace, "Cascadia Mono", "Consolas", monospace)same—
--uc-color-warningvar(--u-color-warning, #8a5c00)sameThe two limit severities. They fall back onto the same tokens with which @umriss-ui/core warns and alarms - a limit in the chart and a tile above it must not be differently red.
--uc-color-alarmvar(--u-color-danger, #b13636)same—
--uc-color-okvar(--u-color-success, #217a4b)same—
--uc-series-1var(--u-chart-1, #2563eb)same—
--uc-series-2var(--u-chart-2, #db2777)same—
--uc-series-3var(--u-chart-3, #059669)same—
--uc-series-4var(--u-chart-4, #d97706)same—
--uc-series-5var(--u-chart-5, #7c3aed)same—
--uc-series-6var(--u-chart-6, #0891b2)same—
--uc-size-tick11.5pxsame—
--uc-size-title12pxsame—
--uc-size-legend12.5pxsame—
--uc-size-tooltip12pxsameThe tooltip's text; its head is an x value and takes the tick's size.
--uc-leading-label1.25sameA label on an axis stands tight to its tick; running text - the legend, the tooltip - gets a little more air.
--uc-leading-text1.35same—
--uc-radius6pxsame—
--uc-radius-chip2pxsameThe colour chips of legend and tooltip, and the legend entry's focus.
--uc-shadow0 1px 2px rgba(0, 0, 0, 0.06), 0 4px 12px rgba(0, 0, 0, 0.08)same—
--uc-focus-ringvar(--u-focus-ring, 0 0 0 2px #0e7d72)same—
--uc-color-hovervar(--u-color-surface-sunken, #f4f4f5)sameA legend entry under the pointer and pressed: core's quiet surfaces, and core's motion for a change in place (the interaction-state canon).
--uc-color-pressedvar(--u-color-surface-pressed, #e9e9eb)same—
--uc-transition-statevar(--u-transition, 120ms cubic-bezier(0.22, 1, 0.36, 1))same—
--uc-transition80ms var(--u-ease-out, cubic-bezier(0.22, 1, 0.36, 1))sameThe tooltip's fade: its own short duration - it follows the pointer and must not lag behind it - on core's curve where core is loaded.
--uc-delay-stalevar(--u-delay-stale, 200ms)sameA course being reloaded dims as the table's rows do (ADR-0042): only after this delay, so that a quick answer never flickers.
--uc-silhouettecolor-mix(in srgb, var(--u-color-text, #18181b) 10%, transparent)sameThe shapes of the silhouette a chart shows while it waits for its rows (chart-loading 03): faint in the text colour, as the table's placeholders.
--uc-ease-swellvar(--u-ease-swell, ease-in-out)sameThe easing of the band that sweeps the silhouette: it swells as the table's shimmer does.
--uc-fadevar(--u-duration-medium, 240ms) var(--u-ease-out, cubic-bezier(0.22, 1, 0.36, 1))sameThe silhouette fading out and the course in, once the rows are there: core's motion for a layout change.

Keyboard

The keys of Button, Checkbox, Switch and Typography apply here.

Props on this page

From StackProps — the full table stands on Stack and Grid.

NameTypeDefaultDescription
gapSpaceStep
| 1
| 2
| 3
| 4
| 5
| 6
| 7
| 8
3Spacing as a step of the 4 px spacing steps (1–8).
alignCSSProperties["alignItems"]—Alignment across the direction – alignItems unchanged.

From GridProps — the full table stands on Stack and Grid.

NameTypeDefaultDescription
columnsnumber | readonly GridColumnWidth[]2How many columns, all of one width - or a list with one width per column: a number in pixels, or "fill" for a share of what is left. Overridden by minItemWidth.
minItemWidthstring—Responsive: as many columns as fit at this minimum width; wins over columns, a list included.
gapSpaceStep
| 1
| 2
| 3
| 4
| 5
| 6
| 7
| 8
4Spacing as a step of the 4 px spacing steps (1–8); applies in both directions.

From CardHeaderProps — the full table stands on Card.

NameTypeDefaultDescription
titlerequiredReactNode—The heading of the card. A node and not merely text, so that an identifier with markup can stand in it too.
eyebrowReactNode—Small all-caps label above the title, e.g. a category.
actionsReactNode—Right-aligned area, e.g. buttons or badges.

From TextProps — the full table stands on Typography.

NameTypeDefaultDescription
sizeTextSize
| "xs"
| "sm"
| "md"
| "lg"
| "xl"
| "2xl"
"md"Type size from the token set. It is independent of the element: a p may be small without becoming a different element.
toneTextTone
| "default"
| "secondary"
| "muted"
"default"How loud the text is. secondary and muted step back without falling below the contrast threshold.

From ButtonProps — the full table stands on Button.

NameTypeDefaultDescription
variantButtonVariant
| "primary"
| "secondary"
| "ghost"
| "plain"
| "danger"
"secondary"How loud the button is. primary exactly once per surface - two main actions side by side are no longer a main action. ghost is quiet in the accent, plain quiet and neutral.
sizeButtonSize
"sm" | "md"
the size of a ControlSizeProvider around it, else "md"sm for buttons in header bars and table rows, md otherwise.

From IconButtonProps — the full table stands on IconButton.

NameTypeDefaultDescription
sizeButtonSize
"sm" | "md"
the size of a ControlSizeProvider around it, else "md"sm for buttons in header bars and table rows, md otherwise. from ButtonProps

From CheckboxProps — the full table stands on Checkbox.

NameTypeDefaultDescription
labelReactNode—Label to the right of the checkbox.

From SwitchProps — the full table stands on Switch.

NameTypeDefaultDescription
labelReactNode—Label to the right of the switch.

From BadgeProps — the full table stands on Badge.

NameTypeDefaultDescription
toneBadgeTone
| "neutral"
| "accent"
| "success"
| "warning"
| "danger"
"neutral"What the badge stands for. There is always a word beside it: a colour on its own is not a statement.

Known limits

What umriss deliberately does not build, and why: ADR-0032.

Every page of @umriss-ui/core

Getting started

Customising

Layout

Typography

Actions

Forms

Choosing

Dates and times

Feedback

Overlays

Navigation

Data display

API index