Skip to main content

:::warning AUTO-GENERATED — do not edit This page is generated from the MCP server snapshot content/guide-mcp.json. Edit the source MCP server (not this file), then run npm run generate. :::

Component Catalog

ComponentDescription
PageLayoutStandard Rystad page layout with top navbar. Uses shadcn components for structure.
DataTableGeneric data table using TanStack Table with shadcn Table primitives. Supports sorting, pagination.
ChartCardCard wrapper for charts using shadcn Card compound component with optional toolbar.
FilterPanelCollapsible filter panel using shadcn Collapsible and Button components.
KPICardKey performance indicator card using shadcn Card with trend indicator.

PageLayout

Standard Rystad page layout with top navbar. Uses shadcn components for structure.

{
"name": "PageLayout",
"description": "Standard Rystad page layout with top navbar. Uses shadcn components for structure.",
"props": {
"title": "string — Page title displayed in the header",
"children": "ReactNode — Main content area"
},
"shadcnDeps": [
"button",
"skeleton"
],
"installCommand": "npx shadcn@latest add button skeleton",
"code": "import type { ReactNode } from \"react\";\nimport { useAuth } from \"@rystad/auth\";\nimport { Button } from \"@/components/ui/button\";\n\ntype PageLayoutProps = {\n title: string;\n children: ReactNode;\n};\n\nexport function PageLayout({ title, children }: PageLayoutProps) {\n const { user, logout } = useAuth();\n\n return (\n <div className=\"flex min-h-screen flex-col\">\n <header className=\"flex h-14 items-center justify-between border-b border-border bg-card px-6 sticky top-0\">\n <h1 className=\"text-lg font-semibold text-foreground\">{title}</h1>\n <div className=\"flex items-center gap-3\">\n <span className=\"text-sm text-muted-foreground\">{user?.name}</span>\n <Button variant=\"ghost\" size=\"sm\" onClick={logout}>\n Log out\n </Button>\n </div>\n </header>\n <main className=\"flex-1 p-6\">{children}</main>\n </div>\n );\n}"
}

DataTable

Generic data table using TanStack Table with shadcn Table primitives. Supports sorting, pagination.

{
"name": "DataTable",
"description": "Generic data table using TanStack Table with shadcn Table primitives. Supports sorting, pagination.",
"props": {
"columns": "ColumnDef<TData, TValue>[] — TanStack Table column definitions",
"data": "TData[] — Array of row data",
"tableTitle": "string? — Optional title above the table"
},
"shadcnDeps": [
"table"
],
"installCommand": "npx shadcn@latest add table",
"code": "import type { ColumnDef } from \"@tanstack/react-table\";\nimport {\n flexRender,\n getCoreRowModel,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/components/ui/table\";\n\ntype DataTableProps<TData, TValue> = {\n columns: ColumnDef<TData, TValue>[];\n data: TData[];\n tableTitle?: string;\n};\n\nexport function DataTable<TData, TValue>({\n columns,\n data,\n tableTitle,\n}: DataTableProps<TData, TValue>) {\n const table = useReactTable({\n data,\n columns,\n getCoreRowModel: getCoreRowModel(),\n });\n\n return (\n <div>\n {tableTitle && (\n <h3 className=\"mb-4 text-lg font-semibold\">{tableTitle}</h3>\n )}\n <div className=\"rounded-md border border-border\">\n <Table>\n <TableHeader>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n {headerGroup.headers.map((header) => (\n <TableHead key={header.id}>\n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n </TableHead>\n ))}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n {table.getRowModel().rows.length ? (\n table.getRowModel().rows.map((row) => (\n <TableRow key={row.id}>\n {row.getVisibleCells().map((cell) => (\n <TableCell key={cell.id}>\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </TableCell>\n ))}\n </TableRow>\n ))\n ) : (\n <TableRow>\n <TableCell colSpan={columns.length} className=\"h-24 text-center text-muted-foreground\">\n No results.\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </div>\n </div>\n );\n}"
}

ChartCard

Card wrapper for charts using shadcn Card compound component with optional toolbar.

