Design System
The RoundTrip design system is the single source of truth for UI implementation. Before building any new component or page, check here first. Do not reinvent components that already exist.
:::info Check Before You Build
Existing shared components live in src/components/. Always check there before building something new. Key components: MetaRow, SurfacePanel, SectionHeader, StatusBadge, PriorityBadge.
:::
Design Concept
RoundTrip's UI is built on a command center / dispatch operations mental model. Dispatchers are the air traffic controllers of field service — the UI should feel like it. This means:
- High information density — see a lot at once without scrolling
- Dark navy panels with bright blue as the primary action color
- Tight data hierarchy — urgent things look urgent, completed things recede
- Monospace for data that needs to be read precisely
- Semantic color discipline — colors mean the same thing everywhere
Color Palette
All colors are defined as CSS variables. Never hardcode hex values in component files. Always reference the variable.
:root {
/* Core brand */
--rt-navy: #0F2D44; /* primary background, sidebar, dark panels */
--rt-blue: #1D6FA4; /* primary action, links, CTAs, active states */
--rt-sky: #7EC8E3; /* logo accent only — not used in product UI */
--rt-cloud: #F4F7FA; /* page background (light content areas) */
--rt-mist: #DDE5ED; /* borders, dividers, subtle separators */
--rt-slate: #2C3E50; /* body text, table content */
--rt-grey: #6B7F8E; /* secondary text, labels, metadata */
/* Semantic */
--rt-amber: #F59E0B; /* warning, high priority — amber means warning, always */
--rt-green: #10B981; /* success, completed — green means success, always */
--rt-red: #EF4444; /* destructive, urgent — red means danger, always */
}
Brand Gradient
Used for hero sections, marketing moments, and the login/splash screen. Not for UI chrome.
background: linear-gradient(135deg, #0F2D44 0%, #1D6FA4 60%, #2A8EC4 100%);
Color Usage Rules
| Color | Use For | Never Use For |
|---|---|---|
Navy #0F2D44 | Sidebar, dark panels, header backgrounds | Body text on white |
Blue #1D6FA4 | Primary buttons, links, active states, ticket numbers | Warning states, success states |
Sky #7EC8E3 | Logo wordmark accent only | Any product UI element |
Cloud #F4F7FA | Page background, content area background | Text |
Amber #F59E0B | Warning badges, high priority indicators | Any non-warning context |
Green #10B981 | Success states, completed status | Any non-success context |
Red #EF4444 | Destructive actions, urgent priority, error states | Any non-danger context |
:::danger Semantic Colors Are Fixed Amber, green, and red carry fixed meanings throughout the product. A user who has learned these associations cannot be surprised by a green destructive action or an amber success state. Never reuse semantic colors for other meanings. :::
Typography
All four typefaces are loaded from Google Fonts. Each has a specific role — do not substitute.
| Font | Weight | Role | Example Usage |
|---|---|---|---|
| Barlow Condensed | 700 | Wordmark only | ROUNDTRIP logo, major KPI numbers |
| DM Sans | 600, 700 | Headings, button labels, section titles | <h1>, <h2>, <button> |
| Inter | 400, 600 | Body text, table content, form labels, UI text | <p>, <td>, <label> |
| JetBrains Mono | 400 | Ticket numbers, IDs, timestamps, code | TKT-0042, 2026-07-01 09:30 |
/* Heading */
font-family: 'DM Sans', sans-serif;
font-weight: 700;
/* Body / UI */
font-family: 'Inter', sans-serif;
font-weight: 400;
/* Ticket numbers, IDs, timestamps */
font-family: 'JetBrains Mono', monospace;
font-weight: 400;
color: var(--rt-blue);
:::info Ticket Numbers Always in Mono Ticket numbers, IDs, and timestamps must always be rendered in JetBrains Mono. This is not optional — monospace makes them easier to read precisely and distinguishes them visually from prose content. :::
Icons
RoundTrip uses Phosphor Icons throughout the product.
npm install @phosphor-icons/react
import { Ticket, Wrench, Bell, MapPin } from '@phosphor-icons/react';
<Ticket size={20} weight="bold" />
Use the regular weight for most UI icons. Use bold for emphasis or primary actions. Use fill sparingly — only for active/selected states.
Layout
Core Layout Split
┌─────────────────────────────────────────────────────┐
│ Top Command Bar (Navy) │
│ Active Techs: 4 | Open Tickets: 12 | Urgent: 2 │
├──────────────┬──────────────────────────────────────┤
│ │ │
│ Sidebar │ Content Area │
│ (Navy │ (Cloud #F4F7FA) │
│ #0F2D44) │ │
│ │ Data tables, forms, detail panels │
│ │ │
└──────────────┴──────────────────────────────────────┘
- Sidebar: Navy (
#0F2D44), fixed width, navigation and tenant context - Top command bar: Navy, persistent heads-up display with live operational stats
- Content area: Light (
#F4F7FA), all data tables and detail views
Components
Existing Shared Components
Always check src/components/ before building a new component. Key shared components:
| Component | Location | Purpose |
|---|---|---|
MetaRow | src/components/MetaRow | Label + value row for detail panels |
SurfacePanel | src/components/SurfacePanel | Bordered card/panel wrapper |
SectionHeader | src/components/SectionHeader | Section title with optional action |
StatusBadge | src/components/StatusBadge | Ticket/invoice status pill |
PriorityBadge | src/components/PriorityBadge | Priority indicator pill |
Status Badges
Status badges use filled pill style with semantic colors:
| Status | Color | CSS Variable |
|---|---|---|
| Open | Blue | --rt-blue |
| Assigned | Amber | --rt-amber |
| In Progress | Blue (active) | --rt-blue |
| On Hold | Grey | --rt-grey |
| Completed | Green | --rt-green |
| Cancelled | Red muted | --rt-red at reduced opacity |
Priority Indicators
Priority is communicated via two mechanisms on ticket rows:
- A
PriorityBadgecomponent showing the priority label - A colored left border on the row — this is the key visual treatment
| Priority | Left Border Color |
|---|---|
| Urgent | --rt-red |
| High | --rt-amber |
| Normal | None |
| Low | None |
Buttons
/* Primary — blue fill */
<button className="bg-[#1D6FA4] text-white font-semibold px-4 py-2 rounded-md">
Assign Technician
</button>
/* Secondary — outlined */
<button className="border border-[#DDE5ED] text-[#2C3E50] px-4 py-2 rounded-md">
Cancel
</button>
/* Destructive */
<button className="bg-[#EF4444] text-white font-semibold px-4 py-2 rounded-md">
Delete
</button>
Data Tables
- Subtle row hover using navy tint (
rgba(15, 45, 68, 0.04)) rather than grey - Ticket number column always in JetBrains Mono, blue
- Priority left-border treatment on rows (see above)
- Status column always uses
StatusBadge - Timestamp columns always in JetBrains Mono, secondary text color
Frontend Architecture Rules
These rules govern where code lives in the frontend. Following them keeps the codebase consistent and maintainable.
| Rule | Detail |
|---|---|
API calls belong in src/lib/api/ | Domain files using apiClient — never inline in components or pages |
TanStack Query hooks belong in src/features/*/hooks/ | Keep data-fetching logic out of UI components |
| Pages are pure UI | Never import API files or call useMutation / useQuery directly in page components |
Use features/ folder structure | Not pages/ — all feature code lives under src/features/ |
| Never reinvent existing components | Always check src/components/ first |
| No hardcoded colors | Always use CSS variables or Tailwind classes — never hex values in JSX |
Storybook (Planned)
Storybook is planned as the interactive component explorer for RoundTrip. When implemented it will provide a browsable, live reference of every component with its variants and props.
See Design Introduction for the full roadmap.
Related
- Brand — logo, brand colors, typography rules for external use
- Brand Guidelines ↗ — full visual identity reference
- Frontend Coding — coding standards for UI implementation
- UI Patterns — page-level patterns and layout conventions