Overview
Halbton
A pastel-first design system for software people look at all day.
The argument
Most design systems optimise for contrast and density — maximum information, maximum separation, built for dashboards you scan. Halbton optimises for sustained attention: software people sit in front of for eight hours.
Halbton is German for both halftone and semitone — a half-step, the smallest interval that still changes the chord. That is a structural commitment, not a nice name: elevation and state changes here are deliberately one step smaller than convention, and the system argues for why rather than apologising for it.
The problem it has to solve
Pastel surfaces and WCAG AA are in tension. Pale hues are surfaces, not text, and a system that pretends otherwise ships illegible interfaces with a colour palette that looked good in the pitch. Every hue here ships as a ten-step ramp with an explicit text-safe boundary, and every published pairing carries its measured ratio.
Four layers, in this order
Tokens are applied in one direction: the page, then the things on it, then the marks on those, then meaning. A token never reaches back up a layer.
| # | Layer | Rule | Tokens |
|---|---|---|---|
| 01 | Canvas | The page itself. One per theme, plus one recess. Never carries meaning. | 2 |
| 02 | Surface | Elevation, not decoration. Each step is deliberately half the size convention would use. | 3 |
| 03 | Content & border | Discrete tokens at every tier. Never an opacity modifier over a colour token — that silently produces an invalid declaration and gets dropped. | 7 |
| 04 | Semantic roles | Named by meaning, never by hue. The palette can be replaced without renaming a single token. | 15 |
There is nothing to install
Halbton is not on npm and has no registry entry. What exists is this site and the token source behind it. The four layers below are the whole system; the CSS this page is rendered with was generated from them by the build. Read it, take what is useful, and adapt the naming to your own product.
/* Halbton's tokens are generated from a single JSON source.
Copy the generated custom properties, or the JSON, and adapt.
Nothing here is a package — it is a worked example. */
.your-scope {
--ht-canvas: #FCFCFB;
--ht-surface: #FDFDFC;
--ht-content: #292F36;
--ht-informational-surface: #E9EFFC;
--ht-informational-content: #3D4A6B; /* 7.62:1 — measured, not guessed */
}
[data-theme="dark"] .your-scope {
--ht-canvas: #111214;
--ht-surface: #17191C;
--ht-content: #ECEFF3;
--ht-informational-surface: #3D4A6B; /* deep end, not "darkened" */
--ht-informational-content: #D7E1F9; /* 6.70:1 */
} What is not here yet
Phase one covers the token spine, dark mode, and two components documented properly. The rest is named below rather than stubbed out — a page that looks finished and is not costs more trust than an empty one.
- The remaining six documented components — Text field, Select, Toast, Tabs, Data table, Empty state.
- The specified catalogue: every other component as a visual specimen with an honest status label.
- Patterns — form validation, empty states, loading, destructive confirmation, long-form reading.
- The generated contrast matrix of every published pairing.
- Typography, Spacing, Elevation, Motion and Iconography foundations.
Start with Colour, which is where the accessibility argument actually gets made.