@beam-ui/design-tokens
v2.3.1
Published
A collection of design decisions and other artifacts for the Beam UI Design System
Readme
Beam UI Design Tokens
A centralized collection of design decisions and other artifacts for the Beam UI Design System.
Overview
Design tokens are the visual design atoms — specifically, they are named entities that store various design decisions. This package provides these tokens in multiple formats for consistent use across applications.
Installation
Option 1: npm/yarn
For applications with a build process:
npm install @beam-ui/design-tokens
# or
yarn add @beam-ui/design-tokensOption 2: CDN via UNPKG or jsDelivr (Zero Configuration)
For server-side rendered HTML, static sites, or environments where build process is not available.
The package is available via CDN with all token formats accessible directly - no build process needed! (Works with both UNPKG and jsDelivr.)
Loading CSS Variables:
<!-- Import all token layers (recommended) -->
<link rel="stylesheet" href="https://unpkg.com/@beam-ui/design-tokens@latest/build/globals/variables.css">
<link rel="stylesheet" href="https://unpkg.com/@beam-ui/design-tokens@latest/build/base/variables.css">
<link rel="stylesheet" href="https://unpkg.com/@beam-ui/design-tokens@latest/build/semantic/variables.css">
<!-- or using jsDelivr -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@beam-ui/design-tokens@latest/build/globals/variables.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@beam-ui/design-tokens@latest/build/base/variables.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@beam-ui/design-tokens@latest/build/semantic/variables.css">Loading JavaScript Tokens:
<script type="module">
import { colorGrayBlack, spacingMedium } from 'https://unpkg.com/@beam-ui/design-tokens@latest/build/base/tokens.es6.js';
// or
import { buttonPrimaryBackground } from 'https://cdn.jsdelivr.net/npm/@beam-ui/design-tokens@latest/build/semantic/tokens.es6.js';
</script>💡 Use Cases for CDN:
- Server-side templating (PHP, Ruby, Python, etc.)
- Static HTML sites without build tools
- Quick prototypes and demos
- CodePen/JSFiddle examples
- Documentation and tutorials
⚡ Performance Benefits:
- Zero configuration - no build process required
- Direct access to all token formats (CSS, JS, JSON)
- Selective loading - load only the token layers you need
- Minified and optimized by the CDN
⚠️ For Production: Pin to a specific version instead of using @latest:
<!-- CSS Variables with pinned version -->
<link rel="stylesheet" href="https://unpkg.com/@beam-ui/[email protected]/build/globals/variables.css">
<link rel="stylesheet" href="https://unpkg.com/@beam-ui/[email protected]/build/base/variables.css">
<link rel="stylesheet" href="https://unpkg.com/@beam-ui/[email protected]/build/semantic/variables.css">
<!-- JavaScript with pinned version -->
<script type="module">
import { colorGrayBlack } from 'https://unpkg.com/@beam-ui/[email protected]/build/base/tokens.es6.js';
// or
import { colorGrayBlack } from 'https://cdn.jsdelivr.net/npm/@beam-ui/[email protected]/build/base/tokens.es6.js';
</script>Available Output Formats
All tokens are available in three formats:
- CSS Variables (
variables.css) - CSS custom properties - JavaScript ES6 (
tokens.es6.js) - ES6 module exports - JSON (
tokens.json) - Nested JSON structure - Tailwind v4 theme (
build/tailwind/theme.css) - see Using with Tailwind CSS v4 - Tailwind theme manifest (
build/tailwind/theme.json) - see Tailwind theme manifest
Token Layers
Tokens are organized in three layers:
build/globals/- Global tokens (breakpoints, accessibility, etc.)build/base/- Default base tokens (colors, fonts, spacing, etc.)build/semantic/- Default semantic tokens (buttons, typography, etc.)
Brand-specific tokens can be found at build/{brand}/base/ and build/{brand}/semantic/ if custom brands exist.
Usage
Using CSS Variables
Important: Semantic Tokens Require Base and Global Tokens
Semantic CSS tokens reference base and global tokens using CSS custom properties (var()), which means you must import all token files in the correct order for semantic tokens to work correctly.
Recommended Import Order
/* Import in this order: */
@import '@beam-ui/design-tokens/build/globals/variables.css';
@import '@beam-ui/design-tokens/build/base/variables.css';
@import '@beam-ui/design-tokens/build/semantic/variables.css';Or in your HTML (with npm):
<link rel="stylesheet" href="node_modules/@beam-ui/design-tokens/build/globals/variables.css">
<link rel="stylesheet" href="node_modules/@beam-ui/design-tokens/build/base/variables.css">
<link rel="stylesheet" href="node_modules/@beam-ui/design-tokens/build/semantic/variables.css">Or in your HTML (with CDN):
<link rel="stylesheet" href="https://unpkg.com/@beam-ui/[email protected]/build/globals/variables.css">
<link rel="stylesheet" href="https://unpkg.com/@beam-ui/[email protected]/build/base/variables.css">
<link rel="stylesheet" href="https://unpkg.com/@beam-ui/[email protected]/build/semantic/variables.css">Why All Three Files Are Required
Tokens use var() references to maintain relationships across all layers:
/* 1. Global tokens define shared values */
:root {
--breakpoint-medium: 768px;
--a11y-min-touch-target: 40px;
}
/* 2. Base tokens define the actual brand values */
:root {
--color-gray-black: hsl(0, 0%, 0%);
--color-gray-white: hsl(0, 0%, 100%);
--color-transparent: hsla(0, 0%, 0%, 0);
--font-size-medium: 1.6rem;
}
/* 3. Semantic tokens reference base and global tokens */
:root {
--button-primary-background: var(--color-gray-black);
--button-primary-text: var(--color-gray-white);
--button-tertiary-border: var(--color-transparent);
--button-primary-font-size: var(--font-size-medium);
--button-size-sm-min-width: var(--a11y-min-touch-target);
}Benefits of This Approach
- Single source of truth - Update base token values and all semantic tokens automatically reflect the change
- Smaller file sizes - References are more efficient than duplicated values
- Runtime flexibility - Override base tokens to theme entire components
- Maintainability - Clear relationships between foundation and application layers
Using Only Base Tokens
If you only need base tokens (colors, spacing, fonts) without semantic tokens, you can import just the base and global files:
@import '@beam-ui/design-tokens/build/globals/variables.css';
@import '@beam-ui/design-tokens/build/base/variables.css';
.custom-button {
background-color: var(--color-gray-black);
padding: var(--spacing-medium);
font-size: var(--font-size-medium);
min-height: var(--a11y-min-touch-target);
}Note: Base tokens may reference global tokens (like accessibility values), so it's recommended to include globals even when not using semantic tokens.
Using JavaScript/TypeScript Tokens
JavaScript and JSON formats output resolved values, so semantic tokens can be used independently:
// Semantic tokens contain resolved values
import { buttonPrimaryBackground, buttonPrimaryText } from '@beam-ui/design-tokens/build/semantic/tokens.es6.js';
const button = {
backgroundColor: buttonPrimaryBackground, // "hsl(0, 0%, 0%)"
color: buttonPrimaryText // "hsl(0, 0%, 100%)"
};Importing Base Tokens
import { colorGrayBlack, fontSizeMedium, spacingLarge } from '@beam-ui/design-tokens/build/base/tokens.es6.js';
const styles = {
color: colorGrayBlack, // "hsl(0, 0%, 0%)"
fontSize: fontSizeMedium, // "1.6rem"
padding: spacingLarge // "2.4rem"
};Importing Global Tokens
import { breakpointMedium, a11yMinTouchTarget } from '@beam-ui/design-tokens/build/globals/tokens.es6.js';
const config = {
breakpoint: breakpointMedium, // "768px"
minTouchSize: a11yMinTouchTarget // "40px"
};Using JSON Tokens
JSON format provides a nested structure:
import tokens from '@beam-ui/design-tokens/build/semantic/tokens.json';
console.log(tokens.button.primary.background); // "hsl(0, 0%, 0%)"
console.log(tokens.color.background.primary); // "hsl(0, 0%, 100%)"Using with Tailwind CSS v4
This package ships a pre-built Tailwind v4 @theme file that exposes most
Beam tokens as Tailwind utilities — colors, spacing, typography, breakpoints,
and more. Requires tailwindcss@^4.0.0.
Import it from your app's main CSS entry alongside Tailwind itself:
/* app.css */
@import "tailwindcss";
@import "@beam-ui/design-tokens/tailwind";This import sets the global root font-size to 62.5% (10px, so 1rem =
10px) — required for Beam's rem-based tokens to resolve to their intended
pixel values. This is a side effect on html, not scoped to Beam's own
utilities: Tailwind's radius and container namespaces aren't reset by
this theme (see What gets exposed below), so their
built-in rem-based defaults (rounded-lg, max-w-7xl, etc.) are still
present but render smaller than Tailwind's docs describe — scaled to the
10px root instead of the browser's default 16px. If your app already sets
its own root font-size, importing this theme will override it.
That single import is self-contained — it does not pull in
build/globals/, build/base/, or build/semantic/variables.css. What it
leaves out falls into two groups:
- No Tailwind equivalent at all: the
a11y,button,focusRing, andinputnamespaces, meant for direct CSS consumption, not Tailwind utilities (see Using CSS Variables above). - Re-exposed under a different name: Beam's original long breakpoint
names (
--breakpoint-medium, etc. — the theme re-emits these as Tailwind's short--breakpoint-md) and the individual--typography-*variables (the theme re-emits these as@utility type-*composite classes, not raw custom properties).
If you need any of the raw CSS variables above — or just prefer referencing
a variable directly in your own CSS instead of via a Tailwind utility —
import build/globals/variables.css, build/base/variables.css, and/or
build/semantic/variables.css directly. semantic/variables.css is built
with token references intact (var(--color-gray-500), etc.), so if you use
it, also bring in base/variables.css (for color/spacing/etc. primitives)
and globals/variables.css (for a11y primitives semantic tokens
reference).
What gets exposed
| Beam token | Tailwind class |
| ------------------------ | ------------------------------------------------ |
| color.surface.* | bg-surface-*, text-surface-*, … |
| color.background.* | bg-background-primary, bg-background-secondary, … |
| color.text.* | text-text-primary, text-text-link, … |
| color.border.* | border-border-primary, border-border-focus, … |
| spacing.x-large | p-8, m-8, gap-8, … (numeric Tailwind keys) |
| font.size.large | text-lg |
| font.family.body | font-sans |
| font.family.display | font-display |
| border.radius.xx-small | rounded-sm |
| breakpoint.* | sm:, md:, lg:, xl: |
| typography.heading.100 | type-heading-100 |
The following Tailwind namespaces are fully reset before Beam tokens are
emitted, so consumers opt into Beam's design language rather than mixing with
Tailwind defaults: --breakpoint-*, --color-*, --font-*, --font-weight-*,
--text-*, --leading-*, --tracking-*, --spacing-*, --shadow-*.
--radius-* is not reset — Beam defines only one radius token
(border-radius-xx-small → rounded-sm), so Tailwind's other radius defaults
(rounded-lg, rounded-xl, etc.) remain available.
Resetting --font-* also clears Tailwind's --font-mono and --font-serif.
--font-sans is re-declared from font.family.body; beam-ui has no custom
mono or serif tokens, so --font-mono and --font-serif are restored to
Tailwind's own system font fallbacks rather than left unavailable.
Brand support
The Tailwind theme is currently brand-agnostic — it is built from the
default globals + base + semantic tokens only. Brand-specific overrides
under build/{brand}/ are emitted as CSS variable files but do not yet
produce per-brand Tailwind themes. If you need brand-scoped Tailwind output,
import the brand's variables.css files after @beam-ui/design-tokens/tailwind
or open an issue to request first-class support.
Tailwind theme manifest
Alongside theme.css, this package also emits build/tailwind/theme.json —
a machine-readable manifest of the Tailwind namespaces, keys, and @utility
names theme.css declares as class-matchable utilities. It exists for tools
that need to know Beam's Tailwind naming but can't read a Tailwind config
directly, like a tailwind-merge
class-conflict config: tailwind-merge is a standalone string matcher, so it
needs an explicit list of Beam's namespaces and keys rather than discovering
them from CSS.
The manifest deliberately excludes breakpoint — Beam's breakpoints drive
Tailwind responsive variants (sm:, md:, lg:, xl:, see
What gets exposed above), not a class-conflict
namespace a tool like tailwind-merge needs to resolve.
// Node ESM requires the JSON import attribute (Node ≥ 20.10); a bundler-based
// consumer (webpack, esbuild, Vite, ...) can drop it and use a plain import.
import manifest from '@beam-ui/design-tokens/tailwind/theme.json' with { type: 'json' };
manifest.namespaces.spacing;
// ["1", "2", "4", "6", "8", "10", "12"]
manifest.utilities;
// ["type-display-100", "type-heading-100", ...]
manifest.nonUtilityNamespaces;
// ["border", "default"]
manifest.resetNamespaces;
// ["color", "font", "font-weight", "text", "leading", "tracking", "spacing", "shadow"]Shape:
namespaces— an object mapping each Tailwind theme namespacetheme.cssdeclares (excludingbreakpoint, see above) to its list of keys (e.g.namespaces.text→["xs", "sm", ...]). A namespace whose bare form is itself a valid utility (e.g. theshadowclass from--shadow, not justshadow-sm) includes an empty-string key.utilities— every@utilitynametheme.cssdeclares (thetype-*typography composites).nonUtilityNamespaces— namespaces present innamespacesthat are declared as CSS custom properties but don't correspond to a Tailwind utility class (currentlyborderanddefault— see What gets exposed above, which has no row for either).resetNamespaces— namespacesnamespaceslists that Beam fully resets (--{ns}-*: initial;) before emitting its own values, so their key list is exhaustive. A utility-bearing namespace present innamespacesbut absent fromresetNamespaces— currently justradius— is only partially covered: Tailwind's own default keys (e.g.rounded-lg,rounded-xl,rounded-full) are still live alongside whatever Beam adds, so atailwind-mergeconfig built fromnamespaces.radiusalone would under-cover that group.borderanddefaultare also absent fromresetNamespaces, but for an unrelated reason: they're non-utility namespaces (seenonUtilityNamespacesabove), not partially-reset ones, so the exhaustive-vs-partial distinction this field draws doesn't apply to them at all.
The manifest is generated from theme.css's own rendered output, so it can't
drift out of sync with it — this package's test suite asserts the two agree
on every namespace, key, and utility name. It deliberately does not ship
a ready-made tailwind-merge (or similar) config: Beam owns the Tailwind
naming, and each consumer owns its own opinion about how classes should
conflict.
npm vs CDN: When to Use Each
| Method | Best For | Setup | Performance | |--------|----------|-------|-------------| | npm + Bundler | Apps with build tools (React, Vue, etc.) | Bundler handles imports | Smaller final bundle (tree-shaking) | | CDN | Server-side templates, static sites | Zero config - direct file loading | No build process needed |
Token Reference
Global Tokens
Breakpoints
breakpoint-small,breakpoint-medium,breakpoint-large,breakpoint-x-large
Accessibility
a11y-min-touch-target- Minimum touch target size for interactive elements
Base Tokens
Colors
- Brand colors:
color-tatari-red,color-tatari-blue, etc. - Gray scale:
color-gray-black,color-gray-800throughcolor-gray-50,color-gray-white - Color palettes:
color-red-*,color-blue-*,color-green-*, etc. (100-700 scales) - Special:
color-transparent,color-overlay-dark,color-overlay-light
Typography
- Font families:
font-family-inter,font-family-favorit,font-family-body,font-family-display - Font weights:
font-weight-normal(400),font-weight-medium(500) - Font sizes:
font-size-x-smallthroughfont-size-xxxx-large - Line heights:
font-line-height-tightthroughfont-line-height-loose - Letter spacing:
font-letter-spacing-x-smallthroughfont-letter-spacing-x-large
Spacing
spacing-x-smallthroughspacing-xxx-large
Borders
- Border radius:
border-radius-xx-small - Border width:
border-width-thin,border-width-medium
Shadows
shadow-50throughshadow-600— Subtle ambient shadows for cards, popovers, and surface depth (uniform black at 6% alpha).shadow-50uses a sub-pixel (0.5px) blur for a "barely-there" hint and may render inconsistently on low-DPR displays — chooseshadow-100if a guaranteed-visible step is required.
Elevation
elevation-100throughelevation-300— Stronger composite shadows for raised surfaces such as modals, drawers, and floating panels (graduated alpha for stacked depth)
Shadow & Elevation Usage Notes
Shadow and elevation tokens are decorative, not boundary-forming. Their alpha values (0.04–0.14) sit well below the WCAG 1.4.11 (Non-text Contrast) 3:1 threshold. If a surface's existence as an interactive element must be perceivable (form fields, focusable cards, popovers that overlap critical content), pair the shadow with an explicit border or background contrast — don't rely on the shadow alone.
box-shadow is stripped in Windows High Contrast Mode (forced-colors: active). Surfaces whose boundary depends on shadow lose all visual separation in that mode. Pair shadow usage with a transparent border that becomes a system color under forced-colors:
.card {
background-color: var(--color-surface-primary);
box-shadow: var(--shadow-200);
border: 0.1rem solid transparent;
}
@media (forced-colors: active) {
.card {
border-color: CanvasText;
}
}
.modal {
background-color: var(--color-surface-primary);
box-shadow: var(--elevation-300);
border: 0.1rem solid transparent;
}
@media (forced-colors: active) {
.modal {
border-color: CanvasText;
}
}Semantic Tokens
Button Tokens
- Variants:
button-primary-*,button-secondary-*,button-tertiary-* - Danger states:
button-danger-primary-*,button-danger-secondary-* - States:
-background,-background-hover,-background-active,-background-disabled - Text:
-text,-text-hover,-text-active,-text-disabled - Border:
-border,-border-hover,-border-active,-border-disabled - Sizes:
button-size-sm-*,button-size-md-*,button-size-lg-*
Input Tokens
- Dimensions:
input-height,input-padding-inline,input-border-radius,input-border-width,input-border-width-focus - Typography:
input-font-size,input-line-height - Transition:
input-transition - Background:
input-background,-hover,-error,-warning,-success,-focus,-readonly,-disabled - Border (color):
input-border,-hover,-error,-warning,-success,-focus,-readonly,-disabled - Text:
input-text,input-text-placeholder,input-text-disabled - Icon:
input-icon-size,input-icon-color,input-icon-color-disabled,input-icon-gap - Label:
input-label-font-size,input-label-color,input-label-gap - Message:
input-message-font-size,input-message-gap,input-message-color-default,-error,-warning,-success
Color Tokens
- Background:
color-background-primary,color-background-secondary, etc. - Surface:
color-surface-primary,color-surface-hover, etc. - Border:
color-border-primary,color-border-focus,color-border-readonly, etc. - Text:
color-text-primary,color-text-link, etc. - Icon:
color-icon-primary,color-icon-interactive, etc. - Interactive states:
color-interactive-primary-default, etc. - Status colors:
color-status-success-base,color-status-error-base, etc. - Brand colors:
color-brand-primary-base,color-brand-secondary-base, etc.
Typography Tokens
- Display:
typography-display-100-*throughtypography-display-500-* - Headings:
typography-heading-100-*throughtypography-heading-500-* - Body text:
typography-body-large-*,typography-body-base-*,typography-body-small-*(each withdefaultandmediumvariants) - Label:
typography-label-base-* - Caption:
typography-caption-* - Overline:
typography-overline-* - Properties:
-font-family,-font-weight,-font-size,-line-height,-letter-spacing,-color,-inverse
Focus Ring Tokens
focus-ring-width- Width of the focus ring outlinefocus-ring-offset- Distance between element and focus ringfocus-ring-color- Color of the focus ringfocus-ring-transition- Animation for focus ring appearance
Examples
Using Focus Ring Tokens for Accessibility (CSS)
/* Import all required token files */
@import '@beam-ui/design-tokens/build/globals/variables.css';
@import '@beam-ui/design-tokens/build/base/variables.css';
@import '@beam-ui/design-tokens/build/semantic/variables.css';
.interactive-element {
/* Remove default browser focus outline */
outline: none;
}
.interactive-element:focus-visible {
/* Apply design system focus ring */
outline: var(--focus-ring-width) solid var(--focus-ring-color);
outline-offset: var(--focus-ring-offset);
@media (prefers-reduced-motion: no-preference) {
transition: var(--focus-ring-transition);
}
}Complete Button Component (CSS)
/* Import all required token files */
@import '@beam-ui/design-tokens/build/globals/variables.css';
@import '@beam-ui/design-tokens/build/base/variables.css';
@import '@beam-ui/design-tokens/build/semantic/variables.css';
.button-primary {
background-color: var(--button-primary-background);
color: var(--button-primary-text);
border: var(--button-primary-border-width) solid var(--button-primary-border);
border-radius: var(--button-primary-border-radius);
font-size: var(--button-primary-font-size);
line-height: var(--button-primary-line-height);
padding-inline: var(--button-size-md-padding-inline);
padding-block: var(--button-size-md-padding-block);
min-width: var(--button-size-md-min-width);
}
.button-primary:hover {
background-color: var(--button-primary-background-hover);
color: var(--button-primary-text-hover);
border-color: var(--button-primary-border-hover);
}React Component with TypeScript
import {
buttonPrimaryBackground,
buttonPrimaryText,
buttonPrimaryBorderRadius,
buttonSizeMdPaddingInline,
buttonSizeMdPaddingBlock
} from '@beam-ui/design-tokens/build/semantic/tokens.es6.js';
interface ButtonProps {
children: React.ReactNode;
}
export const Button: React.FC<ButtonProps> = ({ children }) => {
return (
<button
style={{
backgroundColor: buttonPrimaryBackground,
color: buttonPrimaryText,
borderRadius: buttonPrimaryBorderRadius,
paddingInline: buttonSizeMdPaddingInline,
paddingBlock: buttonSizeMdPaddingBlock
}}
>
{children}
</button>
);
};License
MIT License - see LICENSE file for details
