npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aurea-uds/tokens

v0.6.0

Published

Design tokens for Aurea UDS: the DTCG source and the CSS custom properties generated from it.

Readme

Aurea foundations — what the tokens govern, and what they do not

Canonical answer to "which axis owns this value". Written in Phase 6 of the audit plan, because the audit found the foundations documented nowhere: density and theme both promised things no document defined, and a quarter of the tokens had no consumer (findings M2, M17, M18).

Counts live in STATE.md, generated and gated. This file holds the rules.


The axes

| Axis | Tokens | Unit | Notes | |---|---|---|---| | Colour | --<semantic>, --<family>-<step> | oklch / hex | semantic first; a ramp step is for building a semantic, not for using directly | | Spacing | --space-0--space-24 | rem | scale with deliberate gaps — not every integer exists | | Type size | --text-xs--text-5xl | rem | | | Type family | --font-ui, --font-editorial, --font-code | — | IBM Plex Sans / Serif / Mono | | Type weight | --weight-regular--weight-bold | number | created in Phase 6; the axis did not exist | | Line height | --leading-none--leading-relaxed | number | --leading-none exists for components whose HEIGHT is a contract | | Letter spacing | --tracking-tight--tracking-widest | em | created in Phase 6 | | Radius | --radius-sm--radius-card, --radius-control | px | --radius-card (22px) and --radius-control (999px) are identity — gated | | Border | --border-width | px | | | Shadow | --shadow-md, --shadow-lg | shadow | the xs/sm steps were removed in Phase 6: both were none and unused | | Layer | --z-sticky--z-toast | number | for OVERLAY stacking. Local z-index: 1/2/3 inside a component is not this axis | | Motion | --duration-*, --ease-* | duration / bezier | | | Icon size | --icon-sm--icon-xl | rem | created in Phase 6; rem so glyphs follow text size | | Touch target | --target-min | rem | 44px at a 16px root — WCAG 2.5.5/2.5.8 | | Breakpoint | --breakpoint-sm--breakpoint-2xl | px | @media cannot read var(), so the CSS repeats the literal and validate.py check 4b guards the scale | | Density | see below | rem | |

New value on any of these axes comes from a token. Raw values in the core are ratcheted per axis by validate.py check 12 against scripts/raw-px-baseline.json: the count may fall, never rise.


Density contract — what actually changes

data-density="compact | comfortable | spacious" changes eight tokens, and only these:

--control-h-xs, --control-h-sm, --control-h-md, --control-h-lg, --control-h-xl, --row-h, --card-pad, --section-gap.

So density changes control height, table row height, card padding and gap between sections.

It deliberately does not change: type size, the general spacing scale, layout gaps, radii, icon sizes or line heights. Density is about how tightly controls pack, not about a second type scale.

This was undocumented until Phase 6, and the promise "three densities" read as if it governed everything. Every control must take its height from --control-h-* — three families did not, and that is why a tab measured 8px shorter than the field beside it in spacious (finding A1). tests/visual/geometry.spec.ts now enforces it.


Theme contract — and one asymmetry, on purpose

data-theme="dark | light". Dark is the base; light overrides.

The two themes are not symmetric, and this is the exception: light overrides six colours that dark leaves at their base value — danger-400, info-400, success-400, warning-400, oracle-300, oracle-400.

Reason: on a light surface those four semantic families need a deeper tone to reach 4.5:1, while on dark the base value already does. Nothing is undefined in dark — it inherits from base, so there is no missing-value bug. What was missing was this paragraph.

Identity does not change between themes: the primary yellow is oklch(0.795 0.184 86.047) in both, and validate.py check 3 fails on the canonical value, not just the token name.


Units: rem for anything that should follow text

Type, spacing, icon sizes, control heights, sidebar width and topbar height are rem, so a reader who doubles the browser font size gets bigger controls instead of clipped text (WCAG 1.4.4, finding M12). The conversion from px was exact (px÷16), so nothing moved at the default root size — the 52 pixel baselines prove it.

Radii stay px: a corner is a physical shape, not text, and scaling it with type size makes a pill stop being a pill.


Tokens with no consumer

63 of 174 distinct names are not referenced by the core. That is not automatically waste:

| Group | Why it exists | |---|---| | --breakpoint-* (5) | @media cannot read var(). The CSS repeats the literal and check 4b guards the scale against them | | --oracle-* (11) | consumed only by apps/docs/docs.css. oracle is vocabulary from the origin app, not the system (finding M9) — these leave with that page | | --chart-* (4) | reserved for charts, which do not exist yet as components | | ramp steps (6) | intermediate steps of the semantic families, kept so a consumer can build a variant | | the rest | used only by docs.css — 14 in total |

The rule going forward: a token is born from a use, not from a scale that looks complete. Phase 6 removed 26 that had no use anywhere (--aether-*, --ember-*, two none shadows, two duplicate radii) and created 15 that were needed immediately.

Duplicates are references, not copies: --radius-full is {radius-control}, so the two names cannot drift. Two tokens with the same number written by hand diverge the day one is adjusted.


Cascade

packages/core/dist/aurea.css wraps tokens and component CSS in @layer aurea. A consumer's own CSS, written without a layer, therefore wins over the library regardless of selector specificity — no !important, no specificity hunting.

Tokens are inside the layer with the core, not outside it. A custom property declaration competes in the cascade like any other: with the tokens outside, the :root override that the core declares inside a media query lost to the base value, and the sidebar jumped 48px. An app that redefines a token in its own unlayered :root still wins over both.