Agent-consumable brand guide

VLLNT UI Design Guide

The canonical rules for brand, tokens, layout, motion, accessibility, and component composition across the library.

DESIGN.md

Single source of truth for VLLNT UI's brand and design conventions. Humans read this file. Agents read it too — every UI suggestion must follow it.

This is the canonical brand & design guideline for the library. The full machine-readable token set lives in packages/design/tokens.json, is documented in packages/design/README.md, and is mirrored publicly at /r/design.json. The site rendering at /design reads this file directly.


1. Brand

AttributeValue
NameVLLNT UI (always two words, both capitalised)
VoiceDirect. No marketing fluff. Short sentences.
MissionAgent-first React components — copy-paste, you own them.
ToneConfident, technical, honest about tradeoffs.

Voice rules

  • Sentence case for headings, button labels, tooltips. Title Case only for proper nouns.
  • Avoid superlatives ("the best", "blazingly fast"). State facts.
  • Avoid em-dash chains. One per sentence max.
  • Use (ellipsis glyph), not ....
  • No emoji in shipped UI. Lucide icons handle anything visual.

Banned phrases

  • "Click here"
  • "Submit" as a button label (use the verb of the action)
  • "Loading…" without a context noun ("Loading components…")
  • "Sign up to learn more"

VLLNT UI set in the system font stack at the brand weight. There is no standalone wordmark file; the type itself is the mark.

Clear space — at minimum, height of the cap-height of the logotype. Min size — 14px equivalent. Below that, omit "UI" and show only "VLLNT". Misuse — never stretch, recolor, italicise, or add a tagline beneath.


3. Color

Tokens live as CSS variables in packages/ui/themes/default.css. Components always consume tokens — never raw hex. The token set is versioned with the library.

Machine clients use packages/design/tokens.json. The JSON schema is documented in packages/design/tokens.schema.json and groups tokens by color, typography, spacing, radius, elevation, motion, and iconography.

Semantic tokens (consumer-facing)

TokenLight roleDark role
--backgroundSurfaceSurface
--foregroundPrimary textPrimary text
--mutedSubtle surfaceSubtle surface
--muted-foregroundSecondary textSecondary text
--borderHairline dividerHairline divider
--ringFocus ringFocus ring
--accent / --accent-foregroundActive / hover surfaceSame
--destructive / --destructive-foregroundDanger surface / textSame

