Colors

Semantic color tokens adapt per palette. The 3-tier architecture maps primitives (blue-500) to semantic aliases (brand-primary) to component tokens (button-bg).

Neutral Scale

bg-primaryPage background
bg-secondarySection alt
bg-tertiaryCards
bg-inverseInverted
text-primaryHeadlines
text-secondaryBody text
text-tertiaryMuted

Brand Colors

brand-primaryCTA, links
brand-secondaryAccents
brand-accentHighlights
brand-mutedTints

Semantic Colors

successPositive
warningCaution
errorDestructive
infoInformational

Typography

Fluid type scale using clamp() for responsive sizing without breakpoints. Font families are foundation-locked: Inter for body, Inter for display headings, JetBrains Mono for code, Source Serif 4 for editorial callouts. These never change per palette.

Display Large
Display Medium
Heading Large
Heading Medium
Heading Small
Body Large (18px)
Body Medium (16px)
Body Small (14px)
Label (12px)

Spacing & Grid

4px base grid. 13 spacing tokens from 4px to 80px.

Shadows & Elevation

5-level shadow system. Dark themes use glow-border technique (white rgba border + deeper black shadow) instead of invisible black shadows.

xs
sm
md
lg
xl

Motion

Duration tokens (fast/normal/slow/slower) + 4 easing curves. All motion respects prefers-reduced-motion.

Motion Choreography

Standardized animation presets combining duration + easing + transform. Every component follows these choreography patterns for consistent motion language.

Enter Transitions

250ms · ease-out
250ms · ease-out
150ms · spring
expand ↕
250ms · default

Stagger Children

60ms stagger delay · fade-in + slide-up · max 600ms total

Interaction Feedback

hover-lift
/* Enter: fade + slide */ .enter { animation: fadeSlideUp 250ms cubic-bezier(0,0,0.2,1) forwards; } @keyframes fadeSlideUp { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } /* Stagger children: 60ms per item */ .stagger > :nth-child(1) { animation-delay: 0ms; } .stagger > :nth-child(2) { animation-delay: 60ms; } .stagger > :nth-child(3) { animation-delay: 120ms; } /* ... max 600ms total */ /* Interaction: hover-lift */ @media (hover: hover) { .interactive:hover { transform: translateY(-2px); } } .interactive:active { transform: scale(0.98); } /* Respect motion preferences */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } }

Modern CSS Transitions

Tokens for the View Transitions API and @starting-style rule. These modern CSS features enable smooth page transitions and entry animations for elements that transition from display: none.

View Transition Names

Assign named view transitions to key UI elements so the browser can animate them across page navigations or DOM state changes.

TokenValueUsage
--transition-view-transition-name-headeruds-headerPersistent header across navigations
--transition-view-transition-name-herouds-heroHero sections with cross-fade
--transition-view-transition-name-carduds-cardCard morph transitions
--transition-view-transition-name-sidebaruds-sidebarSidebar navigation persistence
--transition-view-transition-name-modaluds-modalModal dialog transitions

@starting-style Tokens

The @starting-style rule defines the initial state for elements entering the DOM or transitioning from display: none. This replaces the need for JavaScript-triggered animation classes.

ElementOpacityTransformDescription
Modal0scale(0.95)Scale-in entry for modal dialogs
Dropdown0translateY(-8px)Slide-down entry for dropdowns
Toast0translateX(100%)Slide-in from right for toasts
Popover0scale(0.9) translateY(-4px)Combined scale and slide for popovers

Transition Styles

Domain-specific easing curves recommended by the reasoning engine based on sector context.

Luxury, premium
Finance, dashboards
Healthcare, education
Instant
Data-dense UIs

Usage Examples

