Skip to main content

Documentation Index

Fetch the complete documentation index at: https://grantmaster.dev/llms.txt

Use this file to discover all available pages before exploring further.

Component API Reference

Reusable UI components from src/components/ui/. These are the building blocks of GrantMaster’s interface — use them instead of writing inline markup.
Convention: All components support dark mode via Tailwind dark: variants. Colour tokens follow the project palette: slate-* (neutral), primary-* (brand), emerald-* (success), rose-* (error), amber-* (warning).

Layout

PageLayout

Source: src/components/ui/PageLayout.tsx
Top-level content wrapper that constrains width and applies consistent padding.
<PageLayout maxWidth="xl" padding="default">
  <PageHeader title="Projects" />
  {/* page content */}
</PageLayout>

Props

PropTypeDefaultDescription
childrenReactNodePage content
maxWidth'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full''full'Maximum content width (sm = max-w-3xl, md = max-w-5xl, lg = max-w-6xl, xl = max-w-7xl, 2xl = max-w-screen-2xl)
padding'default' | 'compact' | 'none''default'Inner padding (compact = p-4, none / default = p-0)
classNamestring?Additional CSS classes

Source: src/components/ui/PageHeader.tsx
Standard page title bar with optional description, icon, and trailing action buttons. Always use this instead of manual <h1> elements.
<PageHeader
  title="Expense Reports"
  description="Track and manage project expenditures"
  icon={Receipt}
  actions={<Button onClick={handleAdd}>New Expense</Button>}
/>

Props

PropTypeDefaultDescription
titlestring | ReactNodePage heading (rendered as <h1>)
descriptionstring?Subtitle text below the heading
actionsReactNode?Buttons or controls rendered at the trailing edge
iconComponentType?Lucide icon rendered before the title
classNamestring?Additional CSS classes on the outer container

PageTabs

Source: src/components/ui/PageTabs.tsx
Horizontal tab bar using {@link animated-tabs}. Content is rendered externally — do not use the content prop on tab objects.
const [activeTab, setActiveTab] = useState('overview');

<PageTabs
  ariaLabel="Overview sections"
  tabs={[
    { title: 'Overview', value: 'overview', icon: LayoutDashboard },
    { title: 'Settings', value: 'settings', icon: Settings },
  ]}
  activeTab={activeTab}
  onTabChange={setActiveTab}
  idBase="overview-tabs"
/>

<div
  id={`overview-tabs-panel-${activeTab}`}
  role="tabpanel"
  aria-labelledby={`overview-tabs-tab-${activeTab}`}
  tabIndex={0}
>
  {activeTab === 'overview' && <OverviewContent />}
  {activeTab === 'settings' && <SettingsContent />}
</div>
For route-driven pages, derive activeTab from the router and have onTabChange push the canonical tab URL. Do not preserve tab selection in shared state across routes.

Props

PropTypeDefaultDescription
tabsTab[]Tab definitions (see Tab type below)
activeTabstringCurrently selected tab value
onTabChange(value: string) => voidCallback when a tab is selected
idBasestring?auto-generatedStable prefix for tab / tabpanel IDs when the panel is rendered externally
ariaLabelstring?'Page sections'Accessible label announced for the tablist
classNamestring?Additional CSS classes

Tab Type

FieldTypeDescription
titleReactNodeTab label
valuestringUnique identifier
iconComponentType<{ className?: string }>?Lucide icon component

SecondarySidebar

Source: src/components/ui/SecondarySidebar.tsx
Left-side navigation panel for tab pages and sub-sections. Supports flat items or grouped items with collapsible sub-menus. Renders a mobile-friendly <Select> dropdown on small screens.
<div className="flex gap-6">
  <SecondarySidebar
    items={[
      { id: 'general', label: 'General', icon: Settings },
      { id: 'billing', label: 'Billing', icon: CreditCard },
    ]}
    activeId={activeSection}
    onSelect={setActiveSection}
    searchable
  />
  <div className="flex-1">{/* section content */}</div>
