Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af48bd2fa0 | ||
|
|
592b60c5fe |
@@ -104,6 +104,10 @@ import { GlobalFilterProvider, useGlobalFilters } from '@cameleer/design-system'
|
||||
// Utils
|
||||
import { hashColor } from '@cameleer/design-system'
|
||||
|
||||
// Recharts theme (for advanced charts — treemap, radar, heatmap, etc.)
|
||||
import { rechartsTheme, CHART_COLORS } from '@cameleer/design-system'
|
||||
import type { ChartSeries, DataPoint } from '@cameleer/design-system'
|
||||
|
||||
// Styles (once, at app root)
|
||||
import '@cameleer/design-system/style.css'
|
||||
```
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
- Time series → **LineChart**, **AreaChart**
|
||||
- Categorical comparison → **BarChart**
|
||||
- Inline trend → **Sparkline**
|
||||
- Advanced charts (treemap, radar, heatmap, pie, etc.) → **Recharts** with `rechartsTheme` (see [Charting Strategy](#charting-strategy))
|
||||
- Event log → **EventFeed**
|
||||
- Processing pipeline (Gantt view) → **ProcessorTimeline**
|
||||
- Processing pipeline (flow diagram) → **RouteFlow**
|
||||
@@ -160,6 +161,53 @@ StatCard strip (top, recalculates per scope)
|
||||
URL-driven progressive filtering: /agents → /agents/:appId → /agents/:appId/:instanceId
|
||||
```
|
||||
|
||||
## Charting Strategy
|
||||
|
||||
The design system includes built-in **AreaChart**, **BarChart**, **LineChart**, and **Sparkline** components for standard use cases. For advanced chart types (treemap, radar, heatmap, pie, sankey, etc.), consuming apps should use **Recharts** directly with the design system's theme preset for visual consistency.
|
||||
|
||||
**Recharts is the app's dependency, not the design system's.** The design system only exports a theme config object.
|
||||
|
||||
### Setup in consuming app
|
||||
|
||||
```bash
|
||||
npm install recharts
|
||||
```
|
||||
|
||||
### Usage with theme preset
|
||||
|
||||
```tsx
|
||||
import { rechartsTheme, CHART_COLORS } from '@cameleer/design-system'
|
||||
import {
|
||||
ResponsiveContainer, LineChart, Line,
|
||||
CartesianGrid, XAxis, YAxis, Tooltip, Legend,
|
||||
} from 'recharts'
|
||||
|
||||
<ResponsiveContainer width="100%" height={300}>
|
||||
<LineChart data={data}>
|
||||
<CartesianGrid {...rechartsTheme.cartesianGrid} />
|
||||
<XAxis dataKey="name" {...rechartsTheme.xAxis} />
|
||||
<YAxis {...rechartsTheme.yAxis} />
|
||||
<Tooltip {...rechartsTheme.tooltip} />
|
||||
<Legend {...rechartsTheme.legend} />
|
||||
<Line dataKey="value" stroke={CHART_COLORS[0]} strokeWidth={2} dot={false} />
|
||||
<Line dataKey="other" stroke={CHART_COLORS[1]} strokeWidth={2} dot={false} />
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
```
|
||||
|
||||
### Exports
|
||||
|
||||
| Export | Description |
|
||||
|--------|-------------|
|
||||
| `rechartsTheme.cartesianGrid` | Dashed gridlines, subtle stroke |
|
||||
| `rechartsTheme.xAxis` | Mono font axis ticks, subtle color |
|
||||
| `rechartsTheme.yAxis` | Mono font axis ticks, no axis line |
|
||||
| `rechartsTheme.tooltip` | Surface bg, border, shadow, monospace values |
|
||||
| `rechartsTheme.legend` | Matching text size and color |
|
||||
| `rechartsTheme.colors` | The 8 `CHART_COLORS` (CSS variables with light/dark support) |
|
||||
| `CHART_COLORS` | Array of `var(--chart-1)` through `var(--chart-8)` |
|
||||
| `ChartSeries` / `DataPoint` | Type interfaces for chart data |
|
||||
|
||||
## Component Index
|
||||
|
||||
| Component | Layer | When to use |
|
||||
|
||||
@@ -41,3 +41,7 @@ export { SplitPane } from './SplitPane/SplitPane'
|
||||
export { Tabs } from './Tabs/Tabs'
|
||||
export { ToastProvider, useToast } from './Toast/Toast'
|
||||
export { TreeView } from './TreeView/TreeView'
|
||||
|
||||
// Chart utilities for consumers using Recharts or custom charts
|
||||
export { CHART_COLORS } from './_chart-utils'
|
||||
export type { ChartSeries, DataPoint } from './_chart-utils'
|
||||
|
||||
@@ -11,3 +11,4 @@ export { BreadcrumbProvider, useBreadcrumb } from './providers/BreadcrumbProvide
|
||||
export type { BreadcrumbItem } from './providers/BreadcrumbProvider'
|
||||
export * from './utils/hashColor'
|
||||
export * from './utils/timePresets'
|
||||
export * from './utils/rechartsTheme'
|
||||
|
||||
@@ -323,11 +323,9 @@ export function Sidebar({ apps, className, onNavigate }: SidebarProps) {
|
||||
const starredRouteStats = starredItems.filter((i) => i.type === 'routestat')
|
||||
const hasStarred = starredItems.length > 0
|
||||
|
||||
// For exchange detail pages, use the reveal path for sidebar selection so
|
||||
// the parent route is highlighted (exchanges have no sidebar entry of their own)
|
||||
const effectiveSelectedPath = location.pathname.startsWith('/exchanges/') && sidebarRevealPath
|
||||
? sidebarRevealPath
|
||||
: location.pathname
|
||||
// When a sidebar reveal path is provided (e.g. via Cmd-K navigation),
|
||||
// use it for sidebar selection so the correct item is highlighted
|
||||
const effectiveSelectedPath = sidebarRevealPath ?? location.pathname
|
||||
|
||||
return (
|
||||
<aside className={`${styles.sidebar} ${className ?? ''}`}>
|
||||
|
||||
71
src/design-system/utils/rechartsTheme.ts
Normal file
71
src/design-system/utils/rechartsTheme.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { CHART_COLORS } from '../composites/_chart-utils'
|
||||
|
||||
/**
|
||||
* Pre-configured Recharts prop objects that match the design system's
|
||||
* chart styling. Spread these onto Recharts sub-components:
|
||||
*
|
||||
* ```tsx
|
||||
* import { rechartsTheme, CHART_COLORS } from '@cameleer/design-system'
|
||||
* import { LineChart, Line, CartesianGrid, XAxis, YAxis, Tooltip, Legend } from 'recharts'
|
||||
*
|
||||
* <LineChart data={data}>
|
||||
* <CartesianGrid {...rechartsTheme.cartesianGrid} />
|
||||
* <XAxis dataKey="name" {...rechartsTheme.xAxis} />
|
||||
* <YAxis {...rechartsTheme.yAxis} />
|
||||
* <Tooltip {...rechartsTheme.tooltip} />
|
||||
* <Legend {...rechartsTheme.legend} />
|
||||
* <Line stroke={CHART_COLORS[0]} strokeWidth={2} dot={false} />
|
||||
* </LineChart>
|
||||
* ```
|
||||
*/
|
||||
export const rechartsTheme = {
|
||||
colors: CHART_COLORS,
|
||||
|
||||
cartesianGrid: {
|
||||
stroke: 'var(--border-subtle)',
|
||||
strokeDasharray: '3 3',
|
||||
vertical: false,
|
||||
},
|
||||
|
||||
xAxis: {
|
||||
tick: { fontSize: 9, fontFamily: 'var(--font-mono)', fill: 'var(--text-faint)' },
|
||||
axisLine: { stroke: 'var(--border-subtle)' },
|
||||
tickLine: false as const,
|
||||
},
|
||||
|
||||
yAxis: {
|
||||
tick: { fontSize: 9, fontFamily: 'var(--font-mono)', fill: 'var(--text-faint)' },
|
||||
axisLine: false as const,
|
||||
tickLine: false as const,
|
||||
},
|
||||
|
||||
tooltip: {
|
||||
contentStyle: {
|
||||
background: 'var(--bg-surface)',
|
||||
border: '1px solid var(--border)',
|
||||
borderRadius: 'var(--radius-sm)',
|
||||
boxShadow: 'var(--shadow-md)',
|
||||
fontSize: 11,
|
||||
padding: '6px 10px',
|
||||
},
|
||||
labelStyle: {
|
||||
color: 'var(--text-muted)',
|
||||
fontSize: 11,
|
||||
marginBottom: 4,
|
||||
},
|
||||
itemStyle: {
|
||||
color: 'var(--text-primary)',
|
||||
fontFamily: 'var(--font-mono)',
|
||||
fontSize: 11,
|
||||
padding: 0,
|
||||
},
|
||||
cursor: { stroke: 'var(--text-faint)' },
|
||||
},
|
||||
|
||||
legend: {
|
||||
wrapperStyle: {
|
||||
fontSize: 11,
|
||||
color: 'var(--text-secondary)',
|
||||
},
|
||||
},
|
||||
} as const
|
||||
Reference in New Issue
Block a user