Skip to content

Styling and tokens

https://umbra.local/shared/umbra.css gives every widget the same foundation: the Segoe UI Variable font stack, tabular numbers (.num) and a set of design tokens. Use the tokens instead of hard-coded colors, so the user’s theme and appearance settings restyle your widget.

Token Default Used for
--bg #000 Window background
--surface-1, --surface-2, --surface-3 #0a0a0c, #111114, #17171c Cards and raised areas
--line, --line-strong white at 7 % / 12 % Hairlines and borders
--text, --text-2, --text-3 #f4f5f7, #a3a7b1, #6b707b Primary, secondary and muted text
--accent, --accent-strong, --accent-soft #8b93ff, #a9afff, 14 % accent Highlights, active states, glows
--up, --down, --flat #2fd58b, #ff5a5f, #9aa0aa Rising, falling and unchanged values
--radius-s, --radius-m, --radius-l 8px, 12px, 18px Corner radii

Read shared/umbra.css for the complete list.

.card { background: var(--surface-1); border: 1px solid var(--line); border-radius: var(--radius-m); }
.delta.up { color: var(--up); }
.delta.down { color: var(--down); }

The host turns the active theme into one :root { ... } rule, which umbra.js applies after umbra.css. A widget that uses tokens follows the theme live. Set "themeable": false in the manifest to opt out.

On top of that, the user can set:

  • a corner radius (overrides --radius-s/m/l),
  • an accent color (--accent, --accent-strong, --accent-soft, also umbra.settings.accent; empty means the theme, “Match Windows accent” follows the system),
  • light text (brighter --text*),
  • an interface font (--font, --font-display) and text size (--font-scale, applied to the base font size, so use em/rem to follow it),
  • a window border, and reduce transparency (solid --line* and --accent-soft; avoid translucent colors of your own if you want to honor it).

<html data-motion="on|off"> reflects the user’s Animations setting and Windows’ reduced-motion preference, and umbra.css turns off CSS animations when it’s off. Calm animation speed sets --motion-scale: 2; multiply your durations:

.panel { transition: opacity calc(200ms * var(--motion-scale, 1)); }

umbra.tween skips straight to the end value when motion is off.

When Windows has a contrast theme on, the page runs with forced-colors: active. Windows replaces colors and drops box-shadows and most backgrounds, and umbra.css maps the tokens to system colors (Canvas, CanvasText, Highlight; --up, --down and --flat all become CanvasText), ignoring theme tokens. To stay readable:

  • draw borders and separators with border or outline, not shadows,
  • don’t rely on color alone: give a rising or falling value the trend-up or trend-down class and umbra.css adds ▲ or ▼ in front of it (only in that mode),
  • use forced-color-adjust: none only for things that must keep their own colors, such as a chart, and pick system colors yourself then.

Layout in CSS pixels and let the page fill its window. Users can resize a widget freely, and Umbra zooms the page; see Page and lifecycle. Follow the design guidelines for the house style.