Westy Design Systemv0.2.7
OverviewComponentsExamplesStorybook

Foundations

  • Typography
  • Colors
  • Spacing
  • Radius
  • Shadows
  • Icons

Components

  • Accordion
  • Alert
  • Alert Dialog
  • Aspect Ratio
  • Avatar
  • Badge
  • Breadcrumb
  • Button
  • Button Group
  • Calendar
  • Card
  • Carousel
  • Chart
  • Checkbox
  • Collapsible
  • Combobox
  • Command
  • Context Menu
  • Data Table
  • Date Picker
  • Dialog
  • Direction
  • Drawer
  • Dropdown Menu
  • Empty
  • Field
  • Hover Card
  • Input
  • Input Group
  • Input OTP
  • Item
  • Kbd
  • Label
  • Menubar
  • Native Select
  • Navigation Menu
  • Pagination
  • Popover
  • Progress
  • Questionnaire
  • Radio Group
  • Resizable
  • Scroll Area
  • Select
  • Separator
  • Sheet
  • Sidebar
  • Skeleton
  • Slider
  • Sonner
  • Spinner
  • Switch
  • Table
  • Tabs
  • Textarea
  • Toggle
  • Toggle Group
  • Tooltip

Chat

  • Attachment
  • Bubble
  • Marker
  • Message
  • Message Scroller

Components

Chart

Beautiful charts built on Recharts — a container, tooltip, and legend driven by a single config and the design-system chart tokens.

Playground

—chart
—indicator
—CartesianGrid
—ChartLegend
Usage
The design system does not wrap Recharts — compose charts from Recharts primitives inside ChartContainer. The config maps each data key to a label and a color; the container exposes every color as --color-{key}, which the series reference directly. Point config colors at the --chart-1…--chart-5 tokens so charts follow the theme in both modes.
import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"

import {
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from "@workspace/ui/components/chart"

const chartData = [
  { month: "Jan", desktop: 186, mobile: 80 },
  { month: "Feb", desktop: 305, mobile: 200 },
  { month: "Mar", desktop: 237, mobile: 120 },
  { month: "Apr", desktop: 73, mobile: 190 },
  { month: "May", desktop: 209, mobile: 130 },
  { month: "Jun", desktop: 214, mobile: 140 },
]

const chartConfig = {
  desktop: {
    label: "Desktop",
    color: "var(--chart-1)",
  },
  mobile: {
    label: "Mobile",
    color: "var(--chart-3)",
  },
} satisfies ChartConfig

<ChartContainer config={chartConfig} className="w-full">
  <BarChart accessibilityLayer data={chartData}>
    <CartesianGrid vertical={false} />
    <XAxis dataKey="month" tickLine={false} tickMargin={10} axisLine={false} />
    <ChartTooltip content={<ChartTooltipContent />} />
    <Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
    <Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
  </BarChart>
</ChartContainer>
Line chart
The same config drives any chart type. Here Line series take the color as stroke, and the tooltip switches to the line indicator to match.
import { CartesianGrid, Line, LineChart, XAxis } from "recharts"

<ChartContainer config={chartConfig} className="w-full">
  <LineChart accessibilityLayer data={chartData}>
    <CartesianGrid vertical={false} />
    <XAxis dataKey="month" tickLine={false} tickMargin={10} axisLine={false} />
    <ChartTooltip content={<ChartTooltipContent indicator="line" />} />
    <Line
      dataKey="desktop"
      type="natural"
      stroke="var(--color-desktop)"
      strokeWidth={2}
      dot={false}
    />
    <Line
      dataKey="mobile"
      type="natural"
      stroke="var(--color-mobile)"
      strokeWidth={2}
      dot={false}
    />
  </LineChart>
</ChartContainer>
Stacked area with legend
Give the series a shared stackId to stack them, and add ChartLegend with ChartLegendContent — it reads the labels and colors from the same config as the tooltip.
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"

<ChartContainer config={chartConfig} className="w-full">
  <AreaChart accessibilityLayer data={chartData}>
    <CartesianGrid vertical={false} />
    <XAxis dataKey="month" tickLine={false} tickMargin={10} axisLine={false} />
    <ChartTooltip content={<ChartTooltipContent indicator="dot" />} />
    <ChartLegend content={<ChartLegendContent />} />
    <Area
      dataKey="mobile"
      type="natural"
      fill="var(--color-mobile)"
      fillOpacity={0.4}
      stroke="var(--color-mobile)"
      stackId="a"
    />
    <Area
      dataKey="desktop"
      type="natural"
      fill="var(--color-desktop)"
      fillOpacity={0.4}
      stroke="var(--color-desktop)"
      stackId="a"
    />
  </AreaChart>
</ChartContainer>
Pie chart
For categorical charts, each datum carries its own fill and the config keys match the values of nameKey. A donut is just innerRadius; the tooltip hides its label since each slice already names itself.
import { Pie, PieChart } from "recharts"

const chartData = [
  { browser: "chrome", visitors: 275, fill: "var(--color-chrome)" },
  { browser: "safari", visitors: 200, fill: "var(--color-safari)" },
  { browser: "firefox", visitors: 187, fill: "var(--color-firefox)" },
  { browser: "edge", visitors: 173, fill: "var(--color-edge)" },
  { browser: "other", visitors: 90, fill: "var(--color-other)" },
]

const chartConfig = {
  visitors: { label: "Visitors" },
  chrome: { label: "Chrome", color: "var(--chart-1)" },
  safari: { label: "Safari", color: "var(--chart-2)" },
  firefox: { label: "Firefox", color: "var(--chart-3)" },
  edge: { label: "Edge", color: "var(--chart-4)" },
  other: { label: "Other", color: "var(--chart-5)" },
} satisfies ChartConfig

<ChartContainer config={chartConfig} className="mx-auto aspect-square h-64">
  <PieChart>
    <ChartTooltip cursor={false} content={<ChartTooltipContent hideLabel />} />
    <Pie
      data={chartData}
      dataKey="visitors"
      nameKey="browser"
      innerRadius={60}
    />
    <ChartLegend content={<ChartLegendContent nameKey="browser" />} />
  </PieChart>
</ChartContainer>
API Reference
Chart is a set of composable parts around Recharts. ChartTooltip and ChartLegend re-export the Recharts Tooltip and Legend — pass the styled *Content components to their content prop. Give the container a height via aspect-* or min-h-* — it defaults to aspect-video.
PartKey props
ChartContainerconfig: ChartConfig, initialDimension
ChartTooltipRecharts Tooltip — content, cursor, defaultIndex
ChartTooltipContentindicator: "dot" | "line" | "dashed", hideLabel, hideIndicator, labelKey, nameKey, labelFormatter, formatter
ChartLegendRecharts Legend — content, verticalAlign
ChartLegendContentnameKey, hideIcon, verticalAlign
ChartStyleid, config — rendered by ChartContainer

Tokens used

11 design tokens consumed by the Chart components.

  • --chart-1

    Chart 1

    var(--chart-1)
  • --chart-2

    Chart 2

    var(--chart-2)
  • --chart-3

    Chart 3

    var(--chart-3)
  • --chart-4

    Chart 4

    var(--chart-4)
  • --chart-5

    Chart 5

    var(--chart-5)
  • --border

    Border

    stroke-border/50border-border/50
  • --background

    Background

    bg-background
  • --foreground

    Foreground

    text-foreground
  • --muted

    Muted

    fill-muted
  • --muted-foreground

    Muted foreground

    fill-muted-foregroundtext-muted-foreground
  • --radius

    Radius

    rounded-lg