Anti-patterns

  • Never use bg-black / text-white / bg-white. Use bg-background / bg-foreground / text-foreground so dark mode works.
  • Never use bg-gray-500 / Tailwind palette literals. Pick a semantic token.
  • Pure black (#000) is banned for backgrounds — use --background.

Contrast

WCAG AA minimum. Body text against any surface ≥ 4.5:1, large text ≥ 3:1, non-text UI ≥ 3:1. The default theme passes; new themes must verify before merging.


4. Typography

TokenSizeWeightLine height
Display (H1)3rem (48px)600 (semibold)1.1
H22rem (32px)6001.2
H31.5rem (24px)6001.25
H41.25rem (20px)6001.3
Body large1.125rem (18px)4001.6
Body1rem (16px)4001.6
Body small0.875rem (14px)4001.5
Caption0.75rem (12px)5001.4
Codeinherit400 mono1.5

Rules

  • Headings use font-semibold (600), never font-bold (700+) at display sizes — letter shapes crush.
  • Code uses the system mono stack via font-mono.
  • Tabular numerals for data tables, charts, transactions: font-variant-numeric: tabular-nums.

5. Spacing

4-pt scale. Tailwind classes map 1:1.

TokenValueUse
space-14pxIcon padding
space-28pxTight stack, inline gap
space-312pxComfortable inline gap
space-416pxDefault block stack
space-624pxSection break
space-832pxMajor section
space-1248pxPage section
space-1664pxHero / landing block

Rules

  • Stay on the scale. Never gap-[7px] etc.
  • One axis at a time on flex children — use gap-y-N or gap-x-N, not gap-N when only one axis is needed.

6. Radius

TokenValue
radius-none0
radius-sm4px
radius-md8px (default)
radius-lg12px
radius-full9999px

Cards, popovers, dialogs use radius-md. Pills, avatars use radius-full. Long surfaces (panels, sheets) use radius-lg.


7. Elevation

Use sparingly. Most components are flat with border + bg-background.

TokenValue
shadow-nonenone
shadow-sm0 1px 2px rgba(0,0,0,0.05)
shadow-md0 4px 6px -1px rgba(0,0,0,0.1)
shadow-lg0 10px 15px -3px rgba(0,0,0,0.1) (popovers, dialogs)

No coloured shadows. No multi-layered glow effects.


8. Motion

Principles

  1. Purposeful — every animation must explain a state change. No decoration.
  2. Fast — under 200ms unless the motion communicates distance or volume.
  3. Subtle — translate < 8px, scale ±2%. No bounces (spring easings strip fidelity at small distances).
TokenDurationEasingUse
duration-fast100msease-outMicro-interactions (button press)
duration-base200msease-outOpen / close, hover, focus
duration-slow300msease-in-outLayout shifts, modal entry

prefers-reduced-motion — when reduce, durations collapse to 1ms or motion is skipped entirely.

Banned

  • Bounce easings (cubic-bezier(0.68, -0.55, 0.265, 1.55)).
  • Auto-playing entrance animations on initial page load (jarring).
  • animation: spin on anything except a true loading spinner.

9. Iconography

  • Library: lucide-react (only). Match its line-art aesthetic.
  • Default size: 16px (h-4 w-4).
  • Stroke: 2px (lucide default).
  • Color: inherits currentColor. Don't hardcode.
  • Spacing: 8px (gap-2) between icon and adjacent text.

10. Component patterns

UsePattern
Inline actionButton
Single binary choiceSwitch
One of NSelect (≤ 8 options) or Combobox (> 8 / searchable)
Many of NMultiSelect
Free textInput (single line) or Textarea
ConfirmationAlertDialog (destructive) or Dialog (informational)
Side panelSheet
Hover helpTooltip (≤ 80 chars)
Stepper / wizardStepper + MultiStepForm
Tabular dataDataTable
Hierarchical dataTreeView
Status chipBadge
Notification (transient)Toast
Notification (persistent)Banner
Empty stateEmptyState

Anti-patterns

  • <div onClick> — always use Button for click semantics.
  • Tooltips on disabled buttons — wrap in a <span> with aria-disabled instead, since browsers swallow events on disabled elements.
  • Modal-on-modal — restructure the flow.
  • Polymorphic children + items props on the same component — pick one.

11. Accessibility (WCAG AA minimum)

  • Every interactive element is keyboard-reachable.
  • Focus rings visible (--ring token), never outline-none without a replacement.
  • Form inputs always labelled (<label> or aria-label).
  • Live regions for async state changes (aria-live="polite" for toasts, assertive for errors).
  • Color is never the only signal — pair with icon, text, or pattern.
  • Animations respect prefers-reduced-motion.
  • Components shipping a defined ARIA pattern (combobox, dialog, menu, tabs) declare their full keyboard map in meta.json per #255.

12. Voice & writing

  • Buttons: name the action. "Save changes" not "Submit", "Send invite" not "OK".
  • Errors: state what happened + what to do. "Couldn't reach the API. Check your connection and retry."
  • Empty states: explain why empty + what unblocks the user. "No components match. Try a different filter or request a component."
  • Inputs: placeholder = example, label = field meaning. They are not interchangeable.
  • Don't hide failures. If something fails silently, you have a bug.

13. Anti-patterns (banned)

PatternWhy banned
font-bold on display headingsCrushes letter shapes; use font-semibold
bg-black / bg-whiteBreaks dark mode; use bg-background / bg-foreground
Tailwind palette literals (bg-zinc-500)Bypasses tokens; breaks theming
Bounce easingsVisual noise; doesn't scale to small distances
<div> with onClickLoses keyboard + a11y semantics; use Button
Em-dash chains in copy (3+ in a row)Unreadable
Submit / OK / Click here button labelsDon't name the action
Pure black backgroundsEye strain in dark mode
Auto-play hero videoPerformance + motion sensitivity
Modal on modalRestructure the flow
eslint-disable to bypass a ruleFix the root cause

14. Roadmap (this file)

This document is the v1 brand baseline for VLLNT UI. Expansions tracked separately:

  • packages/design/tokens.json — machine-readable tokens (same source of truth, JSON form). Follow-up.
  • /design site route — human-browsable rendering of this file with live token previews. Follow-up.
  • /r/design.json — JSON endpoint mirroring tokens for agent consumption. Follow-up.
  • meta.json a11y schemas per component (#255) — keyboard / ARIA / focus rules surfaced via the registry.

15. References