System
Governance
Solace is maintained as a versioned product — built from a single token source, released under semver via Changesets, and held to a published accessibility and contribution standard.
Principles of the system
Three rules hold the system together. They are not aspirations; they decide whether a change is allowed in.
- Tokens are the single source of truth. Color, type, space, motion, and elevation are defined once as W3C DTCG JSON and compiled by Style Dictionary into CSS variables, the Tailwind preset, and TypeScript types. Nothing downstream hardcodes a value the tokens already own.
- Components consume semantic tokens only. A component never reaches for a primitive like
color.sand.500. It binds to intent —color.bg.canvas,color.text.primary— so that retheming is a token concern, never a component rewrite. - Accessibility is non-negotiable. Every component ships meeting WCAG 2.2 AA. An inaccessible component is not "done," and accessibility regressions block release the same way a failing test does.
Token naming convention
Tokens flow through three tiers. Each tier may only reference the tier above it, which keeps theming and refactors contained.
| Tier | Role | Example | May reference |
|---|---|---|---|
| Primitive | Raw, immutable values | color.sand.500, space.4, font.size.lg | nothing |
| Semantic | Mode-aware intent aliases | color.bg.canvas, color.text.primary, color.accent | primitives |
| Component | Per-component contracts | button.primary.bg, input.border, card.padding | semantic tokens |
Naming is tier.category.role.variant in dot notation — readable in JSON, in code, and in design.
Semantic tokens resolve across two dimensions at once: brand (B2C warm ↔ B2B cool) and scheme (light ↔ dark). That gives four resolved modes from one semantic layer — for example, color.bg.canvas returns a warm cream in B2C light and a deep cool in B2B dark, while every component referencing it simply follows.
Versioning & releases
Solace follows semver, and every change ships with a Changeset declaring its bump. Changesets aggregate into the published changelog and drive the release.
| Bump | Means | Examples |
|---|---|---|
| Major | Breaking change; consumers must act | removing a component or prop, renaming a token, changing default behavior |
| Minor | Backward-compatible addition | new component, new variant, new optional prop, new token |
| Patch | Backward-compatible fix | bug fix, a11y correction, docs-only change, internal refactor with no API change |
Token changes are versioned with the same rules: renaming or removing a token is major, adding one is minor, retuning a primitive value within its contract is patch.
Contribution workflow
Changes move through a fixed path. New components carry one extra step at the front.
- Propose. Open an issue describing the problem and the use cases it serves. For a new component, open an RFC: anatomy, props/API sketch, states, accessibility plan, and prior art. The RFC must establish that the need is shared, not one-off.
- Design review. Align the proposal with foundations and existing patterns before any code. Confirm it uses semantic tokens and introduces no redundant primitives.
- Build with tests. Implement on Radix primitives with CVA variants, styled from tokens. Ship unit tests, interaction tests, and axe accessibility checks alongside.
- Document. Add the docs page — overview, anatomy, props, live playground, variants, accessibility notes, and do/don't — plus a Changeset.
- Review. Maintainers review code, tokens, a11y, and docs together. CI must pass: typecheck, lint, tests, and accessibility checks.
- Release. Merge triggers the Changeset version bump, changelog entry, and publish.
Accessibility standard
Solace targets WCAG 2.2 AA. Components are built on Radix primitives so semantics and ARIA are correct by default, and every component is verified against these requirements:
- Keyboard. Every interactive element is reachable and operable by keyboard, with a logical tab order and no traps.
- Focus. A visible
:focus-visibleindicator that meets contrast against its background — never removed, only styled. - Color contrast. Text and meaningful UI meet AA contrast in all four resolved modes. Color is never the only carrier of meaning.
- Reduced motion. Animation honors
prefers-reduced-motion, degrading to instant or minimal transitions.
Automated axe checks run in CI; they catch regressions but do not replace manual keyboard and screen-reader review during component review.
Deprecation policy
Nothing disappears without warning. Deprecation runs on a predictable, three-step cycle.
- Mark. Flag the API as deprecated with a JSDoc
@deprecatedtag and a console warning in development. The deprecation lands in a minor release. - Document the replacement. State what to use instead, with a migration note and code example, in the docs and changelog. A deprecation is never published without a named successor.
- Remove at the next major. The deprecated API stays available through the current major and is removed only in the next major release, so consumers always have a full major cycle to migrate.
Design ↔ code sync
Tokens are the contract between design and code. Both sides resolve from the same DTCG source: code consumes the Style Dictionary outputs, and the design library mirrors the same primitive, semantic, and component tiers — so a token change propagates to both rather than being reconciled by hand.
A Figma library that mirrors the tokens is a planned stretch goal, added once the coded system has shipped. Until then, the published token reference is the canonical source for both designers and engineers, and any design value not expressed as a token is treated as a gap to close, not a precedent to follow.