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

react-design-tokens

v2.0.1

Published

An optimized and creative theming solution that generates CSS variables based on the tokens provided.

Downloads

431

Readme

react-design-tokens

An optimized theming solution that generates CSS custom properties from a typed design token map.

Installation

Requires react >= 16.8 and react-dom >= 16.8 as peer dependencies.

# npm
npm install react-design-tokens

# yarn
yarn add react-design-tokens

# pnpm
pnpm add react-design-tokens

Quick Start

// theming.ts
import { createTheming } from "react-design-tokens";

export const { VariantSelector, useTokens, useVariant, generateStylesheet } =
  createTheming({
    variants: {
      dark: {
        colors: {
          primary: { base: "#fff", hover: "#eee" },
          background: "#111",
        },
      },
      light: {
        colors: {
          primary: { base: "#000", hover: "#333" },
          background: "#fff",
        },
      },
    },
    common: {
      space: { sm: "4px", md: "8px", lg: "16px" },
      fontFamily: "Inter, sans-serif",
    },
  });
// App.tsx
import { VariantSelector } from "./theming.ts";

const App = () => (
  <VariantSelector variant="dark">
    <Layout />
  </VariantSelector>
);
// Button.tsx
import { useTokens } from "./theming.ts";

const Button = () => {
  const tokens = useTokens();
  return (
    <button style={{ color: `var(--${tokens.colors.primary.base})` }}>
      Click me
    </button>
  );
};

API

createTheming(tokens, config?)

declare const createTheming: <TVariants, TCommon>(
  tokens: { variants: TVariants; common: TCommon },
  config?: {
    cssVariableGenerator?: CSSVariableGenerator;
    logLevel?: LogLevel;
  },
) => Theming<TVariants, TCommon>;

The main entry point. Accepts your token map and returns a fully-typed theming client.

tokens

| Field | Type | Description | | ---------- | ----------------------------------------- | ---------------------------------- | | variants | Record<string, Record<string, unknown>> | One entry per theme variant. | | common | Record<string, unknown> | Tokens shared across all variants. |

Common tokens are shallow-merged on top of variant tokens ({ ...variantTokens, ...commonTokens }). Common tokens take precedence on key collisions — avoid overlapping keys.

config

| Option | Type | Default | Description | | ---------------------- | ---------------------- | ----------------------------- | -------------------------------------------------------------- | | cssVariableGenerator | CSSVariableGenerator | defaultCSSVariableGenerator | Custom function to control CSS variable name/value generation. | | logLevel | LogLevel | "warn" | Minimum log level for internal warnings. |


VariantSelector

A wrapper component that activates a variant for its subtree. Renders a DOM element with the variant's CSS custom properties injected as inline styles.

<VariantSelector variant="dark">
  <App />
</VariantSelector>

// Custom wrapper element
<VariantSelector variant="dark" as="section">
  <App />
</VariantSelector>

| Prop | Type | Default | Description | | ------------------------------ | ----------------------------- | ------- | ------------------------------------------------------------------------------------------------------------- | | variant | keyof TVariants | — | The variant to activate. | | as | keyof JSX.IntrinsicElements | "div" | The HTML element to render as the wrapper. | | children | React.ReactNode | — | Content of the component. | | disableCSSVariableGeneration | boolean | false | When true, CSS variables are not injected as inline styles. Useful when you control CSS variables manually. |


useTokens()

A React hook that returns the merged tokens for the active variant. Must be called inside a descendant of <VariantSelector>.

const MyComponent = () => {
  const tokens = useTokens();
  // tokens.colors.primary.base, tokens.space.sm, etc.
};

Throws in development if called outside a <VariantSelector>. Returns {} in production for graceful degradation.


useVariant()

A React hook that returns the currently active variant key. Must be called inside a descendant of <VariantSelector>.

const MyIcon = () => {
  const variant = useVariant(); // "dark" | "light"
  return <img src={variant === "dark" ? darkSrc : lightSrc} />;
};

generateCSSVariablesAsInlineStyle(variant, options?)

Generates CSS custom properties for a variant as a React inline style object ({ "--variable-name": "value" }). Returns null if the variant key is not found.

