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

@8x8/oxygen-theme

v3.0.0

Published

Oxygen - Theme

Readme

8x8 Oxygen - Theme

This package holds theme definitions and color palettes.

Usage

You don't need to use this. Instead make of of the OxygenProvider component, which exposes the theme object directly to your components. Please look into @8x8/oxygen-config instead.

You can use the example pages to see the available colors and tokens.

Semantic tokens

Alongside the primitive tokens (action01, ui06, error01, ...) the theme exposes an intent-named semantic layer at theme.semanticColor.*. Semantic tokens resolve to the same hex values as the primitives they map to — they exist so component styles can declare intent ("use the danger-feedback color") rather than position on a scale ("use error01").

// Primitive (still supported)
color: ${({ theme }) => theme.error01};

// Semantic (recommended for new code where covered by the spec)
color: ${({ theme }) => theme.semanticColor.feedback_label_text_danger};

Both produce the same rendered pixels. Light and dark themes resolve the same semantic to different primitives where appropriate; theme.semanticColor.bgSurface is #FFFFFF in light and #171719 in dark, because the underlying ui06 primitive differs per theme.

How the layer is structured

| What | Where | |---|---| | Spec (design's source of truth) | semantic-mapping.json at the package root | | Generated runtime mapping | src/semantic/color.ts | | Generated TS interface | src/semantic/types.ts (exports SemanticColor) | | Runtime resolver | src/semantic/buildSemanticColor.ts | | Generator | scripts/generateSemantic.ts | | Validator | scripts/validateDescriptions.ts |

Naming convention

The spec uses dotted names; the JS identifier is the dotted path with the leading color. stripped and remaining . replaced with _:

| Spec key | JS identifier on theme.semanticColor | |---|---| | color.bgSurface | bgSurface | | color.bgSurface.inverse | bgSurface_inverse | | color.icon.onBgSurface.inverse | icon_onBgSurface_inverse | | color.feedback.label.text.danger | feedback_label_text_danger |

The dotted spec name is preserved as a @semanticName JSDoc tag on every entry, so IDE hover always shows the canonical name.

Generating the semantic layer

The semantic files under src/semantic/ are generated — do not edit by hand. Re-run the generator whenever semantic-mapping.json changes:

yarn workspace @8x8/oxygen-theme run generate:semantic

This rewrites src/semantic/color.ts and src/semantic/types.ts. Commit the regenerated files alongside the spec change.

The generator also runs automatically as part of prebuild, followed by validateDescriptions. The validator fails the build when:

  1. Any token (primitive or semantic) lacks a JSDoc description.
  2. Any semantic-mapping.json entry has no description or no oxygenToken.
  3. A semantic entry's oxygenToken does not exist on Theme.
  4. A semantic's underscore-flat JS key collides with an existing primitive on Theme.
  5. The committed src/semantic/* files are out of date with the live spec (forgot to re-run the generator).

Resolution model & forward-looking metadata

Today every semantic entry has three reference fields:

{
  "oxygenToken":        "ui06",
  "lightPaletteToken":  "white",
  "darkPaletteToken":   "purple01"
}

At runtime the resolver uses only oxygenToken to look up the value (theme[oxygenToken]). The two *PaletteToken fields look redundant — they're not. They are forward-looking metadata for the resolution model we expect to grow into:

| Resolution mode | Status | What the resolver reads | When to use | |---|---|---|---| | Named primitive (oxygenToken) | Active | theme[oxygenToken] | Every entry today. Goes through the named layer (action01, ui06, error01, ...). | | Palette-direct (lightPaletteToken + darkPaletteToken) | Reserved | colorPalette[lightPaletteToken] / colorPalette[darkPaletteToken] per theme | A future entry whose intent doesn't have — or shouldn't depend on — a named primitive equivalent. Bypasses the named layer entirely. |

Why this matters. Today's tight coupling between semantics and named primitives means that any future restructuring of the named layer (deprecating error01, renaming ui06, etc.) would force every dependent semantic to be migrated in lockstep. By carrying palette-token metadata on every entry from day one, design retains the option to publish entries that skip the named layer and resolve straight to a palette color.

The current validator already checks that lightPaletteToken / darkPaletteToken exist on colorPalette when present — so they can't silently rot. When the resolver is extended to consume them, no spec migration is needed; the fields are already there.

For now, treat the palette tokens as reference metadata: useful in Storybook and MCP for showing the developer where a color comes from on the palette ramp, and a green-light for future resolution flexibility.

Adding or changing semantic tokens

  1. Edit semantic-mapping.json (this is design's contract — coordinate with design before changing).
  2. Run yarn workspace @8x8/oxygen-theme run generate:semantic.
  3. Commit semantic-mapping.json and the regenerated src/semantic/* files together.
  4. The next yarn build runs the generator + validator automatically and confirms integrity.

What semantics do NOT do

  • They do not emit CSS variables. The semantic layer is JS-only. CSS variables continue to cover the primitive layer (--ui06, --text-color01, ...).
  • They do not replace primitives. Primitives stay exported with the same names and values forever; semantic adoption is opportunistic per component.
  • They do not cover spacing / motion / radius / elevation / typography yet — only color. When design publishes mappings for additional categories, the generator picks them up as sibling namespaces (theme.semanticSpacing.*, theme.semanticMotion.*, etc.) with no consumer-side migration.