Principles and governance
What the system optimizes for, and the rules that keep it coherent as it grows: how tokens are organized and named, how themes work, what is tested, and how changes are versioned.
Principles
-
Figures first
People open Sonar-DB to read quantities: pallets on hold, deliveries due, invoices overdue. Type stays small and steady, and hierarchy comes from weight and color, so a column of figures scans in one pass.
-
Measured, not picked
Neutrals come from one formula, text levels from contrast targets, springs from a duration and a bounce. A value that can be explained can be extended without guessing.
-
Calm by default, expressive on purpose
Motion settles without overshoot and color is reserved for meaning. The Material 3 Expressive character shows in shape and in two moments: dropping a card into place and a confirmed success.
-
One system at every width
From a 402 px phone to a five-column ultra-wide monitor, the same tokens and the same components. Layouts are derived from the desktop reading order rather than designed five times.
-
Accessible by contract
Contrast targets are written down and tested on every build. Touch targets are 48 px, status never relies on color alone, and reduced motion is respected.
Three tiers
Tokens are layered. Each tier only refers to the one below it, so a palette change reaches every component through the roles, and a component never hard-codes a color.
-
Palette
Raw colors, named by hue and tone. The same in both themes.
--sonar-palette-neutral-21 -
Roles
What a value is for. The themes are two sets of values for the same roles.
--sonar-color-text-default -
Components
Components read roles. Component-specific tokens arrive with the components.
.row-label { color: var(…) }
Naming
Every custom property starts with --sonar-, then goes from general to specific. Palette names describe
what a color looks like; every other name describes what it is for, so a role keeps its name when its value changes.
Names are in English, in full words, without abbreviations.
| Example | Pattern | Note |
|---|---|---|
--sonar-palette-neutral-24 |
palette-{family}-{tone} |
Describes appearance. Never used by components. |
--sonar-color-text-tertiary |
color-{role}-{level} |
Describes purpose. Values change with the theme. |
--sonar-color-on-accent-tonal |
color-on-{fill} |
Content placed on a colored fill. |
--sonar-color-state-hover |
color-state-{interaction} |
Translucent layer added on interaction. |
--sonar-type-title-lg |
type-{role}-{size} |
A font shorthand; tracking is -tracking. |
--sonar-motion-spatial-fast-easing |
motion-{kind}-{speed}-{part} |
Duration and easing come in pairs. |
Themes
Light and dark define the same roles with different values. Without any attribute, the system follows the operating
system. data-theme="light" or data-theme="dark" forces a theme on the element and everything
inside it, which is how this site shows both themes side by side.
The dark theme is not an inversion. Its text levels are chosen to reach the same contrast on dark surfaces as the light ones do on light surfaces, so a role reads with the same weight in both.
Accessibility
The system aims at WCAG 2.2 AA. Contrast is a contract in the tokens package, tested in both themes on every build; focus, target sizes, motion, keyboard and screen readers are built into every component. Accessibility sets out each commitment, the measured ratios and how they are checked.
Versioning
- Patch: a value adjusted without a visible change (under 1 ΔE), or documentation.
- Minor: new tokens, new roles, new components.
-
Major: a token renamed, removed or given a different meaning. The old name is kept for one minor
release, marked
$deprecatedin the token source, before it goes.
What changed in each release is in the changelog; how to propose a token or a component, in Contributing.