// Useful for SSR — apply initial variables on the html element
<html style={generateCSSVariablesAsInlineStyle("dark")} />

| Option | Type | Default | Description | | ------------------------------- | --------- | ------- | ----------------------------------- | | disableCommonTokensGeneration | boolean | false | Omit common tokens from the output. |


generateStylesheet(variant, options?)

Generates a CSS rule block string for a variant, suitable for a <style> tag, _document.tsx, or a static .css file. Returns null if the variant key is not found.

generateStylesheet("dark");
// ":root {\n  --colors-primary-base: #fff;\n  ...\n}"

generateStylesheet("dark", { selector: "[data-theme='dark']" });
// "[data-theme='dark'] {\n  --colors-primary-base: #fff;\n  ...\n}"

| Option | Type | Default | Description | | ------------------------------- | --------- | --------- | -------------------------------------- | | selector | string | ":root" | CSS selector to wrap the declarations. | | disableCommonTokensGeneration | boolean | false | Omit common tokens from the output. |


defaultCSSVariableGenerator

declare const defaultCSSVariableGenerator: CSSVariableGenerator;

The default CSS variable generator. Rules:

  • Values that are not string or number are skipped (returns null).
  • number values are converted to {value}px.
  • Variable names are derived from the dot-separated token path with the family key as prefix: colors.primary.base--colors-primary-base

You can pass a custom generator to createTheming() to override this behavior:

createTheming(tokens, {
  cssVariableGenerator: ({ tokenFamilyKey, tokenPath, tokenValue }) => {
    if (typeof tokenValue !== "string") return null;
    return {
      variableName: `my-prefix-${tokenFamilyKey}-${tokenPath.replace(/\./g, "-")}`,
      variableValue: tokenValue,
    };
  },
});

The generator receives a context object:

| Field | Type | Description | | ---------------- | --------- | ------------------------------------------------------------------------------------------ | | tokenFamilyKey | string | Root-level key of the token family (e.g. "colors"). | | tokenKey | string | Immediate key of the token (e.g. "base"). | | tokenPath | string | Dot-separated path from the family root, excluding the family key (e.g. "primary.base"). | | tokenValue | unknown | The raw token value. |


Types

/** Function that maps a token context to a CSS variable descriptor, or null to skip. */
type CSSVariableGenerator = (context: {
  tokenFamilyKey: string;
  tokenKey: string;
  tokenPath: string;
  tokenValue: unknown;
}) => { variableName: string; variableValue: string } | null;

/** The return type of a CSSVariableGenerator call. */
type GeneratedCSSVariable = ReturnType<CSSVariableGenerator>;

CSS Variables

Given the following token map with the default generator and the dark variant active:

const tokens = {
  variants: {
    dark: {
      colors: {
        primary: { base: "#fff", hover: "#eee" },
      },
    },
  },
  common: {
    space: { sm: "4px", md: "8px" },
  },
};

The generated CSS variables are:

--colors-primary-base: #fff;
--colors-primary-hover: #eee;
--space-sm: 4px;
--space-md: 8px;

SSR / Next.js

Use generateCSSVariablesAsInlineStyle or generateStylesheet to apply the initial theme on the server without a flash of unstyled content:

// app/layout.tsx (Next.js App Router)
import { generateCSSVariablesAsInlineStyle } from "./theming.ts";

export default function RootLayout({ children }) {
  return (
    <html style={generateCSSVariablesAsInlineStyle("dark")}>
      <body>{children}</body>
    </html>
  );
}

Or inject a <style> block:

import { generateStylesheet } from "./theming.ts";

export default function RootLayout({ children }) {
  return (
    <html>
      <head>
        <style
          dangerouslySetInnerHTML={{ __html: generateStylesheet("dark") ?? "" }}
        />
      </head>
      <body>{children}</body>
    </html>
  );
}

Nested Variants

VariantSelector components can be nested to apply different variants to different subtrees:

<VariantSelector variant="dark">
  <Header />
  <VariantSelector variant="light">
    <Sidebar />
  </VariantSelector>
  <Main />
</VariantSelector>

Contributing

Read the contributing guide to learn about the development process, how to propose bug fixes and improvements, and how to build and test your changes.

License

MIT