Skip to main content

UI Components

Component Library​

UI primitives live in frontend/src/components/shared/ui/:

ComponentPurpose
ButtonPrimary action buttons with variants
CardContent container with optional header/footer
InputText input with label and error state
BadgeStatus indicators and labels
TabsTab navigation component
AlertInformational/warning/error alerts
SpinnerLoading indicator

Usage​

import { Button } from '@/components/shared/ui/Button';
import { Card } from '@/components/shared/ui/Card';
import { Badge } from '@/components/shared/ui/Badge';

<Card>
<Badge variant="success">Protected</Badge>
<Button onClick={handleRun}>Execute Test</Button>
</Card>

Theming​

One dark theme — the f0 design language. All tokens live in frontend/src/styles/index.css; there is no Tailwind config file (Tailwind v4 declares theme values in @theme / @theme inline blocks).

The palette is exposed in two layers so both component families wear it:

LayerNamesUsed by
A — runtime tokens--background, --card, --popover, --muted, --border, --primary, --destructive, --ring, --sidebar-*shadcn/cva primitives in components/ui/ and every legacy component
B — f0 semantics--surface, --raised, --overlay, --faint, --border-strong, --accent, --accent-hover, --accent-dim, --danger, --warning, --info (+ -dim variants)new components, written straight from the design recipes (bg-surface, text-faint, border-border-strong)

Overlapping names alias the same custom property, so bg-card and bg-surface resolve identically.

Core palette​

TokenValueRole
--background#060906Page ground
--surface#0b100cCards, sidebar
--raised#101713Inputs, hover wash, code blocks
--overlay#162019Popovers, dialogs
--border#1c261fHairlines
--border-strong#2c3a30Emphasised edges
--foreground#dce8deBody text
--muted#8fa598Secondary text
--faint#5f7268Section labels, metadata
--accent#3ef08aPrimary action, active nav, protected
--danger#f87171Failures, unprotected
--warning#fbbf24Stale, degraded
--info#38bdf8Secure Score, informational badges

Chart tokens are governed​

Chart colours must be referenced as var(--chart-*) — never as hex or oklch literals. chartColorGuard.test.ts fails the build on a literal in any file listed in CHART_FILES; chartTokens.css.test.ts asserts every governed token is declared; contrast.test.ts parses index.css live and enforces WCAG AA (≥ 4.5:1) for label-on-fill pairs. Add new chart files to CHART_FILES in the same commit that creates them.


Layout System​

The layout is built around a hierarchical structure with SidebarLayout as the root container.

SidebarLayout​

The main layout container. Provides:

  • Layout Context -- Enables pages to register dynamic TopBar actions via useLayoutActions()
  • Sidebar State -- Persists collapsed/expanded state in localStorage
  • Responsive Design -- Adapts to different screen sizes
// Pages can register dynamic actions in the TopBar
const { setTopBarActions } = useLayoutActions();
setTopBarActions({
onRefreshClick: handleRefresh,
isRefreshing: loading
});

AppSidebar​

Collapsible navigation sidebar with role-based module access:

  • Collapsible -- Transitions between full and icon-only modes
  • Role-based -- Uses useCanAccessModule() and useHasPermission() to show/hide modules
  • Flyout panels -- Shows sub-navigation when collapsed (rendered via React portals)
  • Module locking -- Displays locked state for unconfigured modules (e.g., Analytics without ES)

Module structure:

const modules: ModuleWithItems[] = [
{
label: "Tests",
icon: Shield,
path: "/dashboard",
subItems: [
{ label: "Dashboard", icon: LayoutDashboard, path: "/dashboard" },
{ label: "Browse All", icon: Home, path: "/dashboard?tab=browse" },
{ label: "Favorites", icon: Bookmark, path: "/favorites" }
]
}
// ... Analytics, Endpoints, Settings modules
];

TopBar​

Application header with dynamic content:

  • Breadcrumbs -- Auto-generated from current route via getBreadcrumb()
  • Global search -- Embedded search trigger (Cmd/Ctrl + K)
  • User context -- Role badges and user information
  • Action buttons -- Refresh, settings, documentation, notifications

GlobalSearch​

Command palette-style search (Cmd/Ctrl + K) with multi-entity results:

FeatureDetail
Search scopeTests, agents, tasks across multiple APIs
Debounce200ms delay to prevent excessive API calls
KeyboardArrow keys to navigate, Enter to select, Escape to close
CachingAvoids repeated API calls within a session
GroupingResults grouped by entity type with icons and badges

NotificationBell​

Real-time alert notifications with dropdown history:

  • Connects to alertsApi for system alerts
  • Red dot indicator for unseen notifications
  • Shows setup prompts when alerting is not configured
  • Relative timestamps (e.g., "5 minutes ago")

Two-Layer Component Architecture​

The UI is organized into two distinct layers:

Shared UI (frontend/src/components/shared/ui/)​

Self-contained components built directly on HTML elements with custom styling. These are the base primitives used everywhere.

Advanced UI (frontend/src/components/ui/)​

More sophisticated components built on Radix UI primitives, providing enhanced accessibility and complex interactions (dropdown menus, sheets, charts).

Shared UI Components (Full Catalog)​

Form Components​

Button​

5 visual variants, 4 sizes, built-in hover animations:

<Button variant="primary" size="lg" onClick={handleClick}>
Submit
</Button>
VariantUse case
primaryPrimary actions
secondarySecondary actions
ghostInline/subtle actions
destructiveDangerous actions (delete, remove)
outlineBordered neutral actions

Sizes: sm, md, lg, icon

Input​

Text input with label, error state, and icon support:

<Input
label="Email"
error="Invalid email format"
leftIcon={<Mail />}
placeholder="Enter your email"
/>

Select​

Dropdown selection component:

