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.