</div>

Props

PropTypeDefaultDescription
itemsSidebarItem[]?Flat list of navigation items (mutually exclusive with groups)
groupsSidebarGroup[]?Grouped items with collapsible sub-menus
activeIdstringCurrently selected item id
onSelect(id: string) => voidCallback when an item is selected
searchableboolean?falseShow a search input that filters items by label and keywords
searchPlaceholderstring?'Search...'Placeholder for the search input
hasPermission(permission: string) => boolean?Permission gate function. Items with a permission field are hidden when this returns false.
classNamestring?Additional CSS classes

SidebarItem

FieldTypeDescription
idstringUnique identifier
labelstringDisplay text
iconComponentType?Lucide icon
descriptionstring?Subtitle shown below the label
keywordsstring[]?Additional terms for search filtering
permissionstring?Required permission key (checked via hasPermission)
badgestring | number?Badge rendered at the trailing edge

SidebarGroup

FieldTypeDescription
idstringUnique identifier
labelstringGroup heading
iconComponentType?Icon for the group header
itemsSidebarItem[]Items within this group
defaultExpandedboolean?Whether the group starts expanded

Behavior

  • Active state: primary-600 background with white text on the selected item.
  • Mobile: Renders a native <Select> dropdown instead of the sidebar panel.
  • Permission gating: Items with a permission field are filtered out when hasPermission(permission) returns false.
  • Default width: w-64.

Data Display

StatusBadge

Source: src/components/ui/StatusBadge.tsx
Pill-shaped status indicator with icon, label, and themed colours. Use mapDomainStatus() to convert domain-specific strings to one of the 6 base status types.
import { StatusBadge, mapDomainStatus } from '@/components/ui/StatusBadge';

// Direct usage
<StatusBadge status="success" label="Approved" />

// Domain mapping
<StatusBadge status={mapDomainStatus('draft')} label="Draft" dot />

Props

PropTypeDefaultDescription
statusStatusTypeVisual status category (see table below)
labelstringBadge text
iconLucideIcon?Override the default icon for the status
dotboolean?falseRender a small coloured dot instead of an icon
classNamestring?Additional CSS classes

StatusType Values

ValueColourDefault Icon
successemeraldCheckCircle2
warningamberAlertTriangle
errorroseAlertCircle
infoprimaryInfo
pendingslateClock
neutralslateInfo

mapDomainStatus(domainStatus: string): StatusType

Case-insensitive mapping of 70+ domain strings to base StatusType. Falls back to 'neutral' for unknown values. Examples: 'approved'success, 'pending'warning, 'rejected'error, 'draft'pending, 'cancelled'neutral.

ConfidenceBadge

Source: src/components/ui/ConfidenceBadge.tsx
AI confidence score indicator with colour-coded thresholds.
<ConfidenceBadge confidence={92} />
<ConfidenceBadge confidence={45} size="sm" />

Props

PropTypeDefaultDescription
confidencenumberAI confidence score (0–100)
size'sm' | 'md' | 'lg''md'Badge size preset
showLabelboolean?trueShow label text (e.g. “High”) beside the percentage. Hidden at 'sm' size.

Thresholds

RangeLabelColour
85–100Highemerald
70–84Goodprimary
50–69Mediumamber
0–49Lowrose

CitationList

Source: src/components/ui/CitationList.tsx
Renders a list of document citations with optional excerpts and navigation links. Returns null when citations are empty.
<CitationList
  citations={ragResult.citations}
  title="Sources"
  compact
  onDocumentClick={(id, page) => openDocViewer(id, page)}
/>

Props

PropTypeDefaultDescription
citationsDocumentCitation[]Array of citation objects to render
titlestring?'Sources'Heading shown above the list
compactboolean?falseSmaller text and icon sizes
onDocumentClick(documentId: string, page?: number, section?: string) => void?Custom click handler. When omitted, navigates to /documents/:id.

