@oyavoya/design-tokens
v0.2.0
Published
Voya shared web design language — CSS custom-property tokens (dark + light palettes).
Downloads
494
Maintainers
Readme
@oyavoya/design-tokens
The Voya shared web design language as a single, versioned CSS file: every color, font stack, radius, and shadow as CSS custom properties, with a dark palette (default) and a light palette.
This package is the source of truth for the tokens. It replaces the old
"copy theme.css forward into every app" workflow — apps now depend on a
published version and pick up palette changes through a normal dependency bump
(Renovate/Dependabot), so the copies can no longer drift.
The canonical reference implementation and design rationale live in
Oyavoya/tool-catalog→docs/design-language.md. This package ships the tokens described there.
Install
The package is published to the public npm registry under the @oyavoya
scope. No .npmrc, registry config, or auth token is needed — it installs like
any other public package:
npm install @oyavoya/design-tokensUse
Import the stylesheet once, at your app's entry point, before your own stylesheet so your component styles can reference the tokens:
import '@oyavoya/design-tokens/theme.css'
import './styles.css'(Vite, Next, and webpack all resolve CSS subpath imports from node_modules.)
Theme switching
The active theme is an explicit attribute on the root element
(<html data-theme="dark"> or "light"). Add this pre-paint script to your
HTML entry point, before any stylesheet, so there's no flash of the wrong theme.
It can't ship as a module import — it must run inline before first paint:
<script>
try {
var t = localStorage.getItem('voya-theme')
if (t !== 'light' && t !== 'dark') {
t = matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'
}
document.documentElement.dataset.theme = t
} catch (e) {
document.documentElement.dataset.theme = 'dark'
}
</script>Reuse the same voya-theme localStorage key everywhere so a person's choice
follows them across apps on the same origin.
The one rule
No raw hex values outside this file. Component styles reference tokens only. That single rule is what makes a theme change (or a new theme) a version bump instead of a code sweep. Done-check in a consumer:
grep -nE '#[0-9a-fA-F]{3,8}' src/**/*.css # should return nothingSee the token reference and usage rules (one accent, semantic status, badge triples, nesting surfaces, adding a domain color) in the tool-catalog doc linked above.
Consuming from a component library
A shared component library (e.g. @oyavoya/protocol-builder-core) should
reference these tokens in its styles but not bundle theme.css — the
host app owns the active theme and imports this package once. Libraries should
document the token names they depend on (and may list @oyavoya/design-tokens
as a peerDependency with a floor version so the contract is discoverable).
Releasing
theme.css is the source of truth. Releases are automated with
Release Please — you never tag
or bump the version by hand:
- Edit
theme.csson a branch and open a PR with a Conventional Commit title/message (see mapping below). Do not editversioninpackage.json— Release Please owns it. - Merge the PR to
main. Release Please maintains a rolling "release PR" that bumps the version and updatesCHANGELOG.mdfrom the merged commits. - Merge the release PR. That tags
vX.Y.Z, creates the GitHub Release, and publishes to the public npm registry in the same run — via OIDC trusted publishing, so there is noNPM_TOKENto store or rotate. (One-time setup: on npmjs.com, add a Trusted Publisher for this repo'srelease-please.ymlworkflow. The package must have0.1.0published manually once before the trusted publisher can be added.)
Commit type → version bump (this is the whole versioning policy):
| Change | Commit | Bump |
| --- | --- | --- |
| Add a token | feat: | minor |
| Tweak a value, visually equivalent | fix: | patch |
| Recolor/remove a token in a way that changes existing UIs | feat!: or BREAKING CHANGE: | major |
Consumers pick these up via Renovate: patch/minor auto-merge; major is held for human review (a breaking recolor can change every app — it deserves eyes and a screenshot).
