Contributing
The system grows from needs in the product, not from ideas about it. Every change starts with where it is used, reuses what exists when it nearly fits, and arrives with its tests and its documentation.
A token
- Start from the need: where the value is used and which existing role nearly fits.
- Prefer reusing a role. Add one only when the purpose is new, not when the color is.
- Edit the token source in
packages/tokens/src, in the W3C Design Tokens format, then runnpm test: contrast is checked in both themes. - Describe the token in its
$description: this site andtokens.jsonare generated from it. - Renaming or removing a token: mark the old one
$deprecatedwith what to use instead, and keep it for one minor release.
A component
- Native HTML first. Reach for Base UI only for behavior the platform does not offer everywhere: positioning, focus management, typeahead.
- One folder in
packages/components/src: the component, itsindex.tsand onestyles.cssin thesonar.componentslayer, styled with role tokens only. - Document every prop in its JSDoc: the API tables,
api.jsonandllms.txtare read from it. - Test roles, names, keyboard and states with Testing Library, and run axe on what it renders.
- Stay within 3 KB gzipped, script and styles. A larger budget is named in the build with its reason.
- Add its page under Components: examples, sizes, variants and states, do and don’t, accessibility and its keyboard table in
site/src/lib/a11y.ts.
Releasing
- Every change carries a changeset that says what it adds, changes, fixes or deprecates. Both packages are released together, under one version.
- The changelog is written for the people who use the system: what they can now do, what behaves differently and what to replace.
- A release is cut only when the tests, the type check, the size budgets and the contrast contract all pass.