/* View Transitions API — cross-page element morphing */ .uds-header { view-transition-name: var(--transition-view-transition-name-header); } .uds-card { view-transition-name: var(--transition-view-transition-name-card); } /* Customize the transition animation */ ::view-transition-old(uds-card) { animation: var(--duration-fast) var(--ease-out) fade-out; } ::view-transition-new(uds-card) { animation: var(--duration-normal) var(--ease-out) fade-in; } /* @starting-style — entry animation from display:none */ .uds-modal { opacity: 1; transform: scale(1); transition: opacity var(--duration-normal) var(--ease-out), transform var(--duration-normal) var(--ease-out), display var(--duration-normal) allow-discrete; @starting-style { opacity: 0; transform: scale(0.95); } } .uds-toast { opacity: 1; transform: translateX(0); transition: opacity var(--duration-normal) var(--ease-out), transform var(--duration-normal) var(--ease-out), display var(--duration-normal) allow-discrete; @starting-style { opacity: 0; transform: translateX(100%); } } /* Sector-specific transition styles from reasoning engine */ /* Luxury: elegant curve */ .transition-elegant { transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } /* Finance: snappy curve */ .transition-snappy { transition-timing-function: cubic-bezier(0.2, 0, 0, 1); } /* Healthcare: gentle curve */ .transition-gentle { transition-timing-function: cubic-bezier(0.4, 0, 0.6, 1); } /* Data-dense: instant (no visible transition) */ .transition-instant { transition-timing-function: steps(1); } /* Always respect reduced motion */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; view-transition-name: none !important; } }

Browser Support

View Transitions API

Chrome 111+, Edge 111+, Opera 97+. Safari 18+. Firefox behind flag. Use document.startViewTransition() with progressive enhancement — non-supporting browsers simply skip the animation.

@starting-style

Chrome 117+, Edge 117+, Opera 103+, Safari 17.5+. Firefox 129+. Graceful degradation — without support, elements appear without entry animation. Pair with transition-behavior: allow-discrete for display transitions.

Layout & Scale

Foundation-level tokens for layout breakpoints, border radii, z-index layers, and opacity. These are governance-locked and never change per palette.

Border Radius Scale

Radius Scale
sm
md
lg
xl
2xl
full

Z-Index Layers

TokenValueUsage
--z-dropdown100Dropdown menus, popovers
--z-sticky200Sticky headers, toolbars
--z-overlay300Overlay backdrops
--z-modal400Modal dialogs
--z-toast500Toast notifications
--z-tooltip600Tooltips (above everything)
--z-system9999Skip links, system-level UI

Opacity Scale

Opacity Tokens
disabled (0.4)
muted (0.6)
subtle (0.8)
full (1.0)

Layout Breakpoints

TokenBreakpointContainer MaxUsage
sm640px640pxLarge phones
md768px768pxTablets
lg1024px1024pxSmall laptops
xl1280px1200pxDesktops
2xl1536px1400pxWide screens

Color Palettes

Each palette changes only color and shadow tokens. Typography, spacing, radii, and motion are locked to foundation values. Every palette ships with light + dark appearance modes, toggled via the sidebar button.

PaletteLight bgBrand PrimaryShapeCharacter
Minimal SaaS#FFFFFF#2563EBSoft (6-12px)Clean, conversion-focused
AI Futuristic#0A0A0F#00FF88Sharp (2-6px)Dark-native, neon accents
Gradient Startup#FFFFFF#7C3AEDRound (8-16px)Bold gradients, energetic
Corporate#FFFFFF#1A365DSquare (2-6px)Muted, authoritative
Apple Minimal#FFFFFF#0071E3Smooth (8-14px)Product-driven, restrained
Illustration#FFFFFF#C2410CFriendly (10-18px)Warm, playful, multi-color
Dashboard#FFFFFF#4F46E5Compact (4-8px)Data viz, chart-friendly
Bold Lifestyle#FFFFFF#111111Brutalist (0px)High-contrast, editorial
Minimal Corporate#FDFCFB#B45309Warm neutrals, editorial
Governance: Palettes override --color-*, --shadow-*, --radius-*, and --font-display tokens. Spacing, motion, z-index, opacity, and body typography remain foundation-locked.

Palette Selection Rules

