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

@growth-labs/tokens

v0.2.0

Published

Shared design tokens for Growth Labs React/SPA apps: a pinned, tested subset of [DTCG 2025.10](https://tr.designtokens.org/format/) compiled to CSS custom properties scoped `[data-theme][data-mode]`, plus TypeScript types and values. **Pixel** (light and

Downloads

1,993

Readme

@growth-labs/tokens

Shared design tokens for Growth Labs React/SPA apps: a pinned, tested subset of DTCG 2025.10 compiled to CSS custom properties scoped [data-theme][data-mode], plus TypeScript types and values. Pixel (light and dark) is the first theme.

This package owns base semantic roles — surfaces, text, borders, focus, action, type — and their per-theme values. It does not own component markup (one consumer does not warrant a kit yet, see growth-labs-tokens-package.spec.md) and it does not own a consumer's own state semantics: a consumer maps its own meanings (e.g. "stale", "waiting", "decision-needed") onto the base roles and the small status/chart layer below.

Install

pnpm add @growth-labs/tokens

Use the pre-built CSS

@import '@growth-labs/tokens/pixel.css';
<html data-theme="pixel" data-mode="system">

Self-hosted fonts

font.family.* names Pixelify Sans (display), Source Sans 3 (body) and JetBrains Mono (mono) — this package also ships the actual font files, so a consumer never has to load them from Google Fonts or any other third party (the public hub runs behind a strict font-src 'self' CSP). Import the generated stylesheet once, anywhere the bundle already resolves package imports:

@import '@growth-labs/tokens/fonts.css';

It declares exactly the weights the contract and the prototype use — not every weight each font ships — and nothing else: Pixelify Sans 600 (page titles and big numbers only), Source Sans 3 400/600/700 (all body text), and JetBrains Mono 500 (section labels, ids, timestamps). The .woff2 files it references live alongside it at dist/fonts/ and are part of the published package; there is no runtime dependency on @fontsource/* — those packages are a devDependency this package's own build reads once, at build time, to get correctly subsetted, versioned font files instead of hand-rolling @font-face rules or vendoring binaries by hand (scripts/build-fonts.mjs, src/fonts.ts). Regenerate both fonts.css and dist/fonts/ with pnpm build after bumping a @fontsource/* version or changing FONT_MANIFEST. Every @font-face rule carries font-display: swap.

Only the latin subset of each family ships (not latin-ext or cyrillic) — this package's consumers are English-language operator tools, and the plain latin-<weight>.css file each @fontsource/* package ships is what scripts/build-fonts.mjs reads; add a subset to src/fonts.ts and the build step's copy logic together if a consumer ever needs more coverage.

Fonts and licensing

Pixelify Sans, Source Sans 3 and JetBrains Mono are each licensed under the SIL Open Font License 1.1, which requires the license text to accompany a redistributed copy of the font — and this package publishes its self-hosted files publicly to npm, so dist/fonts/ is exactly that. The build step copies each family's own license next to its .woff2 files as dist/fonts/LICENSE-<family-slug>.txt (pixelify-sans, source-sans-3, jetbrains-mono) and fails the build if a vendor package's LICENSE is missing.

data-mode is exactly three values (DataMode in TypeScript): "system" (everyone's default), "light" and "dark". system resolves with no JS and no flash — the pre-built CSS gives it the light values directly, then the dark values again under @media (prefers-color-scheme: dark), so the browser paints the right one on first render before any script runs. light/dark are explicit, OS-independent per-viewer overrides (e.g. from a stored preference, once available). A theme change is colour and type only — it never changes information, behaviour, status meaning or action availability.

Use the values and types from TypeScript

import { themes, themeCss, type DataMode, type ResolvedTheme } from '@growth-labs/tokens'

themes.pixel.light['color.status.danger'].value // '#c23b2a'
themeCss('pixel') // the same CSS the pre-built file ships

Mounting Pixel under your own selector

[data-theme="pixel"] is this package's own scope. A consumer whose data-theme attribute already means something else (a multi-brand app, say) mounts Pixel under its own selector with cssFor instead of the pre-built CSS — every declaration is a live reference to what resolveTheme() actually produced, never a hand-copied value, so there is nothing to keep in sync by hand and no drift test to write:

import { themes, cssFor } from '@growth-labs/tokens'

const css = cssFor(themes.pixel, {
  system: '[data-theme="acme"]',
  light: '[data-theme="acme"][data-scheme="light"]',
  dark: '[data-theme="acme"][data-scheme="dark"]',
})

Call this at your own build time (a small prebuild script, or a Vite plugin) and write the result to a .css file your app imports — cssFor is a pure function over already-resolved values, not a runtime dependency. See fulcrum-projects's adoption for a worked example: its own data-theme already selects between two brands, so it supplies its own selector shapes (no data-mode attribute at all) instead of the package's.

Token contract

The full contract (every token this package guarantees, in both modes) is CONTRACT in src/contract.ts. Groups:

| Group | CSS prefix | Role | |---|---|---| | color.surface.* | --gl-color-surface-* | Page, panel, nested/raised panel, overlay | | color.text.* | --gl-color-text-* | Primary, secondary, de-emphasized-but-legible tertiary, text-on-a-filled-action | | color.border.* | --gl-color-border-* | Default hairline, strong/structural edge, faint/disabled | | color.focus.* | --gl-color-focus-* | The visible-focus ring | | color.action.* | --gl-color-action-* | Primary action fill | | color.status.* | --gl-color-status-* | Info/success/danger/warning tone + tint pairs, solid success/attention/warning fills, and an advisory (agent-written-content) tone | | color.chart.* | --gl-color-chart-* | A 5-series categorical sequence, aliased to the status/action tones above — no new hues | | color.code.* | --gl-color-code-* | Code/inline-code surface, default code text, selection background, and a 5-role syntax set (keyword/string/number/function/comment) | | color.diff.* | --gl-color-diff-* | Added/removed/changed line text+background pairs, and the line-number gutter | | font.family.*, font.weight.* | --gl-font-* | Display (titles only), body, mono; four weights | | dimension.border.*, shadow.panel | --gl-dimension-*, --gl-shadow-* | The theme's 1px/2px rule weights and its hard shadow |

color.status.*, color.chart.*, color.code.* and color.diff.* are the full extent of what this package opinionates about state: a consumer's own state names (Cockpit's stale, unknown, disconnected, failed, waiting, decision-needed) are that consumer's CSS, aliasing onto these tokens — never redefined here.

Code and diff

Ruling 18 names code/diff explicitly ("the contract also covers dense surfaces, code/diff, charts... and focus on nested dark panels"), so both get pinned roles rather than being left for a consumer to compose ad hoc. The prototype defines no code/diff CSS at all (no .code/.diff/.hl-/.tok- classes anywhere in prototype.html), so every color.code.*/color.diff.* value is an alias onto an existing base/status tone — no new hex values — chosen so it passes a real contrast check against color.code.surface (color.surface.panel-raised, deliberately the nested-panel case) and reads as a defensible syntax role (see tokens/pixel.tokens.json's color.code group description for exactly which existing tones were excluded and why: color.status.info/color.status.success, though contract colors, fall under 4.5:1 against panel-raised specifically in light mode). There is no dedicated punctuation role — it reads as color.code.text, a common syntax-theme convention, once every other safe distinct hue was spent on the five roles that exist. Diff roles are named independently of color.status.* (color.diff.added-fg, not a direct color.status.success reference in a consumer's CSS) precisely so a future status-palette edit can't silently reskin diff rendering too, even though today's values are the same alias.

Extending to a second theme

Add tokens/<theme>.tokens.json in the same DTCG-subset shape (see the top-level $description in tokens/pixel.tokens.json for the exact rules: $value is the light baseline, $extensions["com.growthlabs.tokens.modes"] carries a non-light override, and a "{a.b.c}" string aliases another token). CONTRACT in src/contract.ts is the same list for every theme — a theme missing a contract token in either mode fails resolveTheme(), which the test suite exercises directly (__tests__/contract.test.ts).

A primitive/palette token layer (raw swatches that semantic tokens alias to) is deliberately not built yet: with one theme there is nothing to share it with. Add it at the second theme that needs shared primitives, not before (the estate's "extract at the second real use" rule).

Contrast

__tests__/contrast.test.ts computes real WCAG contrast ratios (src/contrast.ts) for every text/status/focus pairing this contract defines, across light, dark, and the nested-dark-panel case (color.surface.panel-raised in dark mode) — including the code/diff roles above, whose default surface (color.code.surface) is color.surface.panel-raised, so nested-dark-panel coverage for code comes for free.