Feedback & Overlays

Source: src/components/ui/Modal.tsx
Animated dialog overlay built on Radix DialogPrimitive with motion/react transitions.
<Modal isOpen={showModal} onClose={() => setShowModal(false)} title="Confirm Action" size="md">
  <p>Are you sure?</p>
  <Modal.Footer>
    <Button variant="outline" onClick={() => setShowModal(false)}>Cancel</Button>
    <Button onClick={handleConfirm}>Confirm</Button>
  </Modal.Footer>
</Modal>

Props

PropTypeDefaultDescription
isOpenbooleanControls visibility
onClose() => voidCalled when the modal is dismissed (overlay click, Escape, or close button)
titleReactNodeModal heading
childrenReactNodeModal body content
footerReactNode?Content rendered in the footer area
size'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full''lg'Width preset (sm = max-w-md, md = max-w-xl, lg = max-w-3xl, xl = max-w-5xl, 2xl = max-w-7xl, full = max-w-[95vw])

BottomSheet

Source: src/components/ui/BottomSheet.tsx
Mobile-friendly bottom sheet with snap points and drag-to-dismiss.
<BottomSheet isOpen={open} onClose={() => setOpen(false)} snapPoints={[40, 90]}>
  <div className="p-4">Sheet content</div>
</BottomSheet>

Props

PropTypeDefaultDescription
isOpenbooleanControls visibility
onClose() => voidCalled on dismiss
childrenReactNodeSheet content
snapPointsnumber[]?[40, 90]Snap heights as viewport-height percentages
initialSnapnumber?0Index into snapPoints for the initial position
onSnapChange(index: number) => void?Called when snap position changes
showHandleboolean?trueShow the drag handle bar
classNamestring?Additional CSS classes

Tooltip

Source: src/components/ui/Tooltip.tsx
Lightweight tooltip wrapper. Uses the custom GrantMaster implementation — not the multi-part shadcn Tooltip pattern.
<Tooltip content="Save changes" side="top" shortcut="Ctrl+S">
  <Button>Save</Button>
</Tooltip>

Props

PropTypeDefaultDescription
childrenReactNodeTrigger element
contentReactNodeTooltip content
side'top' | 'bottom' | 'left' | 'right'?'top'Tooltip placement
align'start' | 'center' | 'end'?'center'Alignment relative to the trigger
delayDurationnumber?200Delay in ms before showing
disabledboolean?falseSuppress the tooltip
shortcutstring?Keyboard shortcut hint (e.g. 'Ctrl+S')
classNamestring?Additional CSS classes on the content

Variants

ComponentPurposeKey Props
ActionTooltipShorthand for icon buttonslabel, shortcut?, side?
HelpTooltipInformational popover with title/descriptiontitle, description, learnMoreUrl?
InfoIconTooltipSelf-contained (i) icon with HelpTooltipSame as HelpTooltip

WarningBanner

Source: src/components/ui/WarningBanner.tsx
Full-width alert banner with type-based colouring.
<WarningBanner
  type="warning"
  title="Budget Alert"
  message="Project spending has reached 80% of the allocated budget."
  details={['Marketing: $4,200 over', 'Travel: approaching limit']}
  dismissible
  onDismiss={() => setDismissed(true)}
/>

Props

PropTypeDefaultDescription
type'warning' | 'error' | 'info' | 'critical'Banner severity
titlestring?Bold heading text
messagestringBody message
detailsstring[]?Bullet-point detail lines
onDismiss() => void?Callback when dismissed
dismissibleboolean?falseShow a dismiss button

Type Colours

TypeBackgroundIcon
warningamberAlertTriangle
errorroseAlertCircle
infoprimaryInfo
criticalrose (darker)ShieldAlert

FloatingActionButton

Source: src/components/ui/FloatingActionButton.tsx
Fixed-position action button, typically for mobile “add” actions.
<FloatingActionButton onClick={handleAdd} icon={Plus} label="New Expense" hideOnScroll />

