Spaces:
Running
MediaRouter Design System v1
Purpose
The MediaRouter Design System is the backend-agnostic UI foundation for the workspace product. It is intentionally not a collection of application pages: future Dashboard, Projects, AI, media, publishing, analytics, and automation experiences compose these primitives instead of adding one-off visual rules.
The implementation lives in frontend/ and works with the Next.js App Router,
TypeScript, Tailwind CSS, shadcn-compatible Radix primitives, CVA,
Framer Motion, Lucide, React Hook Form, Zod, TanStack Table/Virtual/Query,
Zustand, next-themes, and Storybook.
Architecture
design-system/
tokens/ typed references to CSS semantic tokens
themes/ theme provider and high-contrast control
foundations/ shared conventions and accessibility rules
motion/ Framer Motion presets
icons/ the only Lucide import boundary for new system components
components/
ui/ accessible Radix/shadcn-compatible primitives
layout/ workspace, panel, split-pane and responsive layout primitives
navigation/ navigation, breadcrumbs, switchers and quick actions
feedback/ alerts, toast API, loading/empty/error/offline/progress states
forms/ composable RHF/Zod-ready controls
charts/ backend-neutral chart frame
timeline/ timeline primitives
media/ backend-neutral media and asset cards
hooks/ interaction, reduced-motion, Zod form and table hooks
stories/ Storybook component catalog
No primitive makes a REST, MCP, n8n, SDK, storage, or provider call. Data and actions are injected by a consuming feature.
Tokens and theming
app/globals.css owns CSS custom-property values. Tailwind maps only semantic
names such as bg-surface, text-text-secondary, border-border,
bg-ai, text-success, and bg-timeline-track. Component source must never
add a literal color value.
Semantic color tokens cover background, surface, elevated surface, border, primary, secondary, accent, success, warning, danger, info, muted, three text levels, overlay, focus ring, selection, timeline track/marker/cursor, and AI, publishing, analytics, and automation accents. Each has light, dark, and high-contrast values.
The standardized spacing scale is 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80,
and 96 pixels (space-1 through space-24). New components use classes such
as gap-space-3, p-space-6, and px-space-4, not arbitrary spacing.
Radius tokens are ds-sm, ds-md, ds-lg, ds-xl, ds-2xl, and ds-full.
Shadow tokens are ds-sm, ds-md, ds-lg, floating, modal, and
popover.
ThemeProvider in design-system/themes/theme-provider.tsx wraps
next-themes and supports light, dark, system, and high-contrast.
Theme preferences are client-side presentation preferences only; no backend
state is required. ThemeToggle cycles all modes.
Typography, icons, and motion
components/typography/typography.tsx provides Display, Heading, Title,
Subtitle, Body, Caption, LabelText, Code, and the composable Typography
primitive. The scale uses semantic font-size tokens and balances dense
workspace information with readable hierarchy.
New design-system components import icons only from
design-system/icons/icon.tsx. Icon uses size tokens, a consistent 1.8
stroke, and is decorative unless a label is supplied. This prevents raw
Lucide usage from fragmenting icon weights and accessibility behavior.
design-system/motion/presets.ts supplies page, sidebar, dialog, popover,
tooltip, toast, hover, press, accordion, tabs, card, list, timeline, drawer,
bottom-sheet, loading, skeleton, and progress presets. Use
useMediaRouterReducedMotion() for interactive Framer Motion consumers. The
global stylesheet also reduces native/Tailwind motion when the operating system
requests reduced motion.
Component inventory
Core UI
- Button, IconButton, ToggleButton, SplitButton, DropdownMenu
- Card, Panel, Section, Container, Stack, Grid, Page, ContentArea
- Dialog, Drawer, BottomSheet, Popover, Tooltip, Tabs, Accordion
- Badge, StatusBadge, ProviderBadge, AIBadge, Avatar, Separator
- Command/CommandPalette/Spotlight, Combobox, Pagination, Calendar/DatePicker
- Progress and Skeleton
Forms
- Input, Textarea, Select, Checkbox, RadioGroup, Switch, Slider
- Email, URL, phone, number, currency, search, password, OTP, and color inputs
- Field shell with helper, success, required, disabled, and error states
- FileDropzone, TagInput, MediaSelector, RHF
Form, anduseZodForm
Data, media, and feedback
useDataTable, DataTable, and VirtualTable (sorting, filtering, grouping, selection, visibility, sticky headers, responsive overflow)- MetricCard, StatCard, KPICard, Timeline, ActivityItem
- MediaCard, AssetCard, ProjectCard, ChartContainer
- Alert, Error/Retry/Success banners, toast API, Empty/Error/Offline states, and job/upload/AI/publishing progress
Navigation and workspace layout
- WorkspaceShell, Sidebar, Topbar, Inspector, SplitPane, ResizablePanel, Toolbar, Dock, FloatingPanel
- Sidebar/Mobile navigation, Breadcrumb, WorkspaceSwitcher, ProjectSwitcher, and QuickActions
Accessibility standard
The minimum target is WCAG 2.2 AA:
- Radix primitives provide focus traps, escape handling, menu/listbox/dialog keyboard behavior, and screen-reader relationships.
- Interactive controls have visible semantic focus rings and disabled states.
- Icon-only controls require a text label; decorative icons are hidden.
- Form fields offer label, helper, required, success, and
role=alerterror affordances. - Tables use semantic headers and rows; loading and progress use
aria-busy,progress, status regions, and live text where appropriate. - High-contrast theme tokens increase contrast without changing component source. Reduced-motion preferences disable decorative motion.
- Storybook includes
@storybook/addon-a11yconfigured to fail accessibility checks in the component catalog.
Consumers remain responsible for meaningful labels, error copy, logical tab order across a composed page, and testing real content contrast.
Responsive behavior
The system is mobile-first. xs, tablet, laptop, desktop, wide, and
ultra-wide breakpoints are available. Grid and workspace primitives collapse
to a single column before sidebars/inspectors appear. Tables retain semantics
with horizontal overflow; consuming features may use their own compact-card
renderer for intentionally collapsed mobile views. The bottom dock and bottom
sheet are mobile-ready, including safe-area padding.
Storybook
Run from frontend/:
npm run storybook
npm run storybook:build
Stories cover UI foundations, interactive overlays and controls, forms, feedback, layout/navigation, data display, media, states, sizes, loading, dark/high-contrast controls, and responsive composition. The Storybook toolbar selects light, dark, and high-contrast themes.
Best practices
- Compose primitives; do not introduce page-local UI primitives.
- Use semantic Tailwind tokens and spacing/radius/shadow tokens.
- Keep backend queries, mutation logic, API URLs, and provider credentials outside the design system.
- Add closed typed props and CVA variants before adding a visual state.
- Use
forwardReffor DOM controls and primitives intended for composition. - Use
Iconrather than raw Lucide imports in all new system code. - Use
loading, empty, error, offline, and disabled states intentionally. - Do not animate state merely because it changed; apply motion presets only when they clarify hierarchy or progress.
Contribution guide
For each new primitive:
- Confirm that it cannot be composed from an existing primitive.
- Add semantic tokens only when the state has a cross-product meaning.
- Implement typed props, CVA variants, focus/keyboard behavior, high
contrast, reduced motion, loading/empty/error where applicable, and a
forwardRefwhen it owns a DOM element. - Add a Storybook story that covers variants, sizes, disabled/loading, dark mode, high contrast, keyboard behavior, and responsive behavior.
- Run
npm run lint,npm run typecheck,npm test,npm run build, andnpm run storybook:buildbefore merging.
Future extensions
The foundations intentionally leave backend-bound concerns for future feature work: workspace data adapters, project data, provider-specific visual metadata, server-driven chart schemas, persisted user layout preferences, internationalization, more date-range/calendar behavior, and advanced grid column personalization. Those additions must consume this system rather than add page-local visual foundations.