Skip to main content

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

ColorUse ForNever Use For
Navy #0F2D44Sidebar, dark panels, header backgroundsBody text on white
Blue #1D6FA4Primary buttons, links, active states, ticket numbersWarning states, success states
Sky #7EC8E3Logo wordmark accent onlyAny product UI element
Cloud #F4F7FAPage background, content area backgroundText
Amber #F59E0BWarning badges, high priority indicatorsAny non-warning context
Green #10B981Success states, completed statusAny non-success context
Red #EF4444Destructive actions, urgent priority, error statesAny 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.

FontWeightRoleExample Usage
Barlow Condensed700Wordmark onlyROUNDTRIP logo, major KPI numbers
DM Sans600, 700Headings, button labels, section titles<h1>, <h2>, <button>
Inter400, 600Body text, table content, form labels, UI text<p>, <td>, <label>
JetBrains Mono400Ticket numbers, IDs, timestamps, codeTKT-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:

ComponentLocationPurpose
MetaRowsrc/components/MetaRowLabel + value row for detail panels
SurfacePanelsrc/components/SurfacePanelBordered card/panel wrapper
SectionHeadersrc/components/SectionHeaderSection title with optional action
StatusBadgesrc/components/StatusBadgeTicket/invoice status pill
PriorityBadgesrc/components/PriorityBadgePriority indicator pill

Status Badges

Status badges use filled pill style with semantic colors:

StatusColorCSS Variable
OpenBlue--rt-blue
AssignedAmber--rt-amber
In ProgressBlue (active)--rt-blue
On HoldGrey--rt-grey
CompletedGreen--rt-green
CancelledRed muted--rt-red at reduced opacity

Priority Indicators

Priority is communicated via two mechanisms on ticket rows:

  1. A PriorityBadge component showing the priority label
  2. A colored left border on the row — this is the key visual treatment
PriorityLeft Border Color
Urgent--rt-red
High--rt-amber
NormalNone
LowNone

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.

RuleDetail
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 UINever import API files or call useMutation / useQuery directly in page components
Use features/ folder structureNot pages/ — all feature code lives under src/features/
Never reinvent existing componentsAlways check src/components/ first
No hardcoded colorsAlways 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.