Skip to content
Alpha

Hololink UI is under active development. Components, APIs and these docs may change without notice.

Design tokens

Every colour, size, radius, shadow, duration and layer in Hololink UI is a CSS custom property. The source of truth is packages/ui/src/styles/settings/tokens.css. The tables on this page are generated from that file, so they always match what ships.

Tier Prefix Role Who may use it
Primitive --p-* Raw values with no meaning, such as --p-color-indigo-600. Only tokens.css, to define --s-*
Semantic --s-* Contextual roles that remap per theme, such as --s-color-bg-interactive. Components, stories, docs, your app

Primitives say what a value is. Semantic tokens say what it is for. A semantic token points at a primitive, and themed colours point at a different primitive in light and dark. That indirection is what lets you re-brand or support dark mode by changing the semantic layer only.

/* Primitive: a raw value */
--p-color-indigo-600: #4f46e5;
/* Semantic: a role, mapped per theme */
--s-color-bg-interactive: light-dark(var(--p-color-indigo-600), var(--p-color-indigo-400));
  1. Consume --s-* tokens, never --p-* and never literals such as #4f46e5, 16px or 150ms.
  2. If no semantic token covers your need, add one to tokens.css and map it to a primitive. Do not reach for a primitive.
  3. Per-component hooks are named --holo-<component>-<prop> and fall back to a semantic token: var(--holo-text-field-bg, var(--s-color-bg-surface)). Override hooks, not component internals.
  4. Theme by overriding --s-* on :root or any container. See Theming and dark mode.

Values show the light and dark branches of light-dark(). Swatches follow the live theme. See Colour for usage guidance.