ContextDefault PaletteRationale
Product UI (SaaS, apps)Minimal SaaSHighest readability, neutral brand presence, conversion-optimized
Marketing siteGradient StartupHigh visual energy for acquisition pages; default for all marketing surfaces
Internal dashboardsDashboardChart-friendly 8-color scale, tabular number support
Developer tools / docsAI FuturisticDark-native, monospace-friendly, low eye strain
Enterprise / regulatedCorporateConservative, authority-forward, stakeholder-safe
Rule: Each product or surface selects exactly one palette — the default listed above. Teams must not mix palettes within a single product. If no context matches, default to Minimal SaaS.
Exceptions: To use a non-default palette (e.g., Illustration instead of Gradient Startup for a marketing surface), file a design-system exception request with: (1) the surface name, (2) the requested palette, (3) rationale, and (4) sign-off from the design-system owner. Approved exceptions are logged in the governance registry.

Button

Primary action trigger. 4 variants, 3 sizes, all with 44px minimum touch target.

Live Preview WCAG AA
Min 44px touch target. Focus ring 2px solid + 2px offset. Disabled uses opacity token, cursor:not-allowed.
Use clear action verbs: "Save changes", "Create account", "Send message". Match variant to importance — Primary for main CTA, Secondary for alternatives.
Don't use vague labels like "Click here" or "Submit". Don't put two Primary buttons side by side — one should be Secondary.
<button class="btn btn--primary btn--md">Get Started</button> <button class="btn btn--secondary btn--md">Learn More</button> <button class="btn btn--ghost btn--md">Cancel</button>
PropOptionsDefault
variantprimary, secondary, ghost, destructiveprimary
sizesm (36px), md (44px), lg (52px)md
disabledbooleanfalse

Input

Form text input. WCAG 3:1 border contrast with dedicated border-input token.

Live Preview SC 1.4.11
As it appears on your ID
Labels use for/id. Error state uses aria-invalid + aria-describedby. Error text has role="alert".
Always pair inputs with visible labels. Use helper text for format hints ("MM/DD/YYYY"). Show inline validation errors immediately below the field.
Don't use placeholder text as the only label — it disappears on focus. Don't disable the submit button for validation — show errors instead.

Select

Toggle Switch

Live Preview NEW
Notifications enabled

Tabs

Accessible tabbed interface with keyboard navigation.

Live Preview NEW

Overview content. Tabs use role="tablist" and aria-selected for screen reader support.

role="tablist" on container, role="tab" on triggers, role="tabpanel" on content. Arrow keys navigate, Enter/Space activates.

Accordion

Live Preview NEW
A governed design system with foundation-locked tokens, 9 color palettes, and 43 components built for WCAG 2.2 AA compliance.

Card

Content container with hover elevation. Used for features, pricing tiers, and grouped content.

Performance
Sub-2.5s LCP with optimized asset delivery.
Themeable
9 themes from one token architecture.
Accessible
WCAG 2.2 AA by default across all themes.

Alert

Status banners for success, warning, error, and informational messages. 4px left border + semantic background.

Live Preview WCAG AA
Success
Your changes have been saved.
Info
New version available. Refresh to update.
role="status" for non-urgent, role="alert" for critical. Semantic border + background colors ensure distinguishability without relying on color alone.
Use Success for completed actions, Warning for non-blocking issues, Error for blocking failures, Info for neutral updates. Keep messages under 2 lines.
Don't use alerts for marketing content or feature promotion. Don't stack more than 2 alerts — combine messages or use a toast for transient ones.

Badge

Compact labels for status, categories, and counts. 4 semantic variants.

Live Preview NEW
Brand Active Failed Draft
Use badges for status indicators, counts, and category labels. Keep text to 1–2 words. Match variant to semantic meaning — Success for "Active", Error for "Failed".
Don't use badges for long descriptions. Don't use more than 3 badge variants in the same view — it creates visual noise.

Avatar

User representation with initials, status indicators, and grouping. 5 sizes from 24px to 64px.

Live Preview NEW
A
MK
JD
CS
AB

Avatar Group

A
B
C
+5
Use initials when no profile image is available. Show status indicators (online/busy) only when real-time presence is meaningful. Limit avatar groups to 5 + overflow count.
Don't mix avatar sizes in the same row. Don't use avatars without alt text or aria-label — screen readers need to identify the person.

Tooltip

Live Preview NEW
role="tooltip" on content, aria-describedby on trigger. Shows on hover AND focus for keyboard users.

Toast / Snackbar

Live Preview NEW
Saved successfully
Your changes have been saved.
Syncing
3 files are being synced...

