Foundations
Themes
Two themes, Paper and Graphite, from one set of tokens. Each token holds both values, so any part of a page can take either theme.
Paper and Graphite
Paper is the light theme: warm neutral greys with a hint of paper. Graphite is the dark one, tuned on its own rather than inverted. ThemeProvider follows the system unless the reader picks one, and writes data-theme on the page.
import { useTheme } from "@nibapp/ui";function ThemeChoice() { const { preference, setPreference } = useTheme(); // "system", "light" or "dark"; the choice is remembered on this device. return <button onClick={() => setPreference("dark")}>Graphite</button>;}One part of a page in the other theme
Set data-theme on any element. Everything inside it, the components included, takes that theme.
<section data-theme="dark"> {/* Graphite here, whatever the page's theme */}</section>Semantic tokens
Components use these names, not raw colours. They are the stable surface of the theme: a renamed token is a breaking change.
- bg, bg-subtle, bg-muted
- The canvas, a sidebar, a well
- surface, surface-raised, surface-overlay
- Cards, menus and popovers, dialogs
- fg, fg-muted, fg-subtle
- Text, from the most to the least important
- border, border-subtle, border-strong
- Hairlines, which work on any surface
- primary, primary-fg
- The main action: ink, not colour
- accent, focus, selection
- Focus rings, selected text and progress
- success, warning, danger, info
- Status, always with a glyph or words beside it
One accent, used rarely
Actions are ink. The accent marks focus, selected text, progress and a confirmed copy, and almost nothing else: buttons, tabs, switches, checkboxes and links stay neutral. To use your own accent, set these variables after the kit's stylesheet.
/* After the kit's stylesheet */:root { --accent: oklch(58% 0.16 150); --accent-fg: oklch(45% 0.12 150); --accent-subtle: color-mix(in oklab, oklch(58% 0.16 150) 12%, transparent); --focus: oklch(58% 0.16 150); --selection: color-mix(in oklab, oklch(58% 0.16 150) 24%, transparent);}