Chart
Typed wrapper over LayerChart. ChartContainer injects theme-aware CSS variables per series; ChartTooltip renders a popover-styled surface that mirrors the rest of the system.
Line chart
<script lang="ts">
import {
ChartContainer,
ChartTooltip,
type ChartConfig
} from '$lib/components/ui/chart';
import { LineChart } from 'layerchart';
const data = [
{ month: 'Jan', shipped: 12 },
{ month: 'Feb', shipped: 18 },
{ month: 'Mar', shipped: 14 },
{ month: 'Apr', shipped: 22 },
{ month: 'May', shipped: 30 },
{ month: 'Jun', shipped: 38 }
];
const config = {
shipped: { label: 'Shipped', color: 'var(--primary)' }
} satisfies ChartConfig;
</script>
<ChartContainer {config} class="h-60 w-full">
<LineChart {data} x="month" y="shipped" props={{ spline: { class: 'stroke-primary' } }}>
{#snippet tooltip()}
<ChartTooltip indicator="line" />
{/snippet}
</LineChart>
</ChartContainer>Bar chart
<ChartContainer {config} class="h-60 w-full">
<BarChart {data} x="month" y="components" props={{ bars: { class: 'fill-primary' } }}>
{#snippet tooltip()}
<ChartTooltip />
{/snippet}
</BarChart>
</ChartContainer>Axis tick
Pass a format function via props.xAxis.format to abbreviate or transform tick labels — useful when full month names would overlap.
<script lang="ts">
import { ChartContainer, ChartTooltip, type ChartConfig } from '$lib/components/ui/chart';
import { BarChart } from 'layerchart';
const data = [
{ month: 'January', value: 186 },
{ month: 'February', value: 305 },
{ month: 'March', value: 237 },
{ month: 'April', value: 73 },
{ month: 'May', value: 209 },
{ month: 'June', value: 214 }
];
const config = {
value: { label: 'Visitors', color: 'var(--primary)' }
} satisfies ChartConfig;
// Abbreviate long month names on the x-axis
const fmtMonth = (v: string) => v.slice(0, 3);
</script>
<ChartContainer {config} class="h-64 w-full">
<BarChart
{data}
x="month"
y="value"
props={{
xAxis: { format: fmtMonth },
bars: { class: 'fill-primary', rounded: 'top', radius: 4 }
}}
>
{#snippet tooltip()}
<ChartTooltip />
{/snippet}
</BarChart>
</ChartContainer>Legend
Set legend to true on BarChart and pass a series array for a grouped chart
with color swatches.
<script lang="ts">
import { ChartContainer, ChartTooltip, type ChartConfig } from '$lib/components/ui/chart';
import { BarChart } from 'layerchart';
const data = [
{ month: 'Jan', designed: 3, shipped: 1 },
{ month: 'Feb', designed: 6, shipped: 4 },
{ month: 'Mar', designed: 8, shipped: 5 },
{ month: 'Apr', designed: 12, shipped: 9 },
{ month: 'May', designed: 16, shipped: 12 },
{ month: 'Jun', designed: 20, shipped: 17 }
];
const config = {
designed: { label: 'Designed', color: 'var(--primary)' },
shipped: { label: 'Shipped', color: 'var(--chart-2, var(--secondary))' }
} satisfies ChartConfig;
</script>
<ChartContainer {config} class="h-72 w-full">
<BarChart
{data}
x="month"
series={[
{ key: 'designed', value: 'designed', color: 'var(--primary)' },
{ key: 'shipped', value: 'shipped', color: 'var(--chart-2, var(--secondary))' }
]}
seriesLayout="group"
legend
props={{ bars: { rounded: 'top', radius: 4 } }}
>
{#snippet tooltip()}
<ChartTooltip />
{/snippet}
</BarChart>
</ChartContainer>Interactive
onBarClick fires with the data
row and series on each column click, letting you drive external state from the chart.
Click a bar to select a month.
<script lang="ts">
import { ChartContainer, ChartTooltip, type ChartConfig } from '$lib/components/ui/chart';
import { BarChart } from 'layerchart';
const data = [
{ month: 'Jan', components: 4 },
{ month: 'Feb', components: 8 },
{ month: 'Mar', components: 10 },
{ month: 'Apr', components: 18 },
{ month: 'May', components: 24 },
{ month: 'Jun', components: 31 }
];
const config = {
components: { label: 'Components', color: 'var(--primary)' }
} satisfies ChartConfig;
let activeMonth = $state<string | null>(null);
</script>
{#if activeMonth}
<p class="mb-2 text-sm text-muted-foreground">
Selected: <span class="font-medium text-foreground">{activeMonth}</span>
</p>
{/if}
<ChartContainer {config} class="h-64 w-full">
<BarChart
{data}
x="month"
y="components"
onBarClick={(_e, detail) => {
activeMonth = detail.data.month;
}}
props={{ bars: { class: 'fill-primary', rounded: 'top', radius: 4 } }}
>
{#snippet tooltip()}
<ChartTooltip />
{/snippet}
</BarChart>
</ChartContainer>Theming
ChartConfig.color must be
a CSS custom property reference — raw hex bypasses the token system and breaks dark-mode
adaptation. Use theme when you need different
values per color scheme.
<script lang="ts">
import { ChartContainer, ChartTooltip, type ChartConfig } from '$lib/components/ui/chart';
import { BarChart } from 'layerchart';
// color MUST be a CSS custom property — raw hex bypasses the token system
// theme lets you pick different values per color scheme
const config = {
revenue: {
label: 'Revenue',
// Single value: same in light and dark
color: 'var(--primary)'
},
cost: {
label: 'Cost',
// Per-scheme: different values for light vs. dark
theme: {
light: 'oklch(0.65 0.18 29)',
dark: 'oklch(0.75 0.18 29)'
}
}
} satisfies ChartConfig;
</script>ChartContainer props
ChartContainer sets the chart id, injects per-series CSS variables (light + dark) via ChartStyle, and applies a set of LayerChart overrides so tooltips, highlights, and axes match the token system.
| Prop | Type | Default | Description |
|---|---|---|---|
ChartConfig | — | Map of series key → { label, color | theme, icon }. `color` applies the same value in both themes; `theme` picks different values for light and dark. | |
string | — | Overrides the auto-generated chart id. Used to scope injected CSS variables. | |
string | — | Merged onto the root via tailwind-merge. |
ChartTooltip props
| Prop | Type | Default | Description |
|---|---|---|---|
'dot' | 'line' | 'dashed' | 'dot' | Shape of the series indicator next to each value. | |
boolean | false | Suppress the x-axis label at the top of the tooltip card. | |
boolean | false | Hide the colored swatch alongside each value. | |
string | — | Key into the config used to look up a label for the hovered row. | |
string | — | Key into the config used to look up the series name for each entry. | |
(value, payload) => string | number | Snippet | — | Format the tooltip header. Return a Snippet for rich content. | |
Snippet<[{ value, name, item, index, payload }]> | — | Completely override how each row renders. |