State Matrix

StateVisualTokensBehaviorTiming
EnteringSlide up from bottom-right + fade inz-index: --z-toast (500), shadow: --shadow-lg, radius: --radius-mdAdds to stack (max 3 visible)Enter: --duration-normal ease-out
Visible (success)Green left border, check iconborder-left: 4px --color-success, icon: --icon-md (20px)Auto-dismiss countdown active5 seconds
Visible (error)Red left border, alert iconborder-left: 4px --color-error, icon: --icon-md (20px)Auto-dismiss countdown active8 seconds
HoveredNo visual changecursor: defaultPause auto-dismiss timerTimer resumes on mouse leave
Dismissed (user)Fade out + slide righttransform: translateX(100%), opacity: 0Close button clickedExit: --duration-fast ease-in
Dismissed (auto)Fade out + slide downtransform: translateY(8px), opacity: 0Timer expiredExit: --duration-fast ease-in
Stacked (overflow)Oldest toast removedgap: --space-3 (12px) between toastsWhen 4th toast arrives, remove oldestImmediate removal of excess

Pagination

Live Preview NEW

Skeleton / Loading

Live Preview NEW
Container uses aria-busy="true". Elements use aria-hidden="true". Animation paused with prefers-reduced-motion.

Data Table

Live Preview NEW
NameStatusRoleLast Active
Alice JohnsonActiveAdminJust now
Bob SmithPendingEditor2h ago
Carol DavisInactiveViewer3 days ago
David LeeActiveEditor5m ago

State Matrix

StateVisualTokensBehaviorARIA
Loading (initial)3-5 skeleton rows, header visible--skeleton-count: 4, row-height: 48pxNo interaction on rowsaria-busy="true" on table
Loading (refresh)Existing rows stay, subtle overlayoverlay: --opacity-muted (0.6)Sorting/pagination disabledaria-busy="true"
EmptyIllustration + heading + CTA centeredpadding: --space-16, icon: --icon-xl (32px)Primary action button focusedrole="status" on message
ErrorInline alert above table + retryborder-left: 4px --color-errorPreserve stale data if availablerole="alert"
Selected (single)Row bg: --color-brand-mutedbg: --color-brand-muted, border-left: 2px --color-brand-primaryCheckbox checked, action bar visiblearia-selected="true"
Selected (bulk)Count badge + bulk action baraction-bar height: 48px, z-index: --z-sticky (200)"Select all" applies to current pageLive region announces count
SortedArrow icon in column headericon: --icon-sm (16px), color: --color-text-primaryRe-fetches/re-sorts dataaria-sort="ascending|descending"

Component Variant API

CVA-style variant contracts for every component. Variants compose as className--{variant}. Invalid combinations are explicitly disallowed.

Button

PropValuesDefaultCSS Class
variantprimary · secondary · ghost · destructiveprimary.btn--{variant}
sizesm · md · lgmd.btn--{size}
statedefault · hover · active · disabled · loadingdefault[disabled] · .btn--loading
fullWidthtrue · falsefalse.btn--block
iconOnlytrue · falsefalse.btn--icon

Input

PropValuesDefaultCSS Class
variantdefault · error · successdefault.input--{variant}
sizesm · md · lgmd.input--{size}
statedefault · focus · disabled · readonlydefault[disabled] · [readonly]
prefixicon · text · nonenone.input-group

Card

PropValuesDefaultCSS Class
variantelevated · outlined · filledelevated.card--{variant}
paddingcompact · default · spaciousdefault.card--{padding}
interactivetrue · falsefalse.card--interactive (adds hover-lift)

Badge

PropValuesDefaultCSS Class
variantbrand · success · error · neutral · warningneutral.badge--{variant}
sizesm · mdmd.badge--{size}
dottrue · falsefalse.badge--dot (status indicator)

Alert

PropValuesDefaultCSS Class
variantsuccess · warning · error · infoinfo.alert--{variant}
dismissibletrue · falsefalseAdds close button
icontrue · falsetrueHides leading icon

Toast

