dashboard-patterns

安装量: 121
排名: #7066

安装

npx skills add https://github.com/yonatangross/orchestkit --skill dashboard-patterns

Dashboard Patterns

Dashboard UI patterns for building admin panels, analytics dashboards, and data-driven interfaces with React.

Layout Patterns Responsive Dashboard Grid function DashboardLayout({ children }: { children: React.ReactNode }) { return (

{children}
); }

function DashboardGrid() { return (

); }

Widget Components Stat Card Widget 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 (

{title}

{icon &&
{icon}
}

{value}

{change && ( {changeType === 'positive' && } {changeType === 'negative' && } {change} )}
); }

Widget Registry Pattern 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 (

span ${config.span} : undefined }}>
); }

Real-Time Data Patterns TanStack Query + SSE 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) 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<number>().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 (

setGlobalFilter(e.target.value)} placeholder="Search orders..." className="mb-4 rounded border px-3 py-2" /> {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( ))} ))} {table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( ))} ))}
{flexRender(header.column.columnDef.header, header.getContext())} {header.column.getIsSorted() === 'asc' && ' ↑'} {header.column.getIsSorted() === 'desc' && ' ↓'}
{flexRender(cell.column.columnDef.cell, cell.getContext())}
Page {table.getState().pagination.pageIndex + 1} of {table.getPageCount()}
); }

Skeleton Loading function DashboardSkeleton() { return (

{[...Array(4)].map((, i) => (
))}
{[...Array(5)].map((, i) => (
))}
); }

Anti-Patterns (FORBIDDEN) // 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

返回排行榜