RamosLabs DS

Foundations / Tokens

Every design decision, named once.

A token is the smallest unit of the language: one color, one step of space, one shadow, authored as data and published to CSS and TypeScript from a single source. This is the canonical list of all 213, and the two-tier system that generates them. Click any token to copy its var(...) reference.

213
Total Tokens
2
Tiers
8
Radius Steps
3
Elevation Shadows

Tokens as a Contract

Every token is authored as data, not CSS, in the W3C Design Tokens Community Group format: a JSON object with a reserved $value and a $type like color or dimension. One authored decision publishes to CSS, TypeScript, and native from the same source. The JSON is the contract, and everything downstream honors it. It runs in two tiers.

Tier 1
Primitive

The raw palette. Eight color ramps of eleven shades each, plus pure white and black. These carry a value and nothing else, no role, no meaning. Product code rarely touches this tier directly. It exists so the semantic tier has something concrete to point at. Naming is descriptive: --color-indigo-600.

Tier 2
Semantic

The layer you build with. Each token names a role, not a hue, and aliases a primitive: --color-primary, --color-text-body, --color-border. This indirection is what makes the system themeable. Change one alias, and every consumer moves with it. Naming is intentional: role first, variant second.

Style Dictionary reads that JSON, resolves the aliases, and formats each target. The CSS output is a flat block of custom properties on :root, a parallel TypeScript output exposes the same values as typed constants. Both carry a do-not-edit banner: they are build output, not source.

Source
JSON tokens

Authored by hand in DTCG format under packages/tokens/src/tokens/. One file per category, each token a $value plus a $type.

Build
Style Dictionary

Resolves aliases, applies transforms, and formats each platform target. Run once, every output stays in lockstep.

Generated
CSS and TS

dist/tokens.css as :root custom properties, dist/tokens.ts as typed constants. Do not edit, they are regenerated.

Tier 1: Primitive Palette

The raw material. These ramps are Tailwind CSS's open-source (MIT) default palette, adopted hex-for-hex as the primitive layer; what this system owns sits on top, the mono-indigo constraint and the semantic mapping. Indigo is the brand ramp and the single action accent of the whole system. Slate carries text, surfaces, and borders. The four status ramps, emerald and green for success, amber for warning, red for error, blue for info, feed the feedback tokens. Violet backs the secondary role, a decorative accent only, never for action. Click any shade to copy its variable.

indigo--color-indigo-50 … 950
slate--color-slate-50 … 950
emerald--color-emerald-50 … 950
green--color-green-50 … 950
amber--color-amber-50 … 950
red--color-red-50 … 950
blue--color-blue-50 … 950
violet--color-violet-50 … 950
PreviewTokenValue
--color-white#ffffff
--color-black#000000

Tier 2: Semantic Color

The layer product code consumes. Each token names a role and aliases a primitive. Build with these, never with raw palette shades, so a theme change stays a one-line edit at the alias.

Brand

PreviewTokenValue
--color-primary#4f46e5
indigo 600, the single accent
--color-primary-light#6366f1
indigo 500
--color-primary-dark#4338ca
indigo 700
--color-primary-surface#eef2ff
indigo 50, tinted fill
--color-secondary#8b5cf6
violet 500
--color-secondary-light#a78bfa
violet 400
--color-secondary-dark#7c3aed
violet 600
--color-secondary-surface#f5f3ff
violet 50, tinted fill

Text

PreviewTokenValue
--color-text-heading#0f172a
slate 900, headings
--color-text-strong#1e293b
slate 800, emphasis
--color-text-secondary#475569
slate 600, supporting
--color-text-body#64748b
slate 500, body copy
--color-text-muted#64748b
slate 500, muted
--color-text-disabled#cbd5e1
slate 300, disabled

Surface and Border

PreviewTokenValue
--color-surface#ffffff
cards, panels
--color-surface-secondary#f8fafc
slate 50, sunken fill
--color-surface-hover#f1f5f9
slate 100, hover fill
--color-background#f8fafc
slate 50, page canvas
--color-border#e6e8eb
default divider
--color-border-light#e2e8f0
slate 200, soft divider
--color-border-subtle#f1f5f9
slate 100, hairline
--color-focus#4f46e5
indigo 600, focus ring
Borders are dividers, not control outlines
Rule: use --color-border and --color-border-light only to separate regions, dividers, table rows, card edges. Why: both sit near 1.2:1 against the surface, below the 3:1 floor WCAG 1.4.11 requires for the boundary of an interactive control. For the visible edge of an input, select, or checkbox, reach for a token that clears 3:1, for example --color-text-muted at #64748b, which is 4.55:1 on white. Never let a subtle border be the only thing marking a control's bounds.

