Self-initiated concept
Canon Design System
A token-driven system in two layers: primitives that never appear in a component, and semantics that are all a component is allowed to reference. Theme and density are attributes on <html> — nothing else has to know they changed.
Primitive tokens
64
Semantic tokens
37
Components
14
Themes × densities
2 × 2
Why two layers
Primitives are the raw ramps — --primary-500, --neutral-800. A component that reads one of those has hard-coded a decision it does not own, and it will fight you the first time the theme changes. Components only read semantics: --bg-surface, --text-secondary, --border-default.
That indirection is the entire reason the toggle in the header works. Light mode is not a second stylesheet — it is the same 37 semantic names pointed at different primitives.
The component layer is plain CSS
No Tailwind, no React required. @import "@canon/ds" gives you the whole system in any stack. The React bindings in this site are thin wrappers that compose class names and wire up the accessibility plumbing — they are a convenience, not the product.