Props

PropTypeDefaultDescription
onClick() => voidClick handler
iconComponentType?Lucide icon
labelstring?'Add'Button text
positionstring?'bottom-right'Screen position
hideOnScrollboolean?falseAuto-hide when the user scrolls down

Data State

DataStateWrapper

Source: src/components/ui/DataStateWrapper.tsx
Declarative loading / error / empty state container. Wraps content and renders the appropriate fallback UI based on state flags.
<DataStateWrapper
  loading={isLoading}
  error={error}
  isEmpty={items.length === 0}
  onRetry={refetch}
  emptyState={{ icon: Inbox, title: 'No items', description: 'Get started by adding one.' }}
  skeleton={<SkeletonTable rows={5} cols={4} />}
>
  <ItemList items={items} />
</DataStateWrapper>

Props

PropTypeDefaultDescription
loadingbooleanShow loading state
errorError | string | nullShow error state with message
isEmptybooleanShow empty state when no data
onRetry() => void?Retry button handler for error state
skeletonReactNode?Custom loading skeleton
emptyStateEmptyStateConfig?Configuration for the empty state (see below)
renderError(error, onRetry) => ReactNode?Custom error renderer
renderLoading() => ReactNode?Custom loading renderer
renderEmpty() => ReactNode?Custom empty state renderer
childrenReactNodeContent rendered when not loading, no error, and not empty
classNamestring?Outer container class
minLoadingMsnumber?0Minimum time (ms) to show loading state to prevent flicker

EmptyStateConfig

FieldTypeDescription
iconComponentTypeLucide icon
titlestringHeading text
descriptionstringBody text
actionLabelstring?CTA button label
onAction() => void?CTA button handler

EmptyState

Source: src/components/ui/EmptyState.tsx
Standalone empty state display with illustrations, actions, and suggestion chips.
<EmptyState
  icon={FolderOpen}
  title="No projects yet"
  description="Create your first project to get started."
  illustrationType="getting-started"
  actions={[
    { label: 'Create Project', onClick: handleCreate, variant: 'default' },
    { label: 'Import', onClick: handleImport, variant: 'outline' },
  ]}
  suggestions={[
    { label: 'View templates', onClick: openTemplates },
  ]}
/>

Props

PropTypeDefaultDescription
iconComponentTypePrimary icon
titlestringHeading text
descriptionstringBody text
actionLabelstring?Single CTA button label (shorthand for one action)
onAction() => void?Single CTA button handler
actionsEmptyStateAction[]?Multiple action buttons
suggestionsEmptyStateSuggestion[]?Suggestion chip links
compactboolean?falseSmaller layout for inline contexts
illustrationReactNode?Custom illustration element
illustrationTypeIllustrationType?Built-in SVG illustration key
classNamestring?Additional CSS classes

IllustrationType

'no-data' | 'no-results' | 'empty-folder' | 'getting-started' | 'error' | 'no-access'

ErrorBoundary

Source: src/components/ui/ErrorBoundary.tsx
React class component that catches render errors, reports to Sentry, and shows a recovery UI.
<ErrorBoundary context="User Profile Form" onReset={handleReset}>
  <UserProfileForm />
</ErrorBoundary>

Props

PropTypeDefaultDescription
childrenReactNodeComponent tree to protect
fallbackReactNode?Custom fallback UI (overrides the built-in error card)
onError(error: Error, errorInfo: ErrorInfo) => void?Additional error callback (Sentry reporting is automatic)
contextstring?Label sent to Sentry and shown in the error card title
showDetailsboolean?falseShow error details in production (always shown in dev)
onReset() => void?Custom handler for the “Try Again” button

Behavior

  • Sentry integration: Automatically captures the exception with context as a tag.
  • Recovery: “Try Again” clears the error state and re-renders children. Shows a warning if the error recurs.
  • Development mode: Always shows error details and component stack.