<Select
label="Platform"
options={[
{ value: 'windows', label: 'Windows' },
{ value: 'linux', label: 'Linux' }
]}
/>

Checkbox & Switch​

Boolean input components with custom styling and indeterminate state support.

Layout Components​

Card System​

Flexible card layout with semantic sub-components:

<Card>
<CardHeader>
<CardTitle>Task Details</CardTitle>
</CardHeader>
<CardContent>
Content goes here
</CardContent>
<CardFooter>
<Button>Action</Button>
</CardFooter>
</Card>

Table Components​

Complete table system: Table, TableHeader, TableBody, TableRow, TableHead, TableCell. Includes overflow handling, hover effects, and responsive design.

Feedback Components​

Alert​

5 semantic variants with icon integration:

<Alert variant="success" title="Success!" onClose={handleClose}>
Task completed successfully
</Alert>

Variants: default, success, warning, destructive, info

Spinner & LoadingOverlay​

Loading indicators with multiple sizes and an overlay variant:

<LoadingOverlay message="Processing task..." />

Tabs​

Context-based tab system supporting both controlled and uncontrolled modes:

<Tabs defaultValue="details" onValueChange={setActiveTab}>
<TabsList>
<TabsTrigger value="details">Details</TabsTrigger>
<TabsTrigger value="settings">Settings</TabsTrigger>
</TabsList>
<TabsContent value="details">Details content</TabsContent>
</Tabs>

Dialog​

Modal dialog with backdrop, Escape key handling, and focus management:

<Dialog open={isOpen} onClose={handleClose}>
<DialogHeader onClose={handleClose}>
<DialogTitle>Confirm Action</DialogTitle>
</DialogHeader>
<DialogContent>Are you sure?</DialogContent>
<DialogFooter>
<Button variant="outline" onClick={handleClose}>Cancel</Button>
<Button onClick={handleConfirm}>Confirm</Button>
</DialogFooter>
</Dialog>

Specialized Components​

ComponentPurpose
BadgeStatus indicators with variants (success, warning, destructive, etc.)
PlatformBadgeOS-specific badges (Windows, Linux, macOS)
StatusDotSimple online/offline indicator

Advanced UI Components (Radix-based)​

These components are built on Radix UI primitives for enhanced accessibility and complex interactions.

Avatar System​

User representation with image, fallback initials, and badge:

<Avatar size="lg">
<AvatarImage src="/user.jpg" />
<AvatarFallback>JD</AvatarFallback>
<AvatarBadge>3</AvatarBadge>
</Avatar>

Complex menu system with nested items and keyboard navigation:

<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">Options</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Edit</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>

Sheet​

Slide-out panel component:

<Sheet>
<SheetTrigger asChild>
<Button>Open Panel</Button>
</SheetTrigger>
<SheetContent side="right">
<SheetHeader>
<SheetTitle>Panel Title</SheetTitle>
</SheetHeader>
Panel content
</SheetContent>
</Sheet>

Chart System​

Chart colors are governed: all chart fills route through semantic chart tokens (resolved at runtime via the chartTokens util/hook) rather than hard-coded hex values. A drift-guard test (chartColorGuard.test.ts) fails CI if a chart component reintroduces raw colors, and label contrast is computed for WCAG AA across the heat ramp. When adding a chart, pick from the governed token palette instead of inventing colors.

Recharts integration with theme-aware configuration:

<ChartContainer config={chartConfig}>
<LineChart data={data}>
<ChartTooltip content={<ChartTooltipContent />} />
</LineChart>
</ChartContainer>
warning

When writing custom content renderers for Recharts components (Treemap, etc.), always set stroke="none" on <text> elements. Recharts sets stroke on the parent SVG container for cell borders, and SVG stroke inherits to text children -- causing visible dark outlines around glyphs in dark mode.

Integration Patterns​

Styling with cn()​

All components use the cn() utility (clsx + tailwind-merge) for class merging:

<div className={cn("base-class", isActive && "active-class", className)}>

Icon Integration​

Components integrate with Lucide React icons:

<Button>
<Save className="w-4 h-4" />
Save Changes
</Button>

Variant System​

Most components accept a variant prop following this pattern:

type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'destructive' | 'outline';
type AlertVariant = 'default' | 'success' | 'warning' | 'destructive' | 'info';

Composite Usage Examples​

Form Building​

function TaskForm() {
return (
<Card>
<CardHeader>
<CardTitle>Create Task</CardTitle>
</CardHeader>
<CardContent>
<Input label="Task Name" />
<Select label="Priority" options={priorityOptions} />
<Checkbox label="Send notifications" />
</CardContent>
<CardFooter>
<Button variant="outline">Cancel</Button>
<Button>Create Task</Button>
</CardFooter>
</Card>
);
}

Data Display​

function TaskList({ tasks }) {
return (
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Status</TableHead>
<TableHead>Platform</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{tasks.map(task => (
<TableRow key={task.id}>
<TableCell>{task.name}</TableCell>
<TableCell>
<Badge variant={task.status === 'active' ? 'success' : 'default'}>
{task.status}
</Badge>
</TableCell>
<TableCell>
<PlatformBadge platform={task.platform} />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
}

Performance Considerations​

  • Search debouncing -- GlobalSearch uses a 200ms delay to prevent excessive API calls
  • Portal rendering -- Sidebar flyout panels use React portals to escape stacking contexts
  • Memoized calculations -- Search results and breadcrumbs are memoized
  • Conditional rendering -- Role-based components only render when the user has access

Accessibility​

  • Full keyboard navigation for search, menus, dialogs, and tabs
  • Proper ARIA labels and roles on all interactive elements
  • Automatic focus management in overlays (dialogs, search, sheets)
  • Semantic HTML (<nav>, <header>, <main>, <table>) throughout