---
name: dashboard-patterns
description: Dashboard UI patterns with widget composition, real-time data updates, responsive grid layouts, and data tables for React applications. Use when building dashboards, widgets, or data tables.
tags: [dashboard, widgets, data-grid, real-time, layout, admin, tanstack-table, sse]
context: fork
agent: frontend-ui-developer
version: 1.0.0
author: OrchestKit
user-invocable: false
---
# Dashboard Patterns
Dashboard UI patterns for building admin panels, analytics dashboards, and data-driven interfaces with React.
## Layout Patterns
### Responsive Dashboard Grid
```tsx
function DashboardLayout({ children }: { children: React.ReactNode }) {
return (
);
}
function DashboardGrid() {
return (
);
}
```
## Widget Components
### Stat Card Widget
```tsx
import { TrendingUp, TrendingDown } from 'lucide-react';
interface StatCardProps {
title: string;
value: string | number;
change?: string;
changeType?: 'positive' | 'negative' | 'neutral';
icon?: React.ReactNode;
}
function StatCard({ title, value, change, changeType = 'neutral', icon }: StatCardProps) {
return (
{value}
{change && (
{changeType === 'positive' && }
{changeType === 'negative' && }
{change}
)}
);
}
```
### Widget Registry Pattern
```tsx
type WidgetType = 'stat' | 'chart' | 'table' | 'list';
interface WidgetConfig {
id: string;
type: WidgetType;
title: string;
span?: number;
props: Record;
}
const widgetRegistry: Record> = {
stat: StatCard,
chart: ChartCard,
table: DataTable,
list: ListWidget,
};
function DashboardWidget({ config }: { config: WidgetConfig }) {
const Component = widgetRegistry[config.type];
if (!Component) return null;
return (
);
}
```
## Real-Time Data Patterns
### TanStack Query + SSE
```tsx
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useEffect } from 'react';
function useRealtimeMetrics() {
const queryClient = useQueryClient();
const { data, isLoading } = useQuery({
queryKey: ['metrics'],
queryFn: fetchMetrics,
});
useEffect(() => {
const eventSource = new EventSource('/api/metrics/stream');
eventSource.onmessage = (event) => {
const update = JSON.parse(event.data);
queryClient.setQueryData(['metrics'], (old: Metrics | undefined) => ({
...old,
...update,
}));
};
eventSource.onerror = () => {
eventSource.close();
queryClient.invalidateQueries({ queryKey: ['metrics'] });
};
return () => eventSource.close();
}, [queryClient]);
return { data, isLoading };
}
```
## Data Table (TanStack Table)
```tsx
import {
useReactTable,
getCoreRowModel,
getSortedRowModel,
getFilteredRowModel,
getPaginationRowModel,
flexRender,
type ColumnDef,
type SortingState,
} from '@tanstack/react-table';
const columns: ColumnDef[] = [
{ accessorKey: 'id', header: 'Order ID' },
{ accessorKey: 'customer', header: 'Customer' },
{ accessorKey: 'amount', header: 'Amount', cell: ({ getValue }) => `$${getValue().toLocaleString()}` },
{ accessorKey: 'status', header: 'Status', cell: ({ getValue }) => },
];
function OrdersTable({ data }: { data: Order[] }) {
const [sorting, setSorting] = useState([]);
const [globalFilter, setGlobalFilter] = useState('');
const table = useReactTable({
data,
columns,
state: { sorting, globalFilter },
onSortingChange: setSorting,
onGlobalFilterChange: setGlobalFilter,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
});
return (
);
}
```
## Skeleton Loading
```tsx
function DashboardSkeleton() {
return (
{[...Array(4)].map((_, i) => (
))}
{[...Array(5)].map((_, i) => (
))}
);
}
```
## Anti-Patterns (FORBIDDEN)
```tsx
// NEVER: Fetch data in every widget independently (duplicated queries)
// NEVER: Re-render entire dashboard on single metric change
// NEVER: Hardcoded dashboard layout (not responsive)
// NEVER: Polling without intervals (infinite loop)
// NEVER: Missing loading states (flash of empty state)
// NEVER: Real-time updates without debounce (100 re-renders/sec)
```
## Key Decisions
| Decision | Recommendation |
|----------|----------------|
| Layout | **CSS Grid** for 2D dashboard layouts |
| Real-time | **SSE** for server->client, **WebSocket** for bidirectional |
| Data table | **TanStack Table** for features |
| State | **TanStack Query** with granular keys |
| Loading | **Skeleton** for content areas |
## Related Skills
- `recharts-patterns` - Chart components for dashboards
- `tanstack-query-advanced` - Data fetching patterns
- `streaming-api-patterns` - SSE and WebSocket implementation