@rgrmdesign/rgrm-ds-tokens
v0.14.0
Published
Design tokens (CSS custom properties) generated from Figma variables via Style Dictionary.
Maintainers
Readme
@rgrmdesign/rgrm-ds-tokens
Design tokens as CSS custom properties, generated from Figma variables with Style Dictionary.
The Figma export (W3C DTCG format) lives in figma/ and is turned into
publishable CSS in dist/ by a build step.
Primary consumer
These tokens are the source of truth for visual design in the
RGRM Design System (@rgrmdesign/rgrm-ds-*).
That monorepo ships component CSS, React components, and Web Components that
reference component tokens from this package (e.g. var(--rgrm-heading-h1-font-size)).
The design system declares @rgrmdesign/rgrm-ds-tokens as a peer dependency,
so consuming apps load the tokens once and share them across all @rgrmdesign/rgrm-ds-*
packages.
| Goal | Where to start |
| --- | --- |
| Use RGRM components (Button, Heading, …) | rgrm-ds — install @rgrmdesign/rgrm-ds-css, -react, or -elements; tokens are pulled in via the peer dependency |
| Browse components and themes | Storybook (deployed from rgrm-ds) |
| Custom UI with only the token variables | This package — install and import the CSS below |
Token changes in this repository are released independently on npm; bump the
@rgrmdesign/rgrm-ds-tokens version in your app (or in rgrm-ds) to pick up
new variables or theme updates.
Installation
npm install @rgrmdesign/rgrm-ds-tokensUsage
Import the complete bundle (root tokens + all themes in a single file):
@import "@rgrmdesign/rgrm-ds-tokens/tokens.css";Or import selectively (load components.css after root and any theme files):
@import "@rgrmdesign/rgrm-ds-tokens/root.css"; /* :root primitives + base theme */
@import "@rgrmdesign/rgrm-ds-tokens/dark.css"; /* [data-theme="dark"] */
@import "@rgrmdesign/rgrm-ds-tokens/brand.css"; /* [data-theme="brand"] */
@import "@rgrmdesign/rgrm-ds-tokens/components.css"; /* component tokens */Output is split into three layers:
root.css(:root) — primitives (--rgrm-core-*,--rgrm-scale-*) and base theme (--rgrm-theme-*).theme-*.css([data-theme="…"]) — theme overrides only.components.css(:where(:root, [data-theme])) — component tokens (--rgrm-paragraph-*,--rgrm-heading-*,--rgrm-button-*, …). These are what component CSS typically consumes; they alias down to theme and scale tokens and are re-declared on themed sections so nested themes resolve correctly.
In practice, component styles read component tokens (--rgrm-<component>-*),
not primitives or theme tokens directly. Names follow
--rgrm-<component>-<variant>-<property>; interaction states use suffixes such as
-hover, -active and -focus-visible:
.rgrm-button--primary {
border-radius: var(--rgrm-button-primary-border-radius);
padding-block: var(--rgrm-button-primary-padding-block-start)
var(--rgrm-button-primary-padding-block-end);
background: var(--rgrm-button-primary-background-color);
color: var(--rgrm-button-primary-color);
}
.rgrm-button--primary:hover {
background: var(--rgrm-button-primary-background-color-hover);
color: var(--rgrm-button-primary-color-hover);
}For custom UI without RGRM components you can still use lower layers directly
(--rgrm-theme-*, --rgrm-scale-*, --rgrm-core-*).
Switching themes
The base theme lives on :root. Enable another theme via the data-theme
attribute (on <html>, <body>, or any container):
<html data-theme="dark">
<!-- or -->
<div data-theme="brand"> ... </div>Theme tokens reference the shared swatch palette variables from :root, so
root.css (or tokens.css) must always be loaded.
Fluid typography and spacing
The scale collection in Figma has a small and a large mode (the min/max
ends of fluid typography and spacing). These are merged into a single set of
clamp() values that scale between the viewport breakpoints
(--rgrm-core-site-viewport-min … --rgrm-core-site-viewport-max). For example:
--rgrm-scale-font-size-main: clamp(1rem, 0.9643rem + 0.1786vw, 1.125rem);Development
This project uses pnpm (via Corepack) and TypeScript (run with
tsx, no separate compile step). Requires Node 22.13+ (see
.nvmrc); pnpm@11 won't run on older Node versions.
corepack enable # one-time: activates the pnpm version from package.json
pnpm install
pnpm run build # generate dist/
pnpm run typecheck # tsc --noEmit(Re)generating tokens
On a new Figma export: replace the files in figma/ and run pnpm run build.
The build does three things:
scripts/restore-aliases.ts– restores cross-collection references. Figma flattens those into literal values while keeping the original link incom.figma.aliasData; this converts them back into real DTCG references.scripts/generate-fluid.ts– merges the scalesmall/largemodes into fluidclamp()tokens.build.ts– runs Style Dictionary in four passes (:rootprimitives + base theme, theme overrides,:where(:root, [data-theme])components) and bundles the output.
Intermediate files go to build/ (git-ignored); the publishable output to
dist/.
Conventions
- Numeric dimensions are converted to
rem(16px base);line-height,font-weight, and ratios stay unitless,letter-spacingusesem. - Colors become hex (opaque) or
rgba()(with transparency). - Figma helpers prefixed with
_are private: they remain usable for reference resolution but are not emitted in the output (references to them are inlined).
Publishing
Releases are versioned with Changesets
and published to npm automatically by GitHub Actions
(.github/workflows/release.yml).
Workflow for a change:
pnpm changeset # describe the change + pick a semver bump
git commit -am "…" # commit code + the new .changeset/*.md
git push # push to main (or open a PR)On push to main the workflow opens a "Version Packages" PR (version bump +
changelog). Merging that PR triggers the actual pnpm release
(changeset publish) to npm.
prepublishOnly automatically runs clean + typecheck + build, so only a
fresh dist/ is published (see the files field in package.json).
Publishing uses npm Trusted Publishing
via OIDC (id-token: write), so no NPM_TOKEN secret is needed and packages are
published with provenance.