Forms

FormSection

Source: src/components/ui/FormComponents.tsx
Groups related form fields under a heading with optional description.
<FormSection title="Basic Information" description="Required fields for project setup">
  <FormField label="Name" required error={errors.name}>
    <Input {...register('name')} />
  </FormField>
</FormSection>

Props

PropTypeDefaultDescription
titlestringSection heading
descriptionstring?Subtitle text
childrenReactNodeForm fields
classNamestring?Additional CSS classes

FormField

Source: src/components/ui/FormComponents.tsx
Labelled wrapper for a single form input with error and hint display.
<FormField label="Email" required error={errors.email} hint="We'll never share your email">
  <Input type="email" {...register('email')} />
</FormField>

Props

PropTypeDefaultDescription
labelstringField label text
requiredboolean?falseShow required asterisk
errorstring?Error message (shown in red below the input)
hintstring?Help text below the input
childrenReactNodeThe input element
classNamestring?Additional CSS classes
fullWidthboolean?falseExpand to full container width
idstring?HTML id for the label htmlFor

FormActions

Source: src/components/ui/FormComponents.tsx
Action button container for form submit/cancel buttons.
<FormActions align="right">
  <Button variant="outline" onClick={handleCancel}>Cancel</Button>
  <Button type="submit" isLoading={isSubmitting}>Save</Button>
</FormActions>

Props

PropTypeDefaultDescription
childrenReactNodeAction buttons
align'left' | 'right' | 'center' | 'between''right'Button alignment
classNamestring?Additional CSS classes

SearchFilterBar

Source: src/components/ui/SearchFilterBar.tsx
Search input with built-in debounce, filter slot, and action slot.
<SearchFilterBar
  searchValue={searchTerm}
  onSearchChange={setSearchTerm}
  searchPlaceholder="Search projects..."
  debounceMs={300}
  filters={<Select value={status} onValueChange={setStatus}>...</Select>}
  actions={<Button onClick={handleAdd}><Plus className="w-4 h-4 mr-2" />Add</Button>}
/>

Props

PropTypeDefaultDescription
searchValuestringControlled search value
onSearchChange(value: string) => voidDebounced search callback
searchPlaceholderstring?'Search...'Input placeholder
debounceMsnumber?300Debounce delay (0 to disable)
filtersReactNode?Filter controls rendered beside the input
actionsReactNode?Action buttons at the trailing edge
classNamestring?Additional CSS classes

Behavior

  • Immediate visual feedback: The input updates instantly; only onSearchChange is debounced.
  • Clear button: Fires onSearchChange('') immediately (no debounce).

Lists & Animation

VirtualList<T>

Source: src/components/ui/VirtualList.tsx
Virtualized scrollable list for rendering large datasets efficiently. Built on @tanstack/react-virtual.
<VirtualList
  items={filteredItems}
  height={600}
  estimateSize={() => 64}
  renderItem={(item, index) => <ItemRow key={item.id} item={item} />}
  gap={8}
  loading={isLoading}
  renderSkeleton={() => <SkeletonRow />}
  loadingItemCount={10}
/>

Props

PropTypeDefaultDescription
itemsT[]Data array
heightnumberContainer height in pixels
estimateSize(index: number) => numberEstimated row height function
renderItem(item: T, index: number) => ReactNodeRow renderer
overscannumber?5Number of items to render outside the visible area
measureElementboolean?Enable dynamic measurement
classNamestring?Container CSS classes
contentClassNamestring?Inner scroll content CSS classes
onScroll(offset: number) => void?Scroll position callback
getItemKey(index: number) => string | number?Stable key function
gapnumber?Gap between items in pixels
loadingboolean?Show loading skeletons instead of items
loadingItemCountnumber?Number of skeleton rows
renderSkeleton() => ReactNode?Skeleton row renderer
renderEmpty() => ReactNode?Empty state renderer
horizontalboolean?falseHorizontal scroll mode
widthnumber?Container width (for horizontal mode)
aria-labelstring?Accessible label