{
"name": "ChartCard",
"description": "Card wrapper for charts using shadcn Card compound component with optional toolbar.",
"props": {
"title": "string — Chart title",
"subtitle": "string? — Optional subtitle",
"children": "ReactNode — Chart component (Recharts wrapped in ChartContainer)",
"toolbar": "ReactNode? — Optional toolbar actions"
},
"shadcnDeps": [
"card"
],
"installCommand": "npx shadcn@latest add card",
"code": "import type { ReactNode } from \"react\";\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\";\n\ntype ChartCardProps = {\n title: string;\n subtitle?: string;\n children: ReactNode;\n toolbar?: ReactNode;\n};\n\nexport function ChartCard({ title, subtitle, children, toolbar }: ChartCardProps) {\n return (\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between\">\n <div>\n <CardTitle>{title}</CardTitle>\n {subtitle && <CardDescription>{subtitle}</CardDescription>}\n </div>\n {toolbar && <div className=\"flex items-center gap-2\">{toolbar}</div>}\n </CardHeader>\n <CardContent>{children}</CardContent>\n </Card>\n );\n}"
}

FilterPanel

Collapsible filter panel using shadcn Collapsible and Button components.

{
"name": "FilterPanel",
"description": "Collapsible filter panel using shadcn Collapsible and Button components.",
"props": {
"children": "ReactNode — Filter form controls",
"onApply": "() => void — Called when filters are applied",
"onReset": "() => void — Called when filters are reset",
"defaultOpen": "boolean? — Whether panel starts open (default: true)"
},
"shadcnDeps": [
"collapsible",
"button"
],
"installCommand": "npx shadcn@latest add collapsible button",
"code": "import { useState, type ReactNode } from \"react\";\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from \"@/components/ui/collapsible\";\nimport { Button } from \"@/components/ui/button\";\nimport { ChevronsUpDown } from \"lucide-react\";\n\ntype FilterPanelProps = {\n children: ReactNode;\n onApply: () => void;\n onReset: () => void;\n defaultOpen?: boolean;\n};\n\nexport function FilterPanel({ children, onApply, onReset, defaultOpen = true }: FilterPanelProps) {\n const [isOpen, setIsOpen] = useState(defaultOpen);\n\n return (\n <Collapsible open={isOpen} onOpenChange={setIsOpen} className=\"rounded-lg border border-border bg-card p-4\">\n <CollapsibleTrigger asChild>\n <Button variant=\"ghost\" className=\"flex w-full items-center justify-between\">\n <span className=\"text-sm font-medium\">Filters</span>\n <ChevronsUpDown className=\"h-4 w-4\" />\n </Button>\n </CollapsibleTrigger>\n <CollapsibleContent className=\"mt-4 space-y-4\">\n <div className=\"space-y-3\">{children}</div>\n <div className=\"flex items-center gap-2 pt-2\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onReset}>\n Reset\n </Button>\n <Button size=\"sm\" onClick={onApply}>\n Apply\n </Button>\n </div>\n </CollapsibleContent>\n </Collapsible>\n );\n}"
}

KPICard

Key performance indicator card using shadcn Card with trend indicator.

{
"name": "KPICard",
"description": "Key performance indicator card using shadcn Card with trend indicator.",
"props": {
"label": "string — KPI label",
"value": "string | number — Current value",
"unit": "string? — Unit of measurement",
"trend": "{ direction: 'up' | 'down' | 'flat'; percentage: number }? — Trend indicator"
},
"shadcnDeps": [
"card"
],
"installCommand": "npx shadcn@latest add card",
"code": "import { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { cn } from \"@/lib/utils\";\n\ntype KPICardProps = {\n label: string;\n value: string | number;\n unit?: string;\n trend?: { direction: \"up\" | \"down\" | \"flat\"; percentage: number };\n};\n\nexport function KPICard({ label, value, unit, trend }: KPICardProps) {\n return (\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium text-muted-foreground\">{label}</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"flex items-baseline gap-1\">\n <span className=\"text-2xl font-bold\">{value}</span>\n {unit && <span className=\"text-sm text-muted-foreground\">{unit}</span>}\n </div>\n {trend && (\n <p\n className={cn(\n \"mt-1 text-xs\",\n trend.direction === \"up\" && \"text-green-600\",\n trend.direction === \"down\" && \"text-red-600\",\n trend.direction === \"flat\" && \"text-muted-foreground\",\n )}\n >\n {trend.direction === \"up\" ? \"↑\" : trend.direction === \"down\" ? \"↓\" : \"→\"}{\" \"}\n {trend.percentage}%\n </p>\n )}\n </CardContent>\n </Card>\n );\n}"
}