TokenValuePreview
--s-color-bg-appLight #f8fafc
Dark #020617
--s-color-bg-surfaceLight #ffffff
Dark #0f172a
--s-color-bg-surface-hoverLight #f1f5f9
Dark #1e293b
--s-color-bg-interactiveLight #4f46e5
Dark #818cf8
--s-color-bg-interactive-hoverLight #4338ca
Dark #a5b4fc
--s-color-bg-inverseLight #0f172a
Dark #f1f5f9
--s-color-bg-backdropLight color-mix(in srgb, #0f172a 50%, transparent)
Dark color-mix(in srgb, #020617 70%, transparent)
--s-color-text-primaryLight #0f172a
Dark #f8fafc
--s-color-text-secondaryLight #475569
Dark #cbd5e1
--s-color-text-tertiaryLight #5d6b82
Dark #94a3b8
--s-color-text-on-interactiveLight #ffffff
Dark #020617
--s-color-text-inverseLight #f8fafc
Dark #0f172a
--s-color-text-linkLight #4f46e5
Dark #818cf8
--s-color-text-link-hoverLight #4338ca
Dark #a5b4fc
--s-color-border-subtleLight #e2e8f0
Dark #1e293b
--s-color-border-strongLight #cbd5e1
Dark #334155
--s-color-border-control#64748b
--s-color-border-interactiveLight #6366f1
Dark #818cf8
--s-color-status-successLight #047857
Dark #34d399
--s-color-status-success-bgLight #ecfdf5
Dark #022c22
--s-color-status-warningLight #b45309
Dark #fbbf24
--s-color-status-warning-bgLight #fffbeb
Dark #451a03
--s-color-status-dangerLight #b91c1c
Dark #f87171
--s-color-status-danger-bgLight #fef2f2
Dark #450a0a
--s-color-status-infoLight #1d4ed8
Dark #60a5fa
--s-color-status-info-bgLight #eff6ff
Dark #172554
--s-color-accent-glowcolor-mix(in srgb, #6366f1 40%, transparent)
--s-color-accent-gridcolor-mix(in srgb, #6366f1 8%, transparent)
--s-color-accent-grid-strongcolor-mix(in srgb, #6366f1 20%, transparent)

Colour previews use the live theme. Switch the site theme to see the dark values.

TokenValuePreview
--s-font-sans'Outfit', 'Inter', system-ui, -apple-system, sans-serifAa Bb 0123
--s-font-mono'JetBrains Mono', 'Fira Code', monospaceAa Bb 0123
--s-font-size-caption0.75remAa
--s-font-size-label0.875remAa
--s-font-size-body1remAa
--s-font-size-lead1.125remAa
--s-font-size-title1.25remAa
--s-font-size-headline1.5remAa
--s-font-size-display1.875remAa
TokenValuePreview
--s-space-2xs0.25rem
--s-space-xs0.5rem
--s-space-sm0.75rem
--s-space-md1rem
--s-space-lg1.5rem
--s-space-xl2rem
--s-space-inset1rem
--s-space-stack-sm0.5rem
--s-space-stack-md1rem
--s-space-stack-lg2rem
--s-space-inline-sm0.5rem
--s-space-inline-md1rem
TokenValuePreview
--s-radius-subtle0.25rem
--s-radius-interactive0.375rem
--s-radius-container0.75rem
--s-radius-pill9999px
TokenValuePreview
--s-shadow-depth-10 1px 2px 0 rgba(0, 0, 0, 0.05)
--s-shadow-depth-20 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)
--s-shadow-depth-30 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)
--s-shadow-depth-40 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)
--s-shadow-glass0 8px 32px 0 rgba(31, 38, 135, 0.07)

Hover a row to play the transition.

TokenValuePreview
--s-duration-fast150ms
--s-duration-normal250ms
--s-duration-slow350ms
TokenValuePreview
--s-easing-standardcubic-bezier(0.4, 0, 0.2, 1)
--s-easing-bouncecubic-bezier(0.34, 1.56, 0.64, 1)
TokenValuePreview
--s-transition-smooth250ms cubic-bezier(0.4, 0, 0.2, 1)
--s-transition-pop150ms cubic-bezier(0.34, 1.56, 0.64, 1)
TokenValuePreview
--s-z-index-dropdown100layer 100
--s-z-index-sticky200layer 200
--s-z-index-overlay300layer 300
--s-z-index-modal400layer 400
--s-z-index-popover500layer 500

Primitives are listed so you can map a value back to its source. Do not use them in components or application code.

Show primitive tokens
TokenValuePreview
--p-color-neutral-0#ffffff
--p-color-neutral-50#f8fafc
--p-color-neutral-100#f1f5f9
--p-color-neutral-200#e2e8f0
--p-color-neutral-300#cbd5e1
--p-color-neutral-400#94a3b8
--p-color-neutral-500#64748b
--p-color-neutral-550#5d6b82
--p-color-neutral-600#475569
--p-color-neutral-700#334155
--p-color-neutral-800#1e293b
--p-color-neutral-900#0f172a
--p-color-neutral-950#020617
TokenValuePreview
--p-color-indigo-50#eef2ff
--p-color-indigo-100#e0e7ff
--p-color-indigo-200#c7d2fe
--p-color-indigo-300#a5b4fc
--p-color-indigo-400#818cf8
--p-color-indigo-500#6366f1
--p-color-indigo-600#4f46e5
--p-color-indigo-700#4338ca
--p-color-indigo-800#3730a3
--p-color-indigo-900#312e81
--p-color-indigo-950#1e1b4b
TokenValuePreview
--p-color-green-50#ecfdf5
--p-color-green-400#34d399
--p-color-green-500#10b981
--p-color-green-700#047857
--p-color-green-950#022c22
TokenValuePreview
--p-color-amber-50#fffbeb
--p-color-amber-400#fbbf24
--p-color-amber-500#f59e0b
--p-color-amber-700#b45309
--p-color-amber-950#451a03
TokenValuePreview
--p-color-red-50#fef2f2
--p-color-red-400#f87171
--p-color-red-500#ef4444
--p-color-red-700#b91c1c
--p-color-red-950#450a0a
TokenValuePreview
--p-color-blue-50#eff6ff
--p-color-blue-400#60a5fa
--p-color-blue-500#3b82f6
--p-color-blue-700#1d4ed8
--p-color-blue-950#172554

--p-color-success, --p-color-warning, --p-color-danger and --p-color-info are kept so existing code does not break. They fail AA contrast as text. Use --s-color-status-* instead.

TokenValuePreview
--p-color-success#10b981
TokenValuePreview
--p-color-warning#f59e0b
TokenValuePreview
--p-color-danger#ef4444
TokenValuePreview
--p-color-info#3b82f6
TokenValuePreview
--p-font-family-sans'Outfit', 'Inter', system-ui, -apple-system, sans-serifAa Bb 0123
--p-font-family-mono'JetBrains Mono', 'Fira Code', monospaceAa Bb 0123
--p-font-size-xs0.75remAa
--p-font-size-sm0.875remAa
--p-font-size-base1remAa
--p-font-size-lg1.125remAa
--p-font-size-xl1.25remAa
--p-font-size-2xl1.5remAa
--p-font-size-3xl1.875remAa
--p-font-size-4xl2.25remAa
TokenValuePreview
--p-space-00
--p-space-10.25rem
--p-space-20.5rem
--p-space-30.75rem
--p-space-41rem
--p-space-51.25rem
--p-space-61.5rem
--p-space-82rem
--p-space-102.5rem
--p-space-123rem
--p-space-164rem
TokenValuePreview
--p-radius-none0
--p-radius-sm0.25rem
--p-radius-md0.375rem
--p-radius-lg0.5rem
--p-radius-xl0.75rem
--p-radius-2xl1rem
--p-radius-full9999px
TokenValuePreview
--p-shadow-sm0 1px 2px 0 rgba(0, 0, 0, 0.05)
--p-shadow-md0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)
--p-shadow-lg0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)
--p-shadow-xl0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)
--p-shadow-glass0 8px 32px 0 rgba(31, 38, 135, 0.07)
TokenValuePreview
--p-transition-duration-fast150ms
--p-transition-duration-normal250ms
--p-transition-duration-slow350ms
--p-transition-timing-easecubic-bezier(0.4, 0, 0.2, 1)
--p-transition-timing-bouncecubic-bezier(0.34, 1.56, 0.64, 1)
TokenValuePreview
--p-z-index-under-1layer -1
--p-z-index-normal1layer 1
--p-z-index-dropdown100layer 100
--p-z-index-sticky200layer 200
--p-z-index-overlay300layer 300
--p-z-index-modal400layer 400
--p-z-index-popover500layer 500