PropValuesDefaultCSS Class
variantsuccess · warning · error · infoinfo.toast--{variant}
positiontop-right · top-center · bottom-right · bottom-centerbottom-rightJS positioning
duration3000 · 5000 · 8000 · persistent5000JS auto-dismiss
actiontext · nonenone.toast-action

Avatar

PropValuesDefaultCSS Class
sizexs (24) · sm (32) · md (40) · lg (48) · xl (64)md.avatar--{size}
statusonline · busy · nonenone.avatar-status--{status}
fallbackinitials · icon · imageinitialsContent-based
grouptrue · falsefalse.avatar-group

Toggle

PropValuesDefaultCSS Class
checkedtrue · falsefalse.toggle.on
disabledtrue · falsefalse[disabled]
sizesm · mdmd.toggle--{size}

Data Table

PropValuesDefaultCSS Class
densitycompact (36px) · default (48px) · comfortable (56px)default.data-table--{density}
sortabletrue · falsefalse.data-table--sortable
selectablenone · single · multinone.data-table--selectable
stripedtrue · falsefalse.data-table--striped
stickyHeadertrue · falsefalse.data-table--sticky
Compound variants: Combine props freely except where noted. Invalid combos (e.g., ghost + destructive on buttons) should be caught at lint-time. Use the data-variant attribute for framework-agnostic variant detection.

Component Sandbox

Interactive playground — change props and see live updates. Theme inherits from palette selector above.

<button class="btn btn--md btn--primary">Button</button>

CSS Cascade Layers

All UDS token and component CSS is wrapped in @layer declarations for explicit cascade control. This prevents specificity conflicts between UDS styles and your application styles without resorting to !important.

Layer Hierarchy

UDS declares three ordered layers. Styles in later layers take precedence over earlier ones:

  1. uds.tokens — Design token custom properties (:root variables, palette overrides)
  2. uds.components — Component styles (.btn, .card, .input, etc.)
  3. uds.utilities — Utility classes and overrides

How It Works

The generated CSS output declares the layer order first, then places all tokens inside @layer uds.tokens:

