Skip to Content
ContributeFrontendComponent Library

Component Library

This document describes the reusable component conventions in the Rhesis frontend. There is no generic design-system wrapper library (no custom Button/TextField/Select/Card) — components either use MUI directly or wrap it under a Base* prefix for shared behavior (pagination, loading states, action buttons).

Component Organization

Component Organization
└── 
src/components
    ├── 
common# Base* wrappers and reusable components (flat directory, ~70 files)
    ├── 
layout# AppShell and layout primitives
    ├── 
navigation# Sidebar and nav items
    ├── 
providers# Context providers (ThemeProvider, etc.)
    ├── 
auth# AuthForm, AuthPageShell
    └── 
tasks / tests / comments / onboarding# Feature-specific components

Layout

AppShell

Root two-column layout (src/components/layout/AppShell.tsx) — a CSS grid of sidebar + content, with collapse state shared via SidebarCollapseContext so children don’t need prop-drilling:

AppShell.tsx
interface AppShellProps {
children: React.ReactNode;
sidebar: React.ReactNode;   // typically <Sidebar />
topBar?: React.ReactNode;
}

src/components/navigation/Sidebar.tsx reads navigation items from useNavigationItems(), collapse state from useSidebarCollapse() (exported by AppShell), and theme mode from ColorModeContext — it takes no isOpen/onToggle props.

Common Components (src/components/common/)

The directory is flat (no form//data-display/ subfolders). Notable Base* components:

ComponentPurpose
BaseDataGridWraps MUI X DataGrid — columns, rows, actionButtons, toolbar, density, row click
BaseTableSimpler tabular display — columns, data, actionButtons, row highlighting
BaseDrawerSide-panel form/detail drawer — open, onClose, onSave, onDelete, loading/error state
BaseLineChart / BasePieChart / BaseScatterChartRecharts wrappers with theme-aware color palettes
BaseChartsGridLayout grid for arranging multiple chart components
BaseTag, BaseFreesoloAutocomplete, BaseWorkflowSectionSmaller shared UI primitives
ActionBarToolbar of action buttons above lists/grids
CanAffordance primitives — can(), useCan(), <Can> (see apps/frontend/AGENTS.md)
EntityCard and other entity-specific cardsFeature-specific display cards (no generic Card wrapper exists)

There is no LineChart/BarChart/FlowChart generic component — React Flow (reactflow) is used directly in one place, SpanGraphView under the traces feature, not as a reusable common component.

BaseDataGrid props (abridged)

BaseDataGrid.tsx
interface BaseDataGridProps {
columns: GridColDef[];
rows: GridRowModel[];
title?: string;
loading?: boolean;
getRowId?: (row: GridRowModel) => string | number;
showToolbar?: boolean;
onRowClick?: (params: GridRowParams) => void;
density?: GridDensity;
disableMultipleRowSelection?: boolean;
actionButtons?: {
    label: string;
    onClick?: () => void;
    href?: string;
    variant?: 'text' | 'outlined' | 'contained'; // MUI's own variants, not a custom enum
    color?: 'inherit' | 'primary' | 'secondary' | 'success' | 'error' | 'info' | 'warning';
}[];
}

BaseDrawer props

BaseDrawer.tsx
interface BaseDrawerProps {
open: boolean;
onClose: () => void;
title?: string;
children: React.ReactNode;
loading?: boolean;
onSave?: () => void;
saveDisabled?: boolean;
error?: string;
onDelete?: () => void;
}

Using Components

MyPage.tsx
import { BaseDataGrid } from '@/components/common/BaseDataGrid';
import { AppShell } from '@/components/layout/AppShell';
import { Sidebar } from '@/components/navigation/Sidebar';

export default function MyPage() {
return (
    <AppShell sidebar={<Sidebar />}>
      <BaseDataGrid columns={columns} rows={rows} title="My Data" />
    </AppShell>
);
}

Component Best Practices

  1. Use TypeScript props interfaces for every component
  2. Prefer composing MUI directly over introducing new generic wrappers — reach for a Base* component only when the same cross-cutting behavior (pagination, loading, action buttons) repeats across features
  3. Gate on affordances, not ad-hoc ownership checks — use can/useCan/<Can> (see apps/frontend/AGENTS.md)
  4. Accessibility: components should meet WCAG standards
  5. Responsive design: components should work across screen sizes

Creating New Components

  1. Place them in the appropriate directory based on purpose (common/ for cross-feature reuse, otherwise the relevant feature directory)
  2. Define a clear TypeScript props interface
  3. Add test cases alongside the component (see Testing)
  4. Consider reusability, but don’t generalize a one-off into a Base* component prematurely