Feedback

PreviewTokenValue
--color-success#10b981
emerald 500
--color-success-strong#059669
emerald 600, AA fill for a white glyph
--color-success-surface#f0fdf4
green 50, fill
--color-success-border#bbf7d0
green 200
--color-success-text#166534
green 800, on-surface text
--color-warning#f59e0b
amber 500
--color-warning-surface#fffbeb
amber 50, fill
--color-warning-border#fde68a
amber 200
--color-warning-text#78350f
amber 900, on-surface text
--color-error#ef4444
red 500
--color-error-strong#dc2626
red 600, AA fill for white text
--color-error-surface#fef2f2
red 50, fill
--color-error-border#fecaca
red 200
--color-error-text#991b1b
red 800, on-surface text
--color-info#3b82f6
blue 500
--color-info-surface#eff6ff
blue 50, fill
--color-info-border#bfdbfe
blue 200
--color-info-text#1e40af
blue 800, on-surface text

Spacing Scale

A single scale for margin, padding, and gap. One --space-* step in, one step out, so rhythm stays consistent across every component.

PreviewTokenValue
--space-00
--space-10.25rem (4px)
--space-20.5rem (8px)
--space-30.75rem (12px)
--space-41rem (16px)
--space-51.25rem (20px)
--space-61.5rem (24px)
--space-82rem (32px)
--space-102.5rem (40px)
--space-123rem (48px)
--space-164rem (64px)
--space-205rem (80px)
--space-246rem (96px)
--space-328rem (128px)

Border Radius

Eight steps. sm at 6px is the signature control radius. pill is the fully rounded accent, for chips, tags, and toggles, never for wide buttons or cards.

PreviewTokenValue
--radius-none0
--radius-xs0.25rem (4px)
--radius-sm0.375rem (6px)
--radius-md0.5rem (8px)
--radius-lg0.75rem (12px)
--radius-xl1rem (16px)
--radius-2xl1.25rem (20px)
--radius-pill9999px

State Layers

Interaction feedback is opacity, not elevation. Each token is the opacity of an indigo overlay painted on a control for hover, focus, press, and drag. Numbers only, so the same layer works on any surface color.

PreviewTokenValueRole
--state-hover0.08Hover on pointer devices, gate with @media (hover: hover)
--state-focus0.1Focus-visible, the keyboard state
--state-pressed0.1Active press, primary feedback on touch
--state-dragged0.16While dragging

Shadow and Elevation

Three elevation levels plus a focus ring. Each level is two soft, indigo-tinted layers rather than one hard black drop. Shadow means height, never state. See Foundations / Shadows for the full rationale.

PreviewTokenValue
--shadow-sm
Raised. Buttons and resting cards.
0 1px 2px 0 rgba(79, 70, 229, .06), 0 1px 3px 0 rgba(15, 23, 42, .04)
--shadow-md
Overlay. Dropdowns, popovers, menus.
0 2px 4px -1px rgba(79, 70, 229, .06), 0 8px 16px -4px rgba(79, 70, 229, .10)
--shadow-lg
Floating. Modals, sheets. The ceiling.
0 4px 8px -2px rgba(79, 70, 229, .06), 0 16px 32px -8px rgba(79, 70, 229, .12)
--shadow-focus
Focus ring. Pairs with :focus-visible.
0 0 0 2px #ffffff, 0 0 0 4px #4f46e5

Typography

Three families, eight weights, a ten-step size scale, and the line-height and letter-spacing tokens that pair with them. Rubik carries UI and body, Red Hat Display carries headings.

Families

TokenValue
--font-family-sansRubik, system-ui, sans-serif
--font-family-display'Red Hat Display', system-ui, sans-serif
--font-family-altRoboto, system-ui, sans-serif

Weights

SampleTokenValue
Ag--font-weight-thin100
Ag--font-weight-extralight200
Ag--font-weight-light300
Ag--font-weight-normal400
Ag--font-weight-medium500
Ag--font-weight-semibold600
Ag--font-weight-bold700
Ag--font-weight-extrabold800

Line Height

TokenValueRole
--leading-none1Display text
--leading-tight1.1Headlines
--leading-snug1.25Subheadings
--leading-normal1.5Body text
--leading-relaxed1.625Long-form

Sizes

TokenValue
--font-size-xs0.75rem (12px)
--font-size-sm0.875rem (14px)
--font-size-base1rem (16px)
--font-size-lg1.125rem (18px)
--font-size-xl1.25rem (20px)
--font-size-2xl1.5rem (24px)
--font-size-3xl1.875rem (30px)
--font-size-4xl2.25rem (36px)
--font-size-5xl3rem (48px)
--font-size-6xl3.75rem (60px)