StaggeredList

Source: src/components/ui/StaggeredList.tsx
Animated list that staggers child entrance animations using motion/react.
<StaggeredList direction="up" staggerDelay={0.05}>
  {items.map(item => (
    <StaggeredItem key={item.id}>
      <ItemCard item={item} />
    </StaggeredItem>
  ))}
</StaggeredList>

Props (StaggeredList)

PropTypeDefaultDescription
childrenReactNodeStaggeredItem children
classNamestring?Container CSS classes
directionStaggerDirection?'up'Animation direction
staggerDelaynumber?0.05Delay between items (seconds)
durationnumber?0.3Animation duration (seconds)
initialDelaynumber?0Delay before the first animation
isLoadingboolean?Show loading skeletons
loadingSkeletonReactNode?Skeleton element template
skeletonCountnumber?Number of skeleton rows
animateOnExitboolean?falseAnimate items when they leave
variantsVariants?Custom motion/react variants
disabledboolean?falseDisable animations
listKeystring?Key to reset animations when content changes

StaggerDirection

'up' | 'down' | 'left' | 'right' | 'fade' | 'scale'

Props (StaggeredItem)

PropTypeDefaultDescription
childrenReactNodeItem content
classNamestring?Additional CSS classes
indexnumber?Override auto-calculated index
variantsVariants?Custom motion/react variants
motionPropsMotionProps?Additional motion/react props

Source: src/components/ui/Breadcrumbs.tsx
Auto-generated breadcrumb trail derived from the current URL path via react-router-dom. UUID path segments are automatically hidden. Route labels are resolved from routeLabels then title-cased as a fallback.
<Breadcrumbs />  // no props required — reads from useLocation()
Always renders a home icon as the first crumb. Renders nothing when on the root / path.

BackButton

Source: src/components/ui/BackButton.tsx
A ghost variant button that calls navigate(-1). Use in page headers when drill-down navigation requires an explicit back affordance.
<BackButton />
<BackButton label="Back to Projects" />

Data Display

CardVariants

Source: src/components/ui/CardVariants.tsx
Utility object exporting pre-composed Tailwind class strings for common card surface styles. Avoids repeating bg-white rounded-lg border border-slate-200 dark:bg-slate-900 dark:border-slate-800 across every component.
import { CardVariants } from '@/components/ui/CardVariants';

<div className={CardVariants.default}>...</div>
<div className={CardVariants.elevated}>...</div>
<div className={CardVariants.flat}>...</div>
Use CardVariants for simple styling presets. Use the composable Card/CardHeader/CardContent pattern from card.tsx for structured layouts with headers and footers.

MetricCard

Source: src/components/ui/MetricCard.tsx
Displays a single KPI metric with an icon, label, value, optional trend indicator, and a semantic colour tone. Use in dashboards and summary panels instead of building metric cards inline.
<MetricCard
  label="Active Projects"
  value={12}
  icon={FolderOpen}
  tone="info"
  trend={{ direction: 'up', value: '3 this month' }}
/>

Props

PropTypeDefaultDescription
labelstringMetric name
valuestring | numberDisplayed value
iconLucideIconIcon component
toneMetricTone'neutral'Colour tone: neutral | info | success | warning | danger
trend{ direction: 'up' | 'down' | 'flat'; value: string }?Optional trend label
loadingboolean?falseShow skeleton
classNamestring?Additional CSS classes

AnimatedIcon

Source: src/components/ui/AnimatedIcon.tsx
Wraps any LucideIcon with a configurable motion/react entrance or pulse animation. Use for status indicators and empty state illustrations.
<AnimatedIcon icon={CheckCircle} animation="bounce" size="lg" tone="success" />

Props

PropTypeDefaultDescription
iconLucideIconIcon to render
animation'bounce' | 'pulse' | 'spin' | 'none''none'Animation variant
size'sm' | 'md' | 'lg' | 'xl''md'Icon size
toneMetricTone'neutral'Colour tone
classNamestring?Additional CSS classes

