# ChartContainer

> The shell every Crew OS chart sits in: it wraps a Recharts 2 chart in a `ResponsiveContainer`, turns a config object into per-series colour variables and styles axes, grid, tooltip and legend with the theme tokens.

## Facts

- **Product**: Crew OS
- **Family**: Analytics
- **Global**: `window.DigitalCrew.ChartContainer`
- **Source**: `digitalcrew-orchestrator: components/ui/chart.tsx`
- **Import in the app**: `import { ChartContainer } from "@/components/ui/chart";`
- **Live preview**: /design/components/chart-container/preview.html
- **Page**: /design/components/chart-container

## Guidelines

**Use it for** analytics cards: activity over time (area, line), volume by stage or channel (bar), shares (pie, radial).

**What you provide**: `config` (required), a map from each `dataKey` to `{ label, icon?, color }` or `{ label, theme: { light, dark } }`; each entry becomes `--color-<key>`, so series use `stroke="var(--color-sent)"`. `theme` colours switch on a `.dark` ancestor. Build the chart from Recharts primitives (in this bundle: `DC.Recharts.AreaChart`, `Area`, `BarChart`, `Bar`, `LineChart`, `XAxis`, `CartesianGrid`, …). Add `ChartTooltip` with `content={<ChartTooltipContent />}` (`indicator`: `dot` default, `line`, `dashed`; `hideLabel`, `hideIndicator`, `nameKey`, `labelKey`, `formatter`) and `ChartLegend` with `ChartLegendContent`.

**Anatomy**: the container defaults to `aspect-video` and `text-xs`, so give it a height (`h-[240px] w-full`). Tick labels are `fill-muted-foreground`; the default grid stroke becomes `border/50`; the cursor is `border`. The tooltip is a `bg-background` card, `rounded-lg`, `border-border/50`, `px-2.5 py-1.5`, `shadow-xl`, at least 128px wide, values in `font-mono tabular-nums`. Legend swatches are 8px squares with 2px corners, 16px apart.

**Don't** hard-code hex values in series (go through `config`), or add a second y-axis.

## API

```ts
declare const THEMES: {
    readonly light: "";
    readonly dark: ".dark";
};
export type ChartConfig = {
    [k in string]: {
        label?: React.ReactNode;
        icon?: React.ComponentType;
    } & ({
        color?: string;
        theme?: never;
    } | {
        color?: never;
        theme: Record<keyof typeof THEMES, string>;
    });
};
declare function ChartContainer({ id, className, children, config, ...props }: React.ComponentProps<"div"> & {
    config: ChartConfig;
    children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>["children"];
}): any;
declare const ChartStyle: ({ id, config }: {
    id: string;
    config: ChartConfig;
}) => any;
declare const ChartTooltip: typeof RechartsPrimitive.Tooltip;
declare function ChartTooltipContent({ active, payload, className, indicator, hideLabel, hideIndicator, label, labelFormatter, labelClassName, formatter, color, nameKey, labelKey, }: React.ComponentProps<typeof RechartsPrimitive.Tooltip> & React.ComponentProps<"div"> & {
    hideLabel?: boolean;
    hideIndicator?: boolean;
    indicator?: "line" | "dot" | "dashed";
    nameKey?: string;
    labelKey?: string;
}): any;
declare const ChartLegend: typeof RechartsPrimitive.Legend;
declare function ChartLegendContent({ className, hideIcon, payload, verticalAlign, nameKey, }: React.ComponentProps<"div"> & Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
    hideIcon?: boolean;
    nameKey?: string;
}): any;
export { ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, ChartLegendContent, ChartStyle, };
```

## Example

```html
<div id="root" class="p-6"></div>
<script>
(function () {
  var h = React.createElement, DC = window.DigitalCrew, I = DC.Icons, R = DC.Recharts;
  var data = [
    { day: "Mon", sent: 412, replies: 31 },
    { day: "Tue", sent: 468, replies: 42 },
    { day: "Wed", sent: 455, replies: 38 },
    { day: "Thu", sent: 520, replies: 57 },
    { day: "Fri", sent: 498, replies: 49 },
    { day: "Sat", sent: 120, replies: 9 },
    { day: "Sun", sent: 96, replies: 14 }
  ];
  var config = {
    sent: { label: "Emails sent", color: "var(--chart-1)" },
    replies: { label: "Replies", color: "var(--chart-2)" }
  };
  function App() {
    return h("div", { className: "grid gap-3" },
      h("div", null,
        h("p", { className: "text-sm font-medium" }, "Outbound activity"),
        h("p", { className: "text-muted-foreground text-xs" }, "Q3 CFO outreach, last 7 days")),
      h(DC.ChartContainer, { config: config, className: "h-[240px] w-full" },
        h(R.AreaChart, { data: data, margin: { left: 4, right: 12, top: 8 } },
          h(R.CartesianGrid, { vertical: false }),
          h(R.XAxis, { dataKey: "day", tickLine: false, axisLine: false, tickMargin: 8 }),
          h(R.YAxis, { tickLine: false, axisLine: false, width: 32 }),
          h(DC.ChartTooltip, { defaultIndex: 3, content: h(DC.ChartTooltipContent, { indicator: "line" }) }),
          h(R.Area, { dataKey: "sent", type: "monotone", stroke: "var(--color-sent)", strokeWidth: 2, fill: "var(--color-sent)", fillOpacity: 0.12 }),
          h(R.Area, { dataKey: "replies", type: "monotone", stroke: "var(--color-replies)", strokeWidth: 2, fill: "var(--color-replies)", fillOpacity: 0.2 }),
          h(DC.ChartLegend, { content: h(DC.ChartLegendContent) }))));
  }
  ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>
```

## More in Analytics

- [ActivityChart](/design/components/activity-chart.md): A day-bucketed Recharts chart in Max's glass panel: each series is drawn as an area, a line or a bar, with a dot legend and a popover tooltip.
- [FunnelChart](/design/components/funnel-chart.md): A vertical column funnel with a summary panel.
- [InsightsCard](/design/components/insights-card.md): A meeting's numbers (sentiment, stat tiles, per-speaker talk share, an over-talk hint), all derived on the client from the transcript.
- [QualificationContent](/design/components/qualification-content.md): The body of a BANT qualification snapshot: a score, a verdict, a confirmed count, and one tile per criterion with its status, rationale and first piece of transcript evidence.