@layer uds.tokens, uds.components, uds.utilities; @layer uds.tokens { :root { --color-brand-primary: #2563eb; --color-text-primary: #1a1a24; --space-4: 16px; /* ... all token custom properties */ } }

Overriding UDS Styles

To override UDS styles cleanly, declare your own layer after the UDS layers. Styles in your layer automatically take precedence:

@layer uds.tokens, uds.components, uds.utilities, app; @layer app { /* Your styles here -- automatically override UDS without !important */ .custom-button { background: var(--color-brand-primary); border-radius: 999px; } .hero-section { padding: var(--spacing-16); } }

Backward Compatibility

If your project does not use @layer, UDS styles still work correctly. Unlayered styles (styles not inside any @layer) always take precedence over layered styles in the CSS cascade. This means existing consumer stylesheets that do not use @layer will automatically override UDS defaults without any changes.

Browser Support

@layer is supported in all modern browsers since 2022: Chrome 99+, Firefox 97+, Safari 15.4+, and Edge 99+. For older browsers, the layer declarations are ignored and styles apply in normal source order.

Pattern: Forms

System-wide rules for form layout, validation, and submission. These rules apply to every form regardless of which components are used.

Layout

Single-column by default. Only use multi-column for short, related fields (city + state). Labels always above inputs, never floating or inline.

Validation

Inline errors below the field, shown on blur (not keystroke). Error text uses --color-error with role="alert". Never validate on focus.

Required Fields

Mark optional fields with "(optional)" suffix. Do not use asterisks. All fields are assumed required unless marked.

Submission

Primary button at bottom-left. Disable on submit, show inline spinner. Never navigate away on error. Preserve all entered data on failure.

Spacing

Label-to-input gap: --spacing-1 (4px). Field-to-field gap: --spacing-5 (20px). Section gap: --spacing-8 (32px).

Help Text

Below input, above error message. Uses --color-text-tertiary at --text-body-sm. Connected via aria-describedby.

Pattern: Data Tables

Rules for tabular data display, sorting, pagination, and state handling.

Row Height

Compact: 40px. Default: 48px. Relaxed: 56px. Use compact for data-dense dashboards, relaxed for settings/admin.

Empty State

Centered illustration + heading + action. Never show an empty <tbody>. Use "No [items] found" with a clear action ("Create first [item]").

Loading State

Skeleton rows (3-5) matching column layout. Header stays visible. Never show a full-page spinner for table reloads.

Error State

Inline alert above table: "Unable to load data" + retry button. Preserve any existing rows if the error is a refresh failure.

Sorting

Click header to cycle: unsorted → ascending → descending. Active sort column uses aria-sort. Only one column sorted at a time.

Selection

Checkbox in first column. "Select all" selects current page only. Show selection count + bulk action bar above table on selection.

Pattern: Navigation

Rules for wayfinding, hierarchy, and movement between views.

Primary Nav

Maximum 7 top-level items. Use icons + text labels; never icons-only for primary navigation. Active state uses aria-current="page".

Sidebar Nav

Group items under section headings. Collapse groups by default if >3 sections (Foundation always expanded; active section auto-expands on scroll). Active item highlighted with --color-brand-primary left border.

Breadcrumbs

Show on pages >2 levels deep. Current page is plain text (not a link). Separator: /. Truncate middle items on mobile with ellipsis.

Mobile

Collapse to hamburger below md breakpoint (768px). Drawer slides from left, full height. Trap focus inside open drawer.

Pattern: Feedback

Rules for alerts, toasts, error handling, and confirmations. These rules override any per-component defaults.

Alert Rules

Max 2 lines of text. Use role="status" for info/success, role="alert" for error/warning. Never use alerts for marketing content. Never stack more than 1 inline alert per section.

Toast Rules

Auto-dismiss after 5s (success) or 8s (error). Max 3 visible toasts, stacked bottom-right. Newest on top. Must include close button. Pause timer on hover.

Destructive Confirmations

Require explicit confirmation modal for irreversible actions (delete, publish, transfer). Primary button is destructive variant. Include "Type to confirm" for batch operations.

Loading Feedback

Show spinner after 300ms delay (avoid flicker). For >3s operations, show progress text. For >10s, show estimated time remaining. Never block the entire UI.

Empty States

Always include: illustration or icon, heading, 1-line description, and a primary action button. Never show a blank page or container.

Error Recovery

Every error message must include a next step: retry button, help link, or specific fix instruction. Never show raw error codes or stack traces.

Accessibility Audit

Automated WCAG 2.2 AA contrast verification covering 108 checks (9 palettes × 2 modes × 6 color pairs: text-primary/bg-primary, text-secondary/bg-primary, text-primary/bg-secondary, text-on-brand/brand-primary, brand-primary/bg-primary, text-tertiary/bg-primary). Last audited: March 2026.

100.0%
Pass Rate
62
Checks Run
18
Palette×Mode Combos
Palette Light Min Ratio Dark Min Ratio
Min SaaS 0.0:1 4/4 4.5:1
AI Futur. 6/6 4.7:1 6/6 4.7:1
Grad. Start. 0.0:1 5/5 3.4:1
Corporate 1/1 15.4:1 5/5 4.2:1
Apple Min. 1/1 16.3:1 5/5 4.1:1
Illustr. 1/1 17.0:1 5/5 4.8:1
Dashboard 1/1 17.8:1 5/5 3.1:1
Bold Life. 1/1 17.3:1 6/6 3.7:1
Min Corp. 5/5 4.7:1 5/5 4.0:1

Checks Performed

Body text → bg
4.5:1 required (AA)
Secondary text → bg
4.5:1 required (AA)
Text on cards
4.5:1 required (AA)
Brand button text
4.5:1 required (AA)
Brand links
3.0:1 required (AA large)
Tertiary text
3.0:1 required (AA large)

Governance Requirements

Color Contrast

4.5:1 text, 3:1 UI (SC 1.4.11). Verified across all 9 palettes × 2 modes.

Keyboard Navigation

Full tab order, arrow keys for composite widgets, Escape to dismiss.

Screen Readers

ARIA roles, states, properties on every interactive component.

Motion Sensitivity

prefers-reduced-motion disables all animations globally.

Touch Targets

44px minimum per WCAG 2.2 SC 2.5.8 on all interactive elements.

Forced Colors

forced-colors media query ensures Windows High Contrast Mode support.