Canonical Event Status

CanonicalFreshnessBadge

Source: src/components/ui/CanonicalFreshnessBadge.tsx
Displays the freshness state of a canonical status projection — fresh (green), stale (amber warning), or unknown. Optionally renders a staleActionLabel button to trigger a refresh.
<CanonicalFreshnessBadge
  freshness={projection.freshness}
  staleActionLabel="Refresh"
  onStaleAction={handleRefresh}
/>

Props

PropTypeDefaultDescription
freshnessCanonicalProjectionFreshnessFreshness object from shared/events
staleActionLabelstring?Button label shown when stale
onStaleAction() => void?Called when stale action button clicked

CanonicalProjectionHealthPanel

Source: src/components/ui/CanonicalProjectionHealthPanel.tsx
Displays a debug/admin panel summarising the health of all canonical status projections: total count, stale count, error count, and last-checked timestamp. Use in SuperAdmin and developer tooling pages.
<CanonicalProjectionHealthPanel health={canonicalHealth} />

Props

PropTypeDefaultDescription
healthCanonicalProjectionHealthHealth summary from shared/events

Utilities

AsyncBoundary

Source: src/components/ui/AsyncBoundary.tsx
Composes React Suspense + ErrorBoundary into a single boundary component. Wrap any async/lazy component to handle both loading and error states declaratively.
<AsyncBoundary
  fallback={<SkeletonLoader rows={3} />}
  errorFallback={<p>Failed to load.</p>}
>
  <LazyComponent />
</AsyncBoundary>

Props

PropTypeDefaultDescription
childrenReactNodeContent to render
fallbackReactNode?<LoadingScreen />Suspense fallback
errorFallbackReactNode?Default error UIError boundary fallback

RouteErrorBoundary

Source: src/components/ui/RouteErrorBoundary.tsx
React Router v6 error boundary component used as the errorElement on route definitions. Catches loader/action errors and renders a user-friendly error page with a “go back” action.
// In routeConfig.tsx:
{ path: '/projects', element: <Projects />, errorElement: <RouteErrorBoundary /> }

ScrollToTop

Source: src/components/ui/ScrollToTop.tsx
Effect-only component that scrolls window to (0, 0) on every route change. Mount once inside the router, outside any <Routes>.
<Router>
  <ScrollToTop />
  <Routes>...</Routes>
</Router>
No props.

LoadingScreen

Source: src/components/ui/LoadingScreen.tsx
Full-page centred loading indicator. Used as the default Suspense fallback for lazy-loaded routes and as the AsyncBoundary default.
<LoadingScreen message="Loading projects…" />

Props

PropTypeDefaultDescription
messagestring?'Loading…'Descriptive loading text

KeyboardShortcutsModal

Source: src/components/ui/KeyboardShortcutsModal.tsx
Modal listing all registered keyboard shortcuts from the ActionRegistry. Opened via ⌘? / Ctrl+? by the command palette feature.
<KeyboardShortcutsModal open={open} onOpenChange={setOpen} />

Props

PropTypeDefaultDescription
openbooleanModal open state
onOpenChange(open: boolean) => voidState change handler

PremiumTabs

Source: src/components/ui/PremiumTabs.tsx
Tab bar variant that locks individual tabs behind subscription tier requirements. Locked tabs render a 🔒 icon and redirect to the billing page on click instead of switching content.
<PremiumTabs
  tabs={[
    { label: 'Overview', value: 'overview' },
    { label: 'Intelligence', value: 'intelligence', requiredTier: 'Professional' },
  ]}
  value={activeTab}
  onValueChange={setActiveTab}
/>

Props

PropTypeDefaultDescription
tabsPremiumTab[]Tab definitions with optional requiredTier
valuestringActive tab value
onValueChange(value: string) => voidTab change handler