Letter Spacing

TokenValueRole
--tracking-tighter-0.05emDisplay text
--tracking-tight-0.025emHeadlines
--tracking-normal0emBody text
--tracking-wide0.025emUppercase labels
--tracking-wider0.05emSmall caps

Motion

Three durations and five easing curves. Pair a short duration with an ease-out for enters, an ease-in for exits.

TokenValueRole
--duration-fast150msButtons, toggles
--duration-normal200msCards, panels
--duration-slow300msModals, reveals
TokenValue
--easing-linearcubic-bezier(0, 0, 1, 1)
--easing-incubic-bezier(0.4, 0, 1, 1)
--easing-outcubic-bezier(0, 0, 0.2, 1)
--easing-in-outcubic-bezier(0.4, 0, 0.2, 1)
--easing-springcubic-bezier(0.34, 1.56, 0.64, 1)

Z-Index Scale

A stepped stacking order. Use the token, never a raw integer, so overlays never fight.

TokenValueRole
--z-dropdown100Dropdown menus
--z-sticky200Sticky headers
--z-fixed300Fixed navbars
--z-fab400Floating action buttons
--z-modal-backdrop500Modal overlays
--z-modal600Modal content
--z-popover700Popovers
--z-tooltip800Tooltips
--z-toast900Toast notifications

Breakpoints

Minimum widths for the responsive scale. See Foundations / Responsive for usage.

TokenValue
--breakpoint-sm576px
--breakpoint-md769px
--breakpoint-lg992px
--breakpoint-xl1200px
--breakpoint-2xl1366px

Taxonomy Rules

Three rules keep the system coherent: how to consume a token, how to name a new one, and how a change reaches the screen.

How to consume a token

Reference the variable, never the literal. Reach for the semantic tier first, because it carries the meaning and stays stable across themes. Drop to a primitive only when no semantic token fits, and if you find yourself wanting a raw hex, that is the signal a semantic token is missing, not that you should hardcode.

CSS
/* Yes: reference the semantic token */
.card {
    background: var(--color-surface);
    color: var(--color-text-body);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

/* No: a hardcoded value drifts from the system on the next theme change */
.card {
    background: #ffffff;
    border-radius: 12px;
}

How to name a new token

Pick the tier. Is it a raw value with no role? It belongs in primitive, named by description, for example a new palette shade. Does it carry meaning? It belongs in semantic, named by role.
Name a semantic token role first, variant second: category, role, variant. So color, text, secondary becomes --color-text-secondary. Never encode the hue in the name.
Alias, do not copy. A semantic token points at a primitive with {color.slate.600}, so the value has one home. If two tokens share a value, both alias the same primitive.
Add a $description when the role is not obvious from the name. It becomes the comment in the generated CSS and the note in this reference.

How a change propagates

A change starts in the JSON and ends on the screen without a single manual edit downstream. Edit the $value in packages/tokens/src/tokens/, run the Style Dictionary build, and the generated tokens.css and tokens.ts update together. Because every consumer references the variable, the new value reaches every product surface at once. Never edit the generated files: they carry a do-not-edit banner and the next build overwrites them.

One source, many outputs
The JSON is the only file a person edits. dist/tokens.css, dist/tokens.ts, and dist/tokens.json are all build output. If a value looks wrong on screen, fix it in the source token and rebuild, never in the CSS.
Recommended
  • Consume var(--token) references, and prefer the semantic tier.
  • Author new tokens in the JSON source, then rebuild.
  • Name semantic tokens by role, category first, hue never.
  • Alias a primitive instead of repeating a hex.
  • Add a $description for any non-obvious role.
Avoid
  • Hardcode a hex, px, or raw integer that a token already covers.
  • Edit dist/tokens.css or dist/tokens.ts by hand.
  • Reach for a primitive when a semantic token fits.
  • Encode a color name into a semantic token.
  • Duplicate a value across tokens instead of aliasing.

Sources

  • Design Tokens Community Group, format specification. The open standard, developed under the W3C, that defines a token as a JSON object with a reserved $value and $type, and the alias syntax the semantic tier relies on. design-tokens.org and tr.designtokens.org/format
  • Style Dictionary. The build tool that reads the token source, resolves aliases, applies transforms, and formats the CSS and TypeScript outputs this system ships. styledictionary.com
  • Salesforce, primitive and semantic token tiers. The two-tier model, raw primitive values referenced by role-named semantic aliases, popularized for design systems at scale.
  • Every token name, value, and description in this page is quoted from this system's source JSON and generated CSS. SPA The elevation ceiling and the pill-as-accent-only rule are house rules specific to this system.
Copied!