Introducing Charts. A collection of chart components that you can copy and paste into your apps.
Charts are designed to look great out of the box. They work well with the other components and are fully customizable to fit your project.
About
Charts are drawn by LayerChart, a Svelte charting library built on d3. The chart component ports shadcn/ui's ChartConfig, tooltip, and legend to LayerChart. ChartContainer turns a config into colors, and ChartTooltip and ChartLegend read the same config for labels, icons, and colors.
The examples on this page port the LayerChart charts of shadcn-svelte to the Sveltery components. They follow the charts of shadcn/ui, and the licenses are in THIRD_PARTY_NOTICES.md.
Component
We designed the chart component with composition in mind. You build your charts with LayerChart components and bring in ChartContainer, ChartTooltip, and ChartLegend only where you need them.
<script lang="ts">
import { BarChart } from 'layerchart';
import { ChartContainer, ChartTooltip, type ChartConfig } from '$lib/components/ui/chart';
const data = [
{ month: 'January', value: 186 },
{ month: 'February', value: 305 }
];
const config = { value: { label: 'Visitors', color: 'var(--chart-1)' } } satisfies ChartConfig;
</script>
<ChartContainer {config} aria-label="Visitors by month">
<BarChart {data} x="month" series={[{ key: 'value', color: 'var(--color-value)' }]}>
{#snippet tooltip()}
<ChartTooltip />
{/snippet}
</BarChart>
</ChartContainer>We do not wrap LayerChart. You are not locked into an abstraction, and when LayerChart ships a new version, you follow its upgrade path to update your charts.
The components are yours.
Installation
Install the dependencies
pnpm add cn layerchartMany examples also import d3-scale and d3-shape, which LayerChart already depends on. Install them when you import from them in your own code.
Copy the component
Copy the following files into src/lib/components/ui/chart.
<script lang="ts">
import { on } from 'svelte/events';
import { cn } from 'cn';
import type { ChartState } from 'layerchart';
import ChartStyle from './ChartStyle.svelte';
import { setChartContainer, type ChartRow } from './context.js';
import type { ChartContainerProps } from './types.js';
const uid = $props.id();
let { id, config, class: classProp, children, ...props }: ChartContainerProps = $props();
const chartId = $derived(`chart-${id ?? uid}`);
let tooltipChart = $state.raw<ChartState<ChartRow>>();
setChartContainer({
get config() {
return config;
},
registerTooltip(chart) {
tooltipChart = chart;
return () => {
if (tooltipChart === chart) tooltipChart = undefined;
};
},
});
// LayerChart has no keyboard tooltip. The container steps through the chart's rows and shows each one through the chart's tooltip.
function keyboard(node: HTMLElement) {
const chart = tooltipChart;
if (!chart) return;
const step = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 } as const;
const offKeydown = on(node, 'keydown', (event) => {
const rows = chart.flatData;
const last = rows.length - 1;
if (event.key === 'Escape') return chart.tooltip.hide();
const current = rows.indexOf(chart.tooltip.data);
const next =
event.key === 'Home' ? 0
: event.key === 'End' ? last
: event.key in step ? current + step[event.key as keyof typeof step]
: undefined;
if (next === undefined) return;
event.preventDefault();
chart.tooltip.show({ data: rows[Math.min(Math.max(next, 0), last)] });
});
const offBlur = on(node, 'blur', () => chart.tooltip.hide());
return () => {
offKeydown();
offBlur();
};
}
</script>
<!-- The tabindex and role exist only while a tooltip is registered. -->
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
<div
data-slot="chart"
data-chart={chartId}
tabindex={tooltipChart ? 0 : undefined}
role={tooltipChart ? 'application' : undefined}
aria-roledescription={tooltipChart ? 'chart' : undefined}
class={cn(
'PortalTarget flex aspect-video justify-center text-xs focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-hidden',
'[&_.lc-bar]:stroke-transparent [&_.lc-line]:stroke-border/50 [&_.lc-axis-tick]:stroke-0 [&_.lc-rule-y-line:not(.lc-grid-y-rule)]:stroke-0',
'[&_.lc-highlight-point]:stroke-transparent [&_.lc-highlight-line]:stroke-0',
'[&_.lc-text]:text-xs [&_text]:stroke-transparent [&_.lc-axis-tick-label]:fill-muted-foreground',
'[&_.lc-grid-y-radial-line]:stroke-border [&_.lc-grid-y-radial-circle]:stroke-border',
classProp
)}
{...props}
{@attach keyboard}
>
<ChartStyle id={chartId} {config} />
{@render children?.()}
</div><script lang="ts">
import ChartLegendContent from './ChartLegendContent.svelte';
import type { ChartLegendProps } from './types.js';
let { children, ...props }: ChartLegendProps = $props();
</script>
{#if children}
{@render children()}
{:else}
<ChartLegendContent {...props} />
{/if}<script lang="ts">
import { getChartContext } from 'layerchart';
import { cn } from 'cn';
import { configColor, getChartContainer, type ChartRow } from './context.js';
import type { ChartLegendContentProps } from './types.js';
let { hideIcon = false, nameKey, verticalAlign = 'bottom', class: classProp }: ChartLegendContentProps = $props();
const chart = getChartContext<ChartRow>();
const { config } = getChartContainer();
const items = $derived(
nameKey
? chart.flatData.map((row) => String(row[nameKey])).map((key) => ({ key, label: config[key]?.label, icon: config[key]?.icon, color: configColor(config, key) ?? chart.cScale?.(key) }))
: chart.series.series.map((series) => ({
key: series.key,
label: config[series.key]?.label ?? series.label,
icon: config[series.key]?.icon,
color: configColor(config, series.key) ?? series.color
}))
);
</script>
<div class={cn('absolute inset-x-0 flex items-center justify-center gap-4', verticalAlign === 'top' ? 'top-0 pb-3' : 'bottom-0 pt-3', classProp)}>
{#each items as item (item.key)}
{const Icon = item.icon}
<div class="flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground">
{#if Icon && !hideIcon}
<Icon />
{:else}
<div class="h-2 w-2 shrink-0 rounded-[2px]" style:background-color={item.color}></div>
{/if}
{item.label}
</div>
{/each}
</div><script lang="ts">
import type { ChartConfig } from './context.js';
let { id, config }: { id: string; config: ChartConfig } = $props();
// Format: { THEME_NAME: CSS_SELECTOR }
const THEMES = { light: '', dark: '.dark' } as const;
const colorConfig = $derived(Object.entries(config).filter(([, item]) => item.theme ?? item.color));
const css = $derived(
Object.entries(THEMES)
.map(
([theme, prefix]) => `
${prefix} [data-chart=${id}] {
${colorConfig
.map(([key, item]) => {
const color = item.theme?.[theme as keyof typeof THEMES] ?? item.color;
return color ? ` --color-${key}: ${color};` : null;
})
.join('\n')}
}
`
)
.join('\n')
);
</script>
{#if colorConfig.length}
<svelte:element this={'style'}>{css}</svelte:element>
{/if}<script lang="ts">
import { getChartContext, Tooltip } from 'layerchart';
import ChartTooltipContent from './ChartTooltipContent.svelte';
import { getChartContainer, type ChartRow } from './context.js';
import type { ChartTooltipProps } from './types.js';
let { children: childrenProp, ...props }: ChartTooltipProps = $props();
const chart = getChartContext<ChartRow>();
const container = getChartContainer();
$effect(() => container.registerTooltip(chart));
</script>
<Tooltip.Root variant="none">
{#snippet children({ data })}
{#if childrenProp}
{@render childrenProp({ data })}
{:else}
<ChartTooltipContent {...props} />
{/if}
{/snippet}
</Tooltip.Root><script lang="ts">
import { getChartContext } from 'layerchart';
import { cn } from 'cn';
import { configColor, configKey, getChartContainer, type ChartRow } from './context.js';
import type { ChartTooltipContentProps } from './types.js';
let {
hideLabel = false,
hideIndicator = false,
indicator = 'dot',
nameKey,
labelKey,
label,
labelFormatter,
formatter,
color,
labelClass,
class: classProp
}: ChartTooltipContentProps = $props();
const chart = getChartContext<ChartRow>();
const { config } = getChartContainer();
const data = $derived(chart.tooltip.data);
const items = $derived(chart.tooltip.series.filter((series) => series.visible && series.value != null));
const nestLabel = $derived(items.length === 1 && indicator !== 'dot');
const header = $derived.by(() => {
if (hideLabel || data == null) return;
const category = label ?? (chart.valueAxis === 'x' ? chart.y : chart.x)?.(data);
// Recharts hands upstream a string category; LayerChart's can be a Date or a number, so any category takes the string path.
const text = !labelKey && category != null
? config[String(category)]?.label || category
: config[configKey(config, data, labelKey ?? items[0]?.key ?? 'value')]?.label;
if (labelFormatter) return labelFormatter(text, items);
if (text) return text;
});
const rows = $derived(
items.map((series) => {
const key = configKey(config, data, nameKey ?? series.key);
return {
series,
name: config[key]?.label ?? series.label,
icon: config[key]?.icon,
color: color ?? configColor(config, key) ?? series.color
};
})
);
</script>
{#snippet headerRow()}
{#if header !== undefined}
<div class={cn('font-medium', labelClass)}>{header}</div>
{/if}
{/snippet}
<div class={cn('border-border/50 bg-background gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl grid min-w-32 items-start', classProp)}>
{#if !nestLabel}
{@render headerRow()}
{/if}
<div class="grid gap-1.5">
{#each rows as row, index (row.series.key)}
{const Icon = row.icon}
<div class={cn('flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground', indicator === 'dot' && 'items-center')}>
{#if formatter && row.series.value !== undefined && row.series.label}
{@render formatter({ item: row.series, data, index, name: row.name, value: row.series.value })}
{:else}
{#if Icon}
<Icon />
{:else if !hideIndicator}
<div
class={cn('shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)', {
'h-2.5 w-2.5': indicator === 'dot',
'w-1': indicator === 'line',
'w-0 border-[1.5px] border-dashed bg-transparent': indicator === 'dashed',
'my-0.5': nestLabel && indicator === 'dashed'
})}
style:--color-bg={row.color}
style:--color-border={row.color}
></div>
{/if}
<div class={cn('flex flex-1 justify-between leading-none', nestLabel ? 'items-end' : 'items-center')}>
<div class="grid gap-1.5">
{#if nestLabel}
{@render headerRow()}
{/if}
<span class="text-muted-foreground">{row.name}</span>
</div>
{#if row.series.value != null}
<span class="font-mono font-medium text-foreground tabular-nums">
{typeof row.series.value === 'number' ? row.series.value.toLocaleString() : String(row.series.value)}
</span>
{/if}
</div>
{/if}
</div>
{/each}
</div>
</div>import { createContext, type Component } from 'svelte';
import type { ChartState } from 'layerchart';
export type ChartConfig = Record<
string,
{ label?: string; icon?: Component } & (
| { color?: string; theme?: never }
| { color?: never; theme: { light: string; dark: string } }
)
>;
export type ChartRow = Record<string, unknown>;
export type ChartContainerContext = {
readonly config: ChartConfig;
/** Called by `ChartTooltip` so the container can drive its tooltip from the keyboard. Returns the cleanup. */
registerTooltip(chart: ChartState<ChartRow>): () => void;
};
export const [getChartContainer, setChartContainer] = createContext<ChartContainerContext>();
/** The config key for a series or data row. A row field named by `key` wins when it holds a config key (`nameKey="browser"` on `{ browser: 'chrome' }`). */
export function configKey(config: ChartConfig, row: ChartRow | null, key: string): string {
const value = row?.[key];
return typeof value === 'string' && value in config ? value : key;
}
/** The CSS color for a config key: the per-chart variable when the config defines a color, otherwise nothing. */
export function configColor(config: ChartConfig, key: string): string | undefined {
const entry = config[key];
return entry?.color || entry?.theme ? `var(--color-${key})` : undefined;
}import type { Snippet } from 'svelte';
import type { HTMLAttributes } from 'svelte/elements';
import type { TooltipSeries } from 'layerchart';
import type { ChartConfig, ChartRow } from './context.js';
export type { ChartConfig };
export type ChartContainerProps = HTMLAttributes<HTMLDivElement> & {
config: ChartConfig;
};
export type ChartTooltipFormatterArgs = {
/** The tooltip row: series key, value, color and visibility. */
item: TooltipSeries;
/** The hovered data row. */
data: ChartRow;
index: number;
/** The config label, then the series label. */
name: string;
value: unknown;
};
export type ChartTooltipContentProps = Pick<HTMLAttributes<HTMLDivElement>, 'class'> & {
hideLabel?: boolean;
hideIndicator?: boolean;
indicator?: 'dot' | 'line' | 'dashed';
/** Data field holding the config key of each tooltip row, for charts whose series key is not the config key. */
nameKey?: string;
/** Config key (or data field holding one) whose label becomes the header. */
labelKey?: string;
/** Header text. A config key is replaced by its label. */
label?: string;
// Method syntax keeps the parameter bivariant, so `(value: Date) => string` is accepted for a date axis.
labelFormatter?(value: unknown, items: TooltipSeries[]): string | number;
/** Replaces a row's content. */
formatter?: Snippet<[ChartTooltipFormatterArgs]>;
/** Indicator color for every row. */
color?: string;
labelClass?: string;
};
export type ChartTooltipProps = ChartTooltipContentProps & {
/** Replaces `ChartTooltipContent`. */
children?: Snippet<[{ data: ChartRow }]>;
};
export type ChartLegendContentProps = Pick<HTMLAttributes<HTMLDivElement>, 'class'> & {
hideIcon?: boolean;
/** Data field naming each legend item, for charts whose items are rows (pie, radial) instead of series. */
nameKey?: string;
verticalAlign?: 'top' | 'bottom';
};
export type ChartLegendProps = ChartLegendContentProps & {
children?: Snippet;
};export { default as ChartContainer } from './ChartContainer.svelte';
export { default as ChartStyle } from './ChartStyle.svelte';
export { default as ChartTooltip } from './ChartTooltip.svelte';
export { default as ChartTooltipContent } from './ChartTooltipContent.svelte';
export { default as ChartLegend } from './ChartLegend.svelte';
export { default as ChartLegendContent } from './ChartLegendContent.svelte';
export type {
ChartConfig,
ChartContainerProps,
ChartLegendContentProps,
ChartLegendProps,
ChartTooltipContentProps,
ChartTooltipFormatterArgs,
ChartTooltipProps
} from './types.js';Add the colors to your CSS file
@layer base {
:root {
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
}
.dark {
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
}
}Update the import paths
Change the imports to match your project setup.
Your First Chart
Let's build your first chart. We'll build a bar chart, then add a grid, an axis, a tooltip, and a legend.
Define your data
The following data holds the number of desktop and mobile users for each month.
Note: Your data can be in any shape. Use the x, y, and series props of the LayerChart component to map your data to the chart.
<script lang="ts">
const chartData = [
{ month: 'January', desktop: 186, mobile: 80 },
{ month: 'February', desktop: 305, mobile: 200 },
{ month: 'March', desktop: 237, mobile: 120 },
{ month: 'April', desktop: 73, mobile: 190 },
{ month: 'May', desktop: 209, mobile: 130 },
{ month: 'June', desktop: 214, mobile: 140 }
];
</script>Define your chart config
The chart config holds the human-readable strings of a chart, such as labels, icons, and color tokens for theming.
<script lang="ts">
import type { ChartConfig } from '$lib/components/ui/chart';
const chartConfig = {
desktop: { label: 'Desktop', color: '#2563eb' },
mobile: { label: 'Mobile', color: '#60a5fa' }
} satisfies ChartConfig;
</script>Build your chart
Build the chart with a LayerChart component inside a ChartContainer. Pass each series the color var(--color-KEY), which ChartContainer defines from your config.
ChartContainer is aspect-video by default. Set a height such as h-[200px], or another aspect ratio, to change it.
<ChartContainer config={chartConfig} class="h-[200px] w-full" aria-label="Desktop and mobile visitors by month">
<BarChart
data={chartData}
x="month"
seriesLayout="group"
series={[
{ key: 'desktop', color: 'var(--color-desktop)' },
{ key: 'mobile', color: 'var(--color-mobile)' }
]}
axis={false}
grid={false}
rule={false}
tooltipContext={false}
/>
</ChartContainer>Add a Grid
A BarChart draws a grid by default. Remove grid={false} to show it.
<ChartContainer config={chartConfig} class="h-[200px] w-full" aria-label="Desktop and mobile visitors by month">
<BarChart
data={chartData}
x="month"
seriesLayout="group"
series={[ /* ... */ ]}
axis={false}
rule={false}
tooltipContext={false}
/>
</ChartContainer>Add an Axis
To add an x-axis, set axis="x". Format its labels with props.xAxis.format.
<ChartContainer config={chartConfig} class="h-[200px] w-full" aria-label="Desktop and mobile visitors by month">
<BarChart
data={chartData}
x="month"
seriesLayout="group"
series={[ /* ... */ ]}
axis="x"
props={{ xAxis: { format: (value: string) => value.slice(0, 3) } }}
rule={false}
tooltipContext={false}
/>
</ChartContainer>Add a Tooltip
So far we have only used LayerChart. The charts look right because ChartContainer styles LayerChart for you.
To add a tooltip, render the ChartTooltip component in the tooltip snippet of the chart, and remove tooltipContext={false}.
<script lang="ts">
import { ChartContainer, ChartTooltip } from '$lib/components/ui/chart';
</script>
<ChartContainer config={chartConfig} class="h-[200px] w-full" aria-label="Desktop and mobile visitors by month">
<BarChart
data={chartData}
x="month"
seriesLayout="group"
series={[ /* ... */ ]}
axis="x"
props={{ xAxis: { format: (value: string) => value.slice(0, 3) } }}
rule={false}
>
{#snippet tooltip()}
<ChartTooltip />
{/snippet}
</BarChart>
</ChartContainer>Hover the chart to see the tooltip. Two components, and you have a tooltip that reads your config.
Add a Legend
Do the same for the legend. Render the ChartLegend component in the legend snippet of the chart.
<script lang="ts">
import { ChartContainer, ChartLegend, ChartTooltip } from '$lib/components/ui/chart';
</script>
<ChartContainer config={chartConfig} class="h-[200px] w-full" aria-label="Desktop and mobile visitors by month">
<BarChart
data={chartData}
x="month"
seriesLayout="group"
series={[ /* ... */ ]}
axis="x"
props={{ xAxis: { format: (value: string) => value.slice(0, 3) } }}
rule={false}
>
{#snippet tooltip()}
<ChartTooltip />
{/snippet}
{#snippet legend()}
<ChartLegend />
{/snippet}
</BarChart>
</ChartContainer><script lang="ts">
import { BarChart } from 'layerchart';
import { type ChartConfig, ChartContainer, ChartLegend, ChartTooltip } from '@sveltery/components/chart';
const chartData = [
{ month: 'January', desktop: 186, mobile: 80 },
{ month: 'February', desktop: 305, mobile: 200 },
{ month: 'March', desktop: 237, mobile: 120 },
{ month: 'April', desktop: 73, mobile: 190 },
{ month: 'May', desktop: 209, mobile: 130 },
{ month: 'June', desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: '#2563eb' },
mobile: { label: 'Mobile', color: '#60a5fa' },
} satisfies ChartConfig;
</script>
<ChartContainer config={chartConfig} class="h-[200px] w-full" aria-label="Desktop and mobile visitors by month">
<BarChart
data={chartData}
x="month"
seriesLayout="group"
series={[
{ key: 'desktop', color: 'var(--color-desktop)' },
{ key: 'mobile', color: 'var(--color-mobile)' },
]}
axis="x"
props={{ xAxis: { format: (value: string) => value.slice(0, 3) } }}
rule={false}
>
{#snippet tooltip()}
<ChartTooltip />
{/snippet}
{#snippet legend()}
<ChartLegend />
{/snippet}
</BarChart>
</ChartContainer>Done. You have built your first chart. What's next?
Chart Config
The chart config is where you define the labels, icons, and colors of a chart.
It is intentionally decoupled from chart data. You can share a config and its color tokens between charts. It also works when your data or color tokens live somewhere else, or in another format.
<script lang="ts">
import MonitorIcon from '@lucide/svelte/icons/monitor';
import type { ChartConfig } from '$lib/components/ui/chart';
const chartConfig = {
desktop: {
label: 'Desktop',
icon: MonitorIcon,
// A color like 'hsl(220, 98%, 61%)' or 'var(--color-name)'
color: '#2563eb'
},
mobile: {
label: 'Mobile',
// Or a theme object with 'light' and 'dark' keys
theme: { light: '#2563eb', dark: '#dc2626' }
}
} satisfies ChartConfig;
</script>An entry takes a color or a theme, never both. The icon is any Svelte component that takes no props. The tooltip and the legend show it in place of the color swatch.
In the examples on this page, each config icon is a small component that renders an IconPlaceholder, so the icon follows the icon library you pick. Use the icon component of your own project instead.
Theming
Charts have built-in support for theming. Use CSS variables, which we recommend, or color values in any format, such as hex, hsl, or oklch.
CSS variables
Define your colors in your CSS file
@layer base {
:root {
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
}
.dark {
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
}
}Add the colors to your chart config
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' }
} satisfies ChartConfig;hex, hsl or oklch
You can also define your colors in the chart config. Use the color format you prefer.
const chartConfig = {
desktop: { label: 'Desktop', color: '#2563eb' },
mobile: { label: 'Mobile', color: 'hsl(220, 98%, 61%)' },
tablet: { label: 'Tablet', color: 'oklch(0.5 0.2 240)' },
laptop: { label: 'Laptop', color: 'var(--chart-2)' }
} satisfies ChartConfig;Light and dark colors
Use theme to give a key one color for each mode. The .dark class selects the dark color.
const chartConfig = {
desktop: { label: 'Desktop', theme: { light: '#2563eb', dark: '#60a5fa' } }
} satisfies ChartConfig;Using colors
ChartContainer writes a --color-KEY variable for each config key and scopes it to the chart. Reference the colors with var(--color-KEY).
Series
<BarChart series={[{ key: 'desktop', color: 'var(--color-desktop)' }]} />Chart data
Rows that carry their own color, such as the slices of a pie, name the variable in the data.
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' }
];Tailwind
<Text class="fill-(--color-desktop)" />Tooltip
A chart tooltip contains a label, a name, an indicator, and a value. You can combine these to customize the tooltip.
Turn off the label or the indicator with hideLabel and hideIndicator. Change the indicator style with indicator. Use labelKey and nameKey to read the label and the name from another key.
ChartTooltip replaces the default tooltip of a LayerChart chart. Render it in the tooltip snippet.
<script lang="ts">
import { ChartTooltip } from '$lib/components/ui/chart';
</script>
<BarChart {data} x="month" series={series}>
{#snippet tooltip()}
<ChartTooltip indicator="dashed" />
{/snippet}
</BarChart>Hover the charts in the tooltip examples to compare the options.
Props
ChartTooltip takes the following props, and the same props go to ChartTooltipContent.
| Prop | Type | Default | Description |
|---|---|---|---|
hideLabel | boolean | false | Hides the label |
hideIndicator | boolean | false | Hides the indicator |
indicator | 'dot' \| 'line' \| 'dashed' | 'dot' | The indicator style |
label | string | The label text. A config key is replaced by its label | |
labelKey | string | A config key, or a data field that holds one, whose label becomes the label | |
nameKey | string | The data field that holds the config key of each row, for charts whose series key is not the config key | |
labelFormatter | (value, items) => string \| number | Formats the label | |
formatter | Snippet<[{ item, data, index, name, value }]> | Replaces the content of a row. data is the hovered data row | |
color | string | The indicator color of every row | |
labelClass | string | Added to the label | |
class | string | Added to the tooltip | |
children | Snippet<[{ data }]> | Replaces the whole tooltip |
Colors
Colors come from the chart config. The indicator uses the color of the config key of each row.
Custom
A pie or a radial chart has one series, and each slice is a row. Use nameKey to name the data field that holds the config key of the slice.
const chartData = [
{ browser: 'chrome', visitors: 187, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' }
];
const chartConfig = {
visitors: { label: 'Total Visitors' },
chrome: { label: 'Chrome', color: 'var(--chart-1)' },
safari: { label: 'Safari', color: 'var(--chart-2)' }
} satisfies ChartConfig;<ChartTooltip hideLabel nameKey="browser" />The tooltip names the rows Chrome and Safari. Add labelKey="visitors" to use Total Visitors as the label.
Legend
Render the ChartLegend component in the legend snippet of a chart to add a legend. The snippet also reserves room below the plot in area, bar, and line charts.
<script lang="ts">
import { ChartLegend } from '$lib/components/ui/chart';
</script>
<BarChart {data} x="month" series={series}>
{#snippet legend()}
<ChartLegend />
{/snippet}
</BarChart>Use the legend snippet instead of the legend prop of LayerChart. Svelte reports an error when a component gets both.
Pie, radial, and radar charts do not reserve room for the snippet. Pass padding to the chart, for example padding={{ bottom: 32 }}, to keep the legend off the plot.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
hideIcon | boolean | false | Shows a color swatch even when the config has an icon |
nameKey | string | The data field that names each item, for charts whose items are rows (pie, radial) instead of series | |
verticalAlign | 'top' \| 'bottom' | 'bottom' | The side of the chart that holds the legend |
class | string | Added to the legend | |
children | Snippet | Replaces the legend |
Colors
Colors come from the chart config, in the order of the series.
Custom
Use nameKey to name the data field that holds the config key of each item.
const chartData = [
{ browser: 'chrome', visitors: 187, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' }
];
const chartConfig = {
chrome: { label: 'Chrome', color: 'var(--chart-1)' },
safari: { label: 'Safari', color: 'var(--chart-2)' }
} satisfies ChartConfig;<ChartLegend nameKey="browser" />The legend names the items Chrome and Safari.
Accessibility
A LayerChart chart is an SVG, and the marks of the chart have no text alternative. Describe what the chart shows with aria-label on the ChartContainer, and give a table or text version when readers need the exact values.
A chart that has a ChartTooltip is reachable with the keyboard. The container becomes a focusable element with role="application" and aria-roledescription="chart", and it steps through the rows of the chart. The tooltip hides when the chart loses focus.
| Key | Action |
|---|---|
| Arrow Right, Arrow Down | Show the tooltip of the next row |
| Arrow Left, Arrow Up | Show the tooltip of the previous row |
| Home, End | Show the tooltip of the first or the last row |
| Escape | Hide the tooltip |
API reference
ChartContainer
| Prop | Type | Default | Description |
|---|---|---|---|
config | ChartConfig | Required. The label, icon, and color or theme of each key | |
class | string | Added to the container. It is aspect-video by default |
ChartContainer passes every other attribute to its div. Give it an aria-label.
ChartTooltip and ChartLegend
See the props of the tooltip and of the legend.
ChartConfig
| Field | Type | Description |
|---|---|---|
label | string | The name shown in the tooltip and the legend |
icon | Component | Shown in place of the color swatch |
color | string | Any CSS color. Not allowed with theme |
theme | { light: string; dark: string } | A color for each mode. Not allowed with color |
Examples
<script lang="ts">
import { scaleBand, scaleUtc } from 'd3-scale';
import { curveLinearClosed, curveNatural } from 'd3-shape';
import { cubicInOut } from 'svelte/easing';
import { AreaChart, ArcChart, BarChart, LineChart, PieChart, Text, type ChartContextValue } from 'layerchart';
import { Example, ExampleWrapper } from '@sveltery/components/example';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const monthly = [
{ month: 'January', desktop: 186, mobile: 80 },
{ month: 'February', desktop: 305, mobile: 200 },
{ month: 'March', desktop: 237, mobile: 120 },
{ month: 'April', desktop: 73, mobile: 190 },
{ month: 'May', desktop: 209, mobile: 130 },
{ month: 'June', desktop: 214, mobile: 140 },
];
const dated = monthly.map((row, index) => ({ ...row, date: new Date(Date.UTC(2024, index, 1)) }));
const shortMonth = (value: Date) => value.toLocaleDateString('en-US', { month: 'short', timeZone: 'UTC' });
const longMonth = (value: Date) => value.toLocaleDateString('en-US', { month: 'long', timeZone: 'UTC' });
const visitorsConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
const deviceConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
const pieData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 287, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 190, color: 'var(--color-other)' },
];
const pieConfig = {
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;
const totalVisitors = pieData.reduce((total, row) => total + row.visitors, 0);
const radialData = [{ browser: 'safari', visitors: 1260, color: 'var(--color-safari)' }];
const radialConfig = {
visitors: { label: 'Visitors' },
safari: { label: 'Safari', color: 'var(--chart-2)' },
} satisfies ChartConfig;
let barContext = $state<ChartContextValue>();
</script>
{#snippet trend(detail: string)}
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="flex items-center gap-2 leading-none text-muted-foreground">{detail}</div>
{/snippet}
{#snippet ChartAreaExample()}
<Example title="Area Chart">
<Card class="w-full">
<CardHeader>
<CardTitle>Area Chart</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Area Chart" config={visitorsConfig}>
<AreaChart
data={dated}
x="date"
xScale={scaleUtc()}
series={[{ key: 'desktop', label: 'Desktop', color: 'var(--color-desktop)' }]}
axis="x"
props={{
area: { curve: curveNatural, 'fill-opacity': 0.4, line: { class: 'stroke-1' }, motion: 'tween' },
xAxis: { format: shortMonth },
}}
>
{#snippet tooltip()}
<ChartTooltip labelFormatter={longMonth} indicator="line" />
{/snippet}
</AreaChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="grid gap-2 text-sm">{@render trend('January - June 2024')}</div>
</CardFooter>
</Card>
</Example>
{/snippet}
{#snippet ChartBarExample()}
<Example title="Bar Chart">
<Card class="w-full">
<CardHeader>
<CardTitle>Bar Chart - Multiple</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Bar Chart - Multiple" config={deviceConfig}>
<BarChart
bind:context={barContext}
data={monthly}
xScale={scaleBand().padding(0.25)}
x="month"
axis="x"
series={[
{ key: 'desktop', label: 'Desktop', color: 'var(--color-desktop)' },
{ key: 'mobile', label: 'Mobile', color: 'var(--color-mobile)' },
]}
x1Scale={scaleBand().paddingInner(0.2)}
seriesLayout="group"
rule={false}
props={{
bars: {
stroke: 'none',
strokeWidth: 0,
rounded: 'all',
initialY: barContext?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
highlight: { area: { fill: 'none' } },
xAxis: { format: (month: string) => month.slice(0, 3) },
}}
>
{#snippet tooltip()}
<ChartTooltip indicator="dashed" />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col items-start gap-2 text-sm">
{@render trend('Showing total visitors for the last 6 months')}
</CardFooter>
</Card>
</Example>
{/snippet}
{#snippet ChartLineExample()}
<Example title="Line Chart">
<Card class="w-full">
<CardHeader>
<CardTitle>Line Chart - Multiple</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Line Chart - Multiple" config={deviceConfig}>
<LineChart
data={dated}
x="date"
xScale={scaleUtc()}
axis="x"
series={[
{ key: 'desktop', label: 'Desktop', color: 'var(--color-desktop)' },
{ key: 'mobile', label: 'Mobile', color: 'var(--color-mobile)' },
]}
props={{
spline: { curve: curveNatural, motion: 'tween', strokeWidth: 2 },
xAxis: { format: shortMonth },
highlight: { points: { r: 4 } },
}}
>
{#snippet tooltip()}
<ChartTooltip labelFormatter={longMonth} />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="grid gap-2 text-sm">{@render trend('Showing total visitors for the last 6 months')}</div>
</CardFooter>
</Card>
</Example>
{/snippet}
{#snippet ChartPieExample()}
<Example title="Pie Chart">
<Card class="w-full">
<CardHeader class="items-center pb-0">
<CardTitle>Pie Chart - Donut with Text</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1 pb-0">
<ChartContainer aria-label="Pie Chart - Donut with Text" config={pieConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
data={pieData}
key="browser"
value="visitors"
c="color"
innerRadius={60}
padding={28}
props={{ pie: { motion: 'tween' } }}
>
{#snippet aboveMarks()}
<Text
value={totalVisitors.toLocaleString()}
textAnchor="middle"
verticalAnchor="middle"
class="fill-foreground text-3xl! font-bold"
dy={3}
/>
<Text
value="Visitors"
textAnchor="middle"
verticalAnchor="middle"
class="fill-muted-foreground! text-muted-foreground"
dy={22}
/>
{/snippet}
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
{@render trend('Showing total visitors for the last 6 months')}
</CardFooter>
</Card>
</Example>
{/snippet}
{#snippet ChartRadialExample()}
<Example title="Radial Chart">
<Card class="w-full">
<CardHeader>
<CardTitle>Radial Chart - Shape</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1 pb-0">
<ChartContainer aria-label="Radial Chart - Shape" config={radialConfig} class="mx-auto aspect-square max-h-[250px]">
<ArcChart
label="browser"
value="visitors"
outerRadius={88}
innerRadius={66}
trackOuterRadius={83}
trackInnerRadius={72}
padding={40}
range={[90, -270]}
maxValue={radialData[0].visitors * 4}
series={radialData.map((row) => ({ key: row.browser, color: row.color, data: [row] }))}
props={{
arc: { track: { fill: 'var(--muted)' }, motion: 'tween' },
tooltip: { context: { hideDelay: 350 } },
}}
tooltipContext={false}
>
{#snippet belowMarks()}
<circle cx="0" cy="0" r="80" class="fill-background" />
{/snippet}
{#snippet aboveMarks()}
<Text
value={radialData[0].visitors.toLocaleString()}
textAnchor="middle"
verticalAnchor="middle"
class="fill-foreground text-4xl! font-bold"
dy={3}
/>
<Text value="Visitors" textAnchor="middle" verticalAnchor="middle" class="fill-muted-foreground!" dy={22} />
{/snippet}
</ArcChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
{@render trend('Showing total visitors for the last 6 months')}
</CardFooter>
</Card>
</Example>
{/snippet}
{#snippet ChartRadarExample()}
<Example title="Radar Chart">
<Card class="w-full">
<CardHeader class="items-center pb-4">
<CardTitle>Radar Chart - Multiple</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="pb-0">
<ChartContainer aria-label="Radar Chart - Multiple" config={deviceConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={monthly}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
props: { fill: 'var(--color-desktop)', fillOpacity: 0.6 },
},
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
props: { fill: 'var(--color-mobile)' },
},
]}
radial
x="month"
xScale={scaleBand()}
padding={12}
props={{
spline: { curve: curveLinearClosed, stroke: '0', motion: 'tween' },
xAxis: { tickLength: 0 },
yAxis: { format: () => '' },
grid: { radialY: 'linear' },
tooltip: { context: { mode: 'band' } },
highlight: { lines: false, points: { r: 4 } },
}}
>
{#snippet tooltip()}
<ChartTooltip indicator="line" />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
{@render trend('January - June 2024')}
</CardFooter>
</Card>
</Example>
{/snippet}
<ExampleWrapper class="lg:grid-cols-1">
{@render ChartAreaExample()}
{@render ChartBarExample()}
{@render ChartLineExample()}
{@render ChartPieExample()}
{@render ChartRadialExample()}
{@render ChartRadarExample()}
</ExampleWrapper>Area
Area Chart
<script lang="ts">
import { AreaChart } from 'layerchart';
import { curveNatural } from 'd3-shape';
import { scaleUtc } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186 },
{ date: new Date('2024-02-01'), desktop: 305 },
{ date: new Date('2024-03-01'), desktop: 237 },
{ date: new Date('2024-04-01'), desktop: 73 },
{ date: new Date('2024-05-01'), desktop: 209 },
{ date: new Date('2024-06-01'), desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Area Chart</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Area Chart" config={chartConfig}>
<AreaChart
data={chartData}
x="date"
xScale={scaleUtc()}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
axis="x"
props={{
area: {
curve: curveNatural,
'fill-opacity': 0.4,
line: { class: 'stroke-1' },
motion: 'tween',
},
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
}}
>
{#snippet tooltip()}
<ChartTooltip
labelFormatter={(v: Date) =>
v.toLocaleDateString('en-US', { month: 'long' })}
indicator="line"
/>
{/snippet}
</AreaChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Area Chart - Linear
<script lang="ts">
import { AreaChart } from 'layerchart';
import { curveLinear } from 'd3-shape';
import { scaleUtc } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186 },
{ date: new Date('2024-02-01'), desktop: 305 },
{ date: new Date('2024-03-01'), desktop: 237 },
{ date: new Date('2024-04-01'), desktop: 73 },
{ date: new Date('2024-05-01'), desktop: 209 },
{ date: new Date('2024-06-01'), desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Area Chart - Linear</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Area Chart - Linear" config={chartConfig}>
<AreaChart
data={chartData}
x="date"
xScale={scaleUtc()}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
seriesLayout="stack"
props={{
area: {
curve: curveLinear,
'fill-opacity': 0.4,
line: { class: 'stroke-1' },
motion: 'tween',
},
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
yAxis: { format: () => '' },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</AreaChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Area Chart - Step
<script lang="ts">
import { AreaChart } from 'layerchart';
import { curveStep } from 'd3-shape';
import { scaleUtc } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import ActivityIcon from './icons/ActivityIcon.svelte';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186 },
{ date: new Date('2024-02-01'), desktop: 305 },
{ date: new Date('2024-03-01'), desktop: 237 },
{ date: new Date('2024-04-01'), desktop: 73 },
{ date: new Date('2024-05-01'), desktop: 209 },
{ date: new Date('2024-06-01'), desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)', icon: ActivityIcon },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Area Chart - Step</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Area Chart - Step" config={chartConfig}>
<AreaChart
data={chartData}
x="date"
xScale={scaleUtc()}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
seriesLayout="stack"
props={{
area: {
curve: curveStep,
'fill-opacity': 0.4,
line: { class: 'stroke-1' },
motion: 'tween',
},
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
yAxis: { format: () => '' },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</AreaChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Area Chart - Legend
<script lang="ts">
import { AreaChart } from 'layerchart';
import { curveNatural } from 'd3-shape';
import { scaleUtc } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartLegend, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186, mobile: 80 },
{ date: new Date('2024-02-01'), desktop: 305, mobile: 200 },
{ date: new Date('2024-03-01'), desktop: 237, mobile: 120 },
{ date: new Date('2024-04-01'), desktop: 73, mobile: 190 },
{ date: new Date('2024-05-01'), desktop: 209, mobile: 130 },
{ date: new Date('2024-06-01'), desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Area Chart - Legend</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Area Chart - Legend" config={chartConfig}>
<AreaChart
data={chartData}
x="date"
xScale={scaleUtc()}
yPadding={[0, 25]}
series={[
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
},
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
seriesLayout="stack"
props={{
area: {
curve: curveNatural,
'fill-opacity': 0.4,
line: { class: 'stroke-1' },
motion: 'tween',
},
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
yAxis: { format: () => '' },
}}
>
{#snippet tooltip()}
<ChartTooltip
labelFormatter={(v: Date) => {
return v.toLocaleDateString('en-US', {
month: 'long',
});
}}
indicator="line"
/>
{/snippet}
{#snippet legend()}
<ChartLegend />
{/snippet}
</AreaChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Area Chart - Stacked
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { scaleUtc } from 'd3-scale';
import { curveNatural } from 'd3-shape';
import { AreaChart } from 'layerchart';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186, mobile: 80 },
{ date: new Date('2024-02-01'), desktop: 305, mobile: 200 },
{ date: new Date('2024-03-01'), desktop: 237, mobile: 120 },
{ date: new Date('2024-04-01'), desktop: 73, mobile: 190 },
{ date: new Date('2024-05-01'), desktop: 209, mobile: 130 },
{ date: new Date('2024-06-01'), desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Area Chart - Stacked</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Area Chart - Stacked" config={chartConfig}>
<AreaChart
data={chartData}
x="date"
xScale={scaleUtc()}
yPadding={[0, 25]}
axis="x"
series={[
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
},
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
seriesLayout="stack"
props={{
area: {
curve: curveNatural,
'fill-opacity': 0.4,
line: { class: 'stroke-1' },
motion: 'tween',
},
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
}}
>
{#snippet tooltip()}
<ChartTooltip
indicator="dot"
labelFormatter={(v: Date) => {
return v.toLocaleDateString('en-US', {
month: 'long',
});
}}
/>
{/snippet}
</AreaChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Area Chart - Stacked Expanded
<script lang="ts">
import { AreaChart } from 'layerchart';
import { curveNatural } from 'd3-shape';
import { scaleUtc } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186, mobile: 80, other: 45 },
{ date: new Date('2024-02-01'), desktop: 305, mobile: 200, other: 100 },
{ date: new Date('2024-03-01'), desktop: 237, mobile: 120, other: 150 },
{ date: new Date('2024-04-01'), desktop: 73, mobile: 190, other: 50 },
{ date: new Date('2024-05-01'), desktop: 209, mobile: 130, other: 100 },
{ date: new Date('2024-06-01'), desktop: 214, mobile: 140, other: 160 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
other: { label: 'Other', color: 'var(--chart-3)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Area Chart - Stacked Expanded</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Area Chart - Stacked Expanded" config={chartConfig}>
<AreaChart
data={chartData}
x="date"
xScale={scaleUtc()}
seriesLayout="stackExpand"
axis="x"
series={[
{
key: 'other',
label: 'Other',
color: 'var(--color-other)',
props: { opacity: 0.1 },
},
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
},
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
props={{
area: {
curve: curveNatural,
'fill-opacity': 0.4,
line: { class: 'stroke-1' },
motion: 'tween',
},
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
}}
>
{#snippet tooltip()}
<ChartTooltip
labelFormatter={(v: Date) => {
return v.toLocaleDateString('en-US', {
month: 'long',
});
}}
indicator="line"
/>
{/snippet}
</AreaChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Area Chart - Icons
<script lang="ts">
import { AreaChart } from 'layerchart';
import { curveNatural } from 'd3-shape';
import { scaleUtc } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartLegend, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import TrendingDownIcon from './icons/TrendingDownIcon.svelte';
import TrendingUpIcon from './icons/TrendingUpIcon.svelte';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186, mobile: 80 },
{ date: new Date('2024-02-01'), desktop: 305, mobile: 200 },
{ date: new Date('2024-03-01'), desktop: 237, mobile: 120 },
{ date: new Date('2024-04-01'), desktop: 73, mobile: 190 },
{ date: new Date('2024-05-01'), desktop: 209, mobile: 130 },
{ date: new Date('2024-06-01'), desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)', icon: TrendingDownIcon },
mobile: { label: 'Mobile', color: 'var(--chart-2)', icon: TrendingUpIcon },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Area Chart - Icons</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Area Chart - Icons" config={chartConfig}>
<AreaChart
data={chartData}
x="date"
xScale={scaleUtc()}
series={[
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
},
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
seriesLayout="stack"
props={{
area: {
curve: curveNatural,
'fill-opacity': 0.4,
line: { class: 'stroke-1' },
motion: 'tween',
},
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
yAxis: { format: () => '' },
}}
>
{#snippet tooltip()}
<ChartTooltip
indicator="line"
labelFormatter={(v: Date) => {
return v.toLocaleDateString('en-US', {
month: 'long',
});
}}
/>
{/snippet}
{#snippet legend()}
<ChartLegend />
{/snippet}
</AreaChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Area Chart - Gradient
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { scaleUtc } from 'd3-scale';
import { curveNatural } from 'd3-shape';
import { Area, AreaChart, LinearGradient } from 'layerchart';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186, mobile: 80 },
{ date: new Date('2024-02-01'), desktop: 305, mobile: 200 },
{ date: new Date('2024-03-01'), desktop: 237, mobile: 120 },
{ date: new Date('2024-04-01'), desktop: 73, mobile: 190 },
{ date: new Date('2024-05-01'), desktop: 209, mobile: 130 },
{ date: new Date('2024-06-01'), desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Area Chart - Gradient</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Area Chart - Gradient" config={chartConfig}>
<AreaChart
data={chartData}
x="date"
xScale={scaleUtc()}
yPadding={[0, 25]}
series={[
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
},
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
seriesLayout="stack"
props={{
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
yAxis: { format: () => '' },
}}
>
{#snippet tooltip()}
<ChartTooltip
indicator="dot"
labelFormatter={(v: Date) => {
return v.toLocaleDateString('en-US', {
month: 'long',
});
}}
/>
{/snippet}
{#snippet marks({ context })}
{#each context.series.visibleSeries as s (s.key)}
<LinearGradient stops={[s.color ?? '', `color-mix(in lch, ${s.color} 10%, transparent)`]} vertical>
{#snippet children({ gradient })}
<Area seriesKey={s.key} curve={curveNatural} fill={gradient} fillOpacity={0.4} line={{ class: 'stroke-1' }} motion="tween" />
{/snippet}
</LinearGradient>
{/each}
{/snippet}
</AreaChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Area Chart - Axes
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { scaleUtc } from 'd3-scale';
import { curveNatural } from 'd3-shape';
import { AreaChart } from 'layerchart';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186, mobile: 80 },
{ date: new Date('2024-02-01'), desktop: 305, mobile: 200 },
{ date: new Date('2024-03-01'), desktop: 237, mobile: 120 },
{ date: new Date('2024-04-01'), desktop: 73, mobile: 190 },
{ date: new Date('2024-05-01'), desktop: 209, mobile: 130 },
{ date: new Date('2024-06-01'), desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Area Chart - Axes</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Area Chart - Axes" config={chartConfig}>
<AreaChart
data={chartData}
x="date"
xScale={scaleUtc()}
yDomain={[0, 600]}
series={[
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
},
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
seriesLayout="stack"
props={{
area: {
curve: curveNatural,
'fill-opacity': 0.4,
line: { class: 'stroke-1' },
motion: 'tween',
},
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
yAxis: { ticks: [0, 300, 600] },
}}
>
{#snippet tooltip()}
<ChartTooltip
labelFormatter={(v: Date) => {
return v.toLocaleDateString('en-US', {
month: 'long',
});
}}
indicator="dot"
/>
{/snippet}
</AreaChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Area Chart - Interactive
<script lang="ts">
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartLegend, ChartTooltip } from '@sveltery/components/chart';
import { scaleUtc } from 'd3-scale';
import { NativeSelect, NativeSelectOption } from '@sveltery/components/native-select';
import { Area, AreaChart, ChartClipPath } from 'layerchart';
import { curveNatural } from 'd3-shape';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ date: new Date('2024-04-01'), desktop: 222, mobile: 150 },
{ date: new Date('2024-04-02'), desktop: 97, mobile: 180 },
{ date: new Date('2024-04-03'), desktop: 167, mobile: 120 },
{ date: new Date('2024-04-04'), desktop: 242, mobile: 260 },
{ date: new Date('2024-04-05'), desktop: 373, mobile: 290 },
{ date: new Date('2024-04-06'), desktop: 301, mobile: 340 },
{ date: new Date('2024-04-07'), desktop: 245, mobile: 180 },
{ date: new Date('2024-04-08'), desktop: 409, mobile: 320 },
{ date: new Date('2024-04-09'), desktop: 59, mobile: 110 },
{ date: new Date('2024-04-10'), desktop: 261, mobile: 190 },
{ date: new Date('2024-04-11'), desktop: 327, mobile: 350 },
{ date: new Date('2024-04-12'), desktop: 292, mobile: 210 },
{ date: new Date('2024-04-13'), desktop: 342, mobile: 380 },
{ date: new Date('2024-04-14'), desktop: 137, mobile: 220 },
{ date: new Date('2024-04-15'), desktop: 120, mobile: 170 },
{ date: new Date('2024-04-16'), desktop: 138, mobile: 190 },
{ date: new Date('2024-04-17'), desktop: 446, mobile: 360 },
{ date: new Date('2024-04-18'), desktop: 364, mobile: 410 },
{ date: new Date('2024-04-19'), desktop: 243, mobile: 180 },
{ date: new Date('2024-04-20'), desktop: 89, mobile: 150 },
{ date: new Date('2024-04-21'), desktop: 137, mobile: 200 },
{ date: new Date('2024-04-22'), desktop: 224, mobile: 170 },
{ date: new Date('2024-04-23'), desktop: 138, mobile: 230 },
{ date: new Date('2024-04-24'), desktop: 387, mobile: 290 },
{ date: new Date('2024-04-25'), desktop: 215, mobile: 250 },
{ date: new Date('2024-04-26'), desktop: 75, mobile: 130 },
{ date: new Date('2024-04-27'), desktop: 383, mobile: 420 },
{ date: new Date('2024-04-28'), desktop: 122, mobile: 180 },
{ date: new Date('2024-04-29'), desktop: 315, mobile: 240 },
{ date: new Date('2024-04-30'), desktop: 454, mobile: 380 },
{ date: new Date('2024-05-01'), desktop: 165, mobile: 220 },
{ date: new Date('2024-05-02'), desktop: 293, mobile: 310 },
{ date: new Date('2024-05-03'), desktop: 247, mobile: 190 },
{ date: new Date('2024-05-04'), desktop: 385, mobile: 420 },
{ date: new Date('2024-05-05'), desktop: 481, mobile: 390 },
{ date: new Date('2024-05-06'), desktop: 498, mobile: 520 },
{ date: new Date('2024-05-07'), desktop: 388, mobile: 300 },
{ date: new Date('2024-05-08'), desktop: 149, mobile: 210 },
{ date: new Date('2024-05-09'), desktop: 227, mobile: 180 },
{ date: new Date('2024-05-10'), desktop: 293, mobile: 330 },
{ date: new Date('2024-05-11'), desktop: 335, mobile: 270 },
{ date: new Date('2024-05-12'), desktop: 197, mobile: 240 },
{ date: new Date('2024-05-13'), desktop: 197, mobile: 160 },
{ date: new Date('2024-05-14'), desktop: 448, mobile: 490 },
{ date: new Date('2024-05-15'), desktop: 473, mobile: 380 },
{ date: new Date('2024-05-16'), desktop: 338, mobile: 400 },
{ date: new Date('2024-05-17'), desktop: 499, mobile: 420 },
{ date: new Date('2024-05-18'), desktop: 315, mobile: 350 },
{ date: new Date('2024-05-19'), desktop: 235, mobile: 180 },
{ date: new Date('2024-05-20'), desktop: 177, mobile: 230 },
{ date: new Date('2024-05-21'), desktop: 82, mobile: 140 },
{ date: new Date('2024-05-22'), desktop: 81, mobile: 120 },
{ date: new Date('2024-05-23'), desktop: 252, mobile: 290 },
{ date: new Date('2024-05-24'), desktop: 294, mobile: 220 },
{ date: new Date('2024-05-25'), desktop: 201, mobile: 250 },
{ date: new Date('2024-05-26'), desktop: 213, mobile: 170 },
{ date: new Date('2024-05-27'), desktop: 420, mobile: 460 },
{ date: new Date('2024-05-28'), desktop: 233, mobile: 190 },
{ date: new Date('2024-05-29'), desktop: 78, mobile: 130 },
{ date: new Date('2024-05-30'), desktop: 340, mobile: 280 },
{ date: new Date('2024-05-31'), desktop: 178, mobile: 230 },
{ date: new Date('2024-06-01'), desktop: 178, mobile: 200 },
{ date: new Date('2024-06-02'), desktop: 470, mobile: 410 },
{ date: new Date('2024-06-03'), desktop: 103, mobile: 160 },
{ date: new Date('2024-06-04'), desktop: 439, mobile: 380 },
{ date: new Date('2024-06-05'), desktop: 88, mobile: 140 },
{ date: new Date('2024-06-06'), desktop: 294, mobile: 250 },
{ date: new Date('2024-06-07'), desktop: 323, mobile: 370 },
{ date: new Date('2024-06-08'), desktop: 385, mobile: 320 },
{ date: new Date('2024-06-09'), desktop: 438, mobile: 480 },
{ date: new Date('2024-06-10'), desktop: 155, mobile: 200 },
{ date: new Date('2024-06-11'), desktop: 92, mobile: 150 },
{ date: new Date('2024-06-12'), desktop: 492, mobile: 420 },
{ date: new Date('2024-06-13'), desktop: 81, mobile: 130 },
{ date: new Date('2024-06-14'), desktop: 426, mobile: 380 },
{ date: new Date('2024-06-15'), desktop: 307, mobile: 350 },
{ date: new Date('2024-06-16'), desktop: 371, mobile: 310 },
{ date: new Date('2024-06-17'), desktop: 475, mobile: 520 },
{ date: new Date('2024-06-18'), desktop: 107, mobile: 170 },
{ date: new Date('2024-06-19'), desktop: 341, mobile: 290 },
{ date: new Date('2024-06-20'), desktop: 408, mobile: 450 },
{ date: new Date('2024-06-21'), desktop: 169, mobile: 210 },
{ date: new Date('2024-06-22'), desktop: 317, mobile: 270 },
{ date: new Date('2024-06-23'), desktop: 480, mobile: 530 },
{ date: new Date('2024-06-24'), desktop: 132, mobile: 180 },
{ date: new Date('2024-06-25'), desktop: 141, mobile: 190 },
{ date: new Date('2024-06-26'), desktop: 434, mobile: 380 },
{ date: new Date('2024-06-27'), desktop: 448, mobile: 490 },
{ date: new Date('2024-06-28'), desktop: 149, mobile: 200 },
{ date: new Date('2024-06-29'), desktop: 103, mobile: 160 },
{ date: new Date('2024-06-30'), desktop: 446, mobile: 400 },
];
let timeRange = $state('90d');
const filteredData = $derived(
chartData.filter((item) => {
// eslint-disable-next-line svelte/prefer-svelte-reactivity
const referenceDate = new Date('2024-06-30');
let daysToSubtract = 90;
if (timeRange === '30d') {
daysToSubtract = 30;
} else if (timeRange === '7d') {
daysToSubtract = 7;
}
referenceDate.setDate(referenceDate.getDate() - daysToSubtract);
return item.date >= referenceDate;
})
);
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-3xl">
<CardHeader class="flex items-center gap-2 space-y-0 border-b py-5 sm:flex-row">
<div class="grid flex-1 gap-1 text-center sm:text-start">
<CardTitle>Area Chart - Interactive</CardTitle>
<CardDescription>Showing total visitors for the last 3 months</CardDescription>
</div>
<NativeSelect bind:value={timeRange} class="sm:ms-auto" aria-label="Select a time range">
<NativeSelectOption value="90d">Last 3 months</NativeSelectOption>
<NativeSelectOption value="30d">Last 30 days</NativeSelectOption>
<NativeSelectOption value="7d">Last 7 days</NativeSelectOption>
</NativeSelect>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Area Chart - Interactive" config={chartConfig} class="-ml-3 aspect-auto h-[250px] w-full">
<AreaChart
data={filteredData}
x="date"
xScale={scaleUtc()}
series={[
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
},
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
seriesLayout="stack"
props={{
xAxis: {
ticks: timeRange === '7d' ? 7 : undefined,
format: (v) => {
return v.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
});
},
},
yAxis: { format: () => '' },
}}
>
{#snippet marks({ context })}
<defs>
<linearGradient id="fillDesktop" x1="0" y1="0" x2="0" y2="1">
<stop
offset="5%"
stop-color="var(--color-desktop)"
stop-opacity={1.0}
/>
<stop
offset="95%"
stop-color="var(--color-desktop)"
stop-opacity={0.1}
/>
</linearGradient>
<linearGradient id="fillMobile" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stop-color="var(--color-mobile)" stop-opacity={0.8} />
<stop
offset="95%"
stop-color="var(--color-mobile)"
stop-opacity={0.1}
/>
</linearGradient>
</defs>
<ChartClipPath
initialWidth={0}
motion={{
width: { type: 'tween', duration: 1000, easing: cubicInOut },
}}
>
{#each context.series.visibleSeries as s (s.key)}
<Area
seriesKey={s.key}
curve={curveNatural}
fillOpacity={0.4}
line={{ class: 'stroke-1' }}
motion="tween"
fill={s.key === 'desktop' ? 'url(#fillDesktop)' : 'url(#fillMobile)'}
/>
{/each}
</ChartClipPath>
{/snippet}
{#snippet tooltip()}
<ChartTooltip
labelFormatter={(v: Date) => {
return v.toLocaleDateString('en-US', {
month: 'long',
});
}}
indicator="dot"
/>
{/snippet}
{#snippet legend()}
<ChartLegend />
{/snippet}
</AreaChart>
</ChartContainer>
</CardContent>
</Card>Bar
Bar Chart
<script lang="ts">
import { scaleBand } from 'd3-scale';
import { BarChart, type ChartContextValue } from 'layerchart';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ month: 'January', desktop: 186 },
{ month: 'February', desktop: 305 },
{ month: 'March', desktop: 237 },
{ month: 'April', desktop: 73 },
{ month: 'May', desktop: 209 },
{ month: 'June', desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Bar Chart</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Bar Chart" config={chartConfig}>
<BarChart
bind:context
data={chartData}
xScale={scaleBand().padding(0.25)}
x="month"
axis="x"
series={[{ key: 'desktop', label: 'Desktop', color: 'var(--color-desktop)' }]}
props={{
bars: {
stroke: 'none',
rounded: 'all',
radius: 8,
// use the height of the chart to animate the bars
initialY: context?.height,
initialHeight: 0,
motion: {
x: { type: 'tween', duration: 500, easing: cubicInOut },
width: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
y: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
highlight: { area: { fill: 'none' } },
xAxis: { format: (d) => d.slice(0, 3) },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
Showing total visitors for the last 6 months
</div>
</div>
</div>
</CardFooter>
</Card>Bar Chart - Horizontal
<script lang="ts">
import { BarChart } from 'layerchart';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ month: 'January', desktop: 186 },
{ month: 'February', desktop: 305 },
{ month: 'March', desktop: 237 },
{ month: 'April', desktop: 73 },
{ month: 'May', desktop: 209 },
{ month: 'June', desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Bar Chart - Horizontal</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Bar Chart - Horizontal" config={chartConfig}>
<BarChart
data={chartData}
orientation="horizontal"
yScale={scaleBand().padding(0.25)}
y="month"
series={[{ key: 'desktop', label: 'Desktop', color: 'var(--color-desktop)' }]}
padding={{ left: 20 }}
grid={false}
rule={false}
axis="y"
props={{
bars: {
stroke: 'none',
radius: 5,
insets: {
left: 24,
},
rounded: 'all',
initialWidth: 0,
initialX: 0,
motion: {
x: { type: 'tween', duration: 500, easing: cubicInOut },
width: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
highlight: { area: { fill: 'none' } },
yAxis: { format: (d) => d.slice(0, 3) },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
Showing total visitors for the last 6 months
</div>
</div>
</div>
</CardFooter>
</Card>Bar Chart - Multiple
<script lang="ts">
import { scaleBand } from 'd3-scale';
import { BarChart, type ChartContextValue } from 'layerchart';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ month: 'January', desktop: 186, mobile: 80 },
{ month: 'February', desktop: 305, mobile: 200 },
{ month: 'March', desktop: 237, mobile: 120 },
{ month: 'April', desktop: 73, mobile: 190 },
{ month: 'May', desktop: 209, mobile: 130 },
{ month: 'June', desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Bar Chart - Multiple</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Bar Chart - Multiple" config={chartConfig}>
<BarChart
bind:context
data={chartData}
xScale={scaleBand().padding(0.25)}
x="month"
axis="x"
series={[
{ key: 'desktop', label: 'Desktop', color: 'var(--color-desktop)' },
{ key: 'mobile', label: 'Mobile', color: 'var(--color-mobile)' },
]}
x1Scale={scaleBand().paddingInner(0.2)}
seriesLayout="group"
rule={false}
props={{
bars: {
stroke: 'none',
strokeWidth: 0,
rounded: 'all',
// use the height of the chart to animate the bars
initialY: context?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
highlight: { area: { fill: 'none' } },
xAxis: { format: (d) => d.slice(0, 3) },
}}
>
{#snippet tooltip()}
<ChartTooltip indicator="dashed" />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
Showing total visitors for the last 6 months
</div>
</div>
</div>
</CardFooter>
</Card>Bar Chart - Label
<script lang="ts">
import { scaleBand } from 'd3-scale';
import { BarChart, type ChartContextValue } from 'layerchart';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ month: 'January', desktop: 186 },
{ month: 'February', desktop: 305 },
{ month: 'March', desktop: 237 },
{ month: 'April', desktop: 73 },
{ month: 'May', desktop: 209 },
{ month: 'June', desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Bar Chart - Label</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Bar Chart - Label" config={chartConfig}>
<BarChart
labels={{ offset: 12 }}
data={chartData}
xScale={scaleBand().padding(0.25)}
x="month"
series={[{ key: 'desktop', label: 'Desktop', color: 'var(--color-desktop)' }]}
axis="x"
rule={false}
props={{
bars: {
stroke: 'none',
radius: 8,
rounded: 'all',
// use the height of the chart to animate the bars
initialY: (context?.height ?? 0) + 180,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
highlight: { area: { fill: 'none' } },
xAxis: { format: (d) => d.slice(0, 3) },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
Showing total visitors for the last 6 months
</div>
</div>
</div>
</CardFooter>
</Card>Bar Chart - Custom Label
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { BarChart } from 'layerchart';
import { scaleBand } from 'd3-scale';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ month: 'January', desktop: 186, mobile: 80 },
{ month: 'February', desktop: 305, mobile: 200 },
{ month: 'March', desktop: 237, mobile: 120 },
{ month: 'April', desktop: 73, mobile: 190 },
{ month: 'May', desktop: 209, mobile: 130 },
{ month: 'June', desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
label: { color: 'var(--background)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Bar Chart - Custom Label</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Bar Chart - Custom Label" config={chartConfig}>
<BarChart
labels={{ offset: 12 }}
data={chartData}
orientation="horizontal"
yScale={scaleBand().padding(0.25)}
y="month"
axis="y"
rule={false}
series={[{ key: 'desktop', label: 'Desktop', color: 'var(--color-desktop)' }]}
padding={{ right: 16 }}
props={{
bars: {
stroke: 'none',
radius: 5,
rounded: 'all',
initialWidth: 0,
initialX: 0,
motion: {
x: { type: 'tween', duration: 500, easing: cubicInOut },
width: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
highlight: { area: { fill: 'none' } },
yAxis: {
tickLabelProps: {
textAnchor: 'start',
dx: 6,
class: 'stroke-none fill-background!',
},
tickLength: 0,
},
}}
>
{#snippet tooltip()}
<ChartTooltip indicator="line" />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
Showing total visitors for the last 6 months
</div>
</div>
</div>
</CardFooter>
</Card>Bar Chart - Mixed
<script lang="ts">
import { BarChart } from 'layerchart';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 187, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 90, color: '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;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Bar Chart - Mixed</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Bar Chart - Mixed" config={chartConfig}>
<BarChart
data={chartData}
orientation="horizontal"
yScale={scaleBand().padding(0.25)}
y="browser"
x="visitors"
cRange={chartData.map((c) => c.color)}
c="color"
padding={{ left: 48 }}
grid={false}
rule={false}
axis="y"
props={{
bars: {
stroke: 'none',
radius: 5,
rounded: 'all',
initialWidth: 0,
initialX: 0,
motion: {
x: { type: 'tween', duration: 500, easing: cubicInOut },
width: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
highlight: { area: { fill: 'none' } },
yAxis: {
format: (d) => chartConfig[d as keyof typeof chartConfig].label,
tickLabelProps: {
svgProps: {
x: -16,
},
},
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="visitors" />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
Showing total visitors for the last 6 months
</div>
</div>
</div>
</CardFooter>
</Card>Bar Chart - Active
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { scaleBand } from 'd3-scale';
import { Bar, BarChart } from 'layerchart';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ browser: 'chrome', visitors: 187, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 275, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 90, color: '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;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Bar Chart - Active</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Bar Chart - Active" config={chartConfig}>
<BarChart
data={chartData}
x="browser"
c="color"
y="visitors"
cRange={chartData.map((c) => c.color)}
xScale={scaleBand().padding(0.25)}
axis="x"
rule={false}
props={{
xAxis: {
format: (d) => chartConfig[d as keyof typeof chartConfig].label,
},
highlight: { area: { fill: 'none' } },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="visitors" />
{/snippet}
{#snippet marks({ context })}
{#each chartData as data, i (data.browser)}
<Bar
{data}
fill={data.color}
radius={8}
rounded="all"
initialY={context.height}
initialHeight={0}
motion={{
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
}}
fillOpacity={i === 2 ? 0.8 : undefined}
stroke={i === 2 ? data.color : undefined}
strokeWidth={i === 2 ? 2 : undefined}
stroke-dasharray={i === 2 ? 4 : undefined}
stroke-dashoffset={i === 2 ? 4 : undefined}
/>
{/each}
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
Showing total visitors for the last 6 months
</div>
</div>
</div>
</CardFooter>
</Card>Bar Chart - Stacked + Legend
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartLegend, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { scaleBand } from 'd3-scale';
import { BarChart, Highlight, type ChartContextValue } from 'layerchart';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ month: 'January', desktop: 186, mobile: 80 },
{ month: 'February', desktop: 305, mobile: 200 },
{ month: 'March', desktop: 237, mobile: 120 },
{ month: 'April', desktop: 73, mobile: 190 },
{ month: 'May', desktop: 209, mobile: 130 },
{ month: 'June', desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Bar Chart - Stacked + Legend</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Bar Chart - Stacked + Legend" config={chartConfig}>
<BarChart
bind:context
data={chartData}
xScale={scaleBand().padding(0.25)}
x="month"
axis="x"
rule={false}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
props: { rounded: 'bottom' },
},
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
},
]}
seriesLayout="stack"
props={{
bars: {
stroke: 'none',
initialY: context?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
highlight: { area: false },
xAxis: { format: (d) => d.slice(0, 3) },
}}
>
{#snippet belowMarks()}
<Highlight area={{ class: 'fill-muted' }} />
{/snippet}
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
{#snippet legend()}
<ChartLegend />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
Showing total visitors for the last 6 months
</div>
</div>
</div>
</CardFooter>
</Card>Bar Chart - Negative
<script lang="ts">
import { scaleBand } from 'd3-scale';
import { BarChart } from 'layerchart';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', visitors: 186 },
{ month: 'February', visitors: 205 },
{ month: 'March', visitors: -207 },
{ month: 'April', visitors: 173 },
{ month: 'May', visitors: -209 },
{ month: 'June', visitors: 214 },
];
const chartConfig = {
visitors: { label: 'Visitors' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Bar Chart - Negative</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Bar Chart - Negative" config={chartConfig}>
<BarChart
labels={{
offset: 5,
value: (d) => d.month,
fill: (d) => {
if (d.visitors > 0) {
return 'var(--chart-1)';
} else if (d.visitors < 0) {
return 'var(--chart-2)';
}
},
}}
data={chartData}
xScale={scaleBand().padding(0.25)}
x="month"
y="visitors"
yNice={4}
yBaseline={0}
cRange={['var(--chart-1)', 'var(--chart-2)']}
c={(d) => (d.visitors > 0 ? 'var(--chart-1)' : 'var(--chart-2)')}
axis={false}
props={{
bars: { stroke: 'none', radius: 0 },
highlight: { area: { fill: 'none' } },
xAxis: { format: (d) => d.slice(0, 3) },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel hideIndicator nameKey="visitors" />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
Showing total visitors for the last 6 months
</div>
</div>
</div>
</CardFooter>
</Card>Bar Chart - Interactive
<script lang="ts">
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { scaleUtc } from 'd3-scale';
import { BarChart, type ChartContextValue, Highlight } from 'layerchart';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ date: new Date('2024-04-01'), desktop: 222, mobile: 150 },
{ date: new Date('2024-04-02'), desktop: 97, mobile: 180 },
{ date: new Date('2024-04-03'), desktop: 167, mobile: 120 },
{ date: new Date('2024-04-04'), desktop: 242, mobile: 260 },
{ date: new Date('2024-04-05'), desktop: 373, mobile: 290 },
{ date: new Date('2024-04-06'), desktop: 301, mobile: 340 },
{ date: new Date('2024-04-07'), desktop: 245, mobile: 180 },
{ date: new Date('2024-04-08'), desktop: 409, mobile: 320 },
{ date: new Date('2024-04-09'), desktop: 59, mobile: 110 },
{ date: new Date('2024-04-10'), desktop: 261, mobile: 190 },
{ date: new Date('2024-04-11'), desktop: 327, mobile: 350 },
{ date: new Date('2024-04-12'), desktop: 292, mobile: 210 },
{ date: new Date('2024-04-13'), desktop: 342, mobile: 380 },
{ date: new Date('2024-04-14'), desktop: 137, mobile: 220 },
{ date: new Date('2024-04-15'), desktop: 120, mobile: 170 },
{ date: new Date('2024-04-16'), desktop: 138, mobile: 190 },
{ date: new Date('2024-04-17'), desktop: 446, mobile: 360 },
{ date: new Date('2024-04-18'), desktop: 364, mobile: 410 },
{ date: new Date('2024-04-19'), desktop: 243, mobile: 180 },
{ date: new Date('2024-04-20'), desktop: 89, mobile: 150 },
{ date: new Date('2024-04-21'), desktop: 137, mobile: 200 },
{ date: new Date('2024-04-22'), desktop: 224, mobile: 170 },
{ date: new Date('2024-04-23'), desktop: 138, mobile: 230 },
{ date: new Date('2024-04-24'), desktop: 387, mobile: 290 },
{ date: new Date('2024-04-25'), desktop: 215, mobile: 250 },
{ date: new Date('2024-04-26'), desktop: 75, mobile: 130 },
{ date: new Date('2024-04-27'), desktop: 383, mobile: 420 },
{ date: new Date('2024-04-28'), desktop: 122, mobile: 180 },
{ date: new Date('2024-04-29'), desktop: 315, mobile: 240 },
{ date: new Date('2024-04-30'), desktop: 454, mobile: 380 },
{ date: new Date('2024-05-01'), desktop: 165, mobile: 220 },
{ date: new Date('2024-05-02'), desktop: 293, mobile: 310 },
{ date: new Date('2024-05-03'), desktop: 247, mobile: 190 },
{ date: new Date('2024-05-04'), desktop: 385, mobile: 420 },
{ date: new Date('2024-05-05'), desktop: 481, mobile: 390 },
{ date: new Date('2024-05-06'), desktop: 498, mobile: 520 },
{ date: new Date('2024-05-07'), desktop: 388, mobile: 300 },
{ date: new Date('2024-05-08'), desktop: 149, mobile: 210 },
{ date: new Date('2024-05-09'), desktop: 227, mobile: 180 },
{ date: new Date('2024-05-10'), desktop: 293, mobile: 330 },
{ date: new Date('2024-05-11'), desktop: 335, mobile: 270 },
{ date: new Date('2024-05-12'), desktop: 197, mobile: 240 },
{ date: new Date('2024-05-13'), desktop: 197, mobile: 160 },
{ date: new Date('2024-05-14'), desktop: 448, mobile: 490 },
{ date: new Date('2024-05-15'), desktop: 473, mobile: 380 },
{ date: new Date('2024-05-16'), desktop: 338, mobile: 400 },
{ date: new Date('2024-05-17'), desktop: 499, mobile: 420 },
{ date: new Date('2024-05-18'), desktop: 315, mobile: 350 },
{ date: new Date('2024-05-19'), desktop: 235, mobile: 180 },
{ date: new Date('2024-05-20'), desktop: 177, mobile: 230 },
{ date: new Date('2024-05-21'), desktop: 82, mobile: 140 },
{ date: new Date('2024-05-22'), desktop: 81, mobile: 120 },
{ date: new Date('2024-05-23'), desktop: 252, mobile: 290 },
{ date: new Date('2024-05-24'), desktop: 294, mobile: 220 },
{ date: new Date('2024-05-25'), desktop: 201, mobile: 250 },
{ date: new Date('2024-05-26'), desktop: 213, mobile: 170 },
{ date: new Date('2024-05-27'), desktop: 420, mobile: 460 },
{ date: new Date('2024-05-28'), desktop: 233, mobile: 190 },
{ date: new Date('2024-05-29'), desktop: 78, mobile: 130 },
{ date: new Date('2024-05-30'), desktop: 340, mobile: 280 },
{ date: new Date('2024-05-31'), desktop: 178, mobile: 230 },
{ date: new Date('2024-06-01'), desktop: 178, mobile: 200 },
{ date: new Date('2024-06-02'), desktop: 470, mobile: 410 },
{ date: new Date('2024-06-03'), desktop: 103, mobile: 160 },
{ date: new Date('2024-06-04'), desktop: 439, mobile: 380 },
{ date: new Date('2024-06-05'), desktop: 88, mobile: 140 },
{ date: new Date('2024-06-06'), desktop: 294, mobile: 250 },
{ date: new Date('2024-06-07'), desktop: 323, mobile: 370 },
{ date: new Date('2024-06-08'), desktop: 385, mobile: 320 },
{ date: new Date('2024-06-09'), desktop: 438, mobile: 480 },
{ date: new Date('2024-06-10'), desktop: 155, mobile: 200 },
{ date: new Date('2024-06-11'), desktop: 92, mobile: 150 },
{ date: new Date('2024-06-12'), desktop: 492, mobile: 420 },
{ date: new Date('2024-06-13'), desktop: 81, mobile: 130 },
{ date: new Date('2024-06-14'), desktop: 426, mobile: 380 },
{ date: new Date('2024-06-15'), desktop: 307, mobile: 350 },
{ date: new Date('2024-06-16'), desktop: 371, mobile: 310 },
{ date: new Date('2024-06-17'), desktop: 475, mobile: 520 },
{ date: new Date('2024-06-18'), desktop: 107, mobile: 170 },
{ date: new Date('2024-06-19'), desktop: 341, mobile: 290 },
{ date: new Date('2024-06-20'), desktop: 408, mobile: 450 },
{ date: new Date('2024-06-21'), desktop: 169, mobile: 210 },
{ date: new Date('2024-06-22'), desktop: 317, mobile: 270 },
{ date: new Date('2024-06-23'), desktop: 480, mobile: 530 },
{ date: new Date('2024-06-24'), desktop: 132, mobile: 180 },
{ date: new Date('2024-06-25'), desktop: 141, mobile: 190 },
{ date: new Date('2024-06-26'), desktop: 434, mobile: 380 },
{ date: new Date('2024-06-27'), desktop: 448, mobile: 490 },
{ date: new Date('2024-06-28'), desktop: 149, mobile: 200 },
{ date: new Date('2024-06-29'), desktop: 103, mobile: 160 },
{ date: new Date('2024-06-30'), desktop: 446, mobile: 400 },
];
const chartConfig = {
views: { label: 'Page Views', color: '' },
desktop: { label: 'Desktop', color: 'var(--chart-2)' },
mobile: { label: 'Mobile', color: 'var(--chart-1)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
let activeChart = $state<keyof typeof chartConfig>('desktop');
const total = $derived({
desktop: chartData.reduce((acc, curr) => acc + curr.desktop, 0),
mobile: chartData.reduce((acc, curr) => acc + curr.mobile, 0),
});
const activeSeries = $derived([
{
key: activeChart,
label: chartConfig[activeChart].label,
color: `var(--color-${activeChart})`,
},
]);
</script>
<Card class="w-full max-w-3xl">
<CardHeader class="flex flex-col items-stretch space-y-0 border-b p-0 sm:flex-row">
<div class="flex flex-1 flex-col justify-center gap-1 px-6 py-5 sm:py-6">
<CardTitle>Bar Chart - Interactive</CardTitle>
<CardDescription>Showing total visitors for the last 3 months</CardDescription>
</div>
<div class="flex">
{#each ['desktop', 'mobile'] as key (key)}
{const chart = key as keyof typeof chartConfig}
<button
data-active={activeChart === chart}
class="data-[active=true]:bg-muted/50 relative z-30 flex flex-1 flex-col justify-center gap-1 border-t px-6 py-4 text-start even:border-s sm:border-s sm:border-t-0 sm:px-8 sm:py-6"
onclick={() => (activeChart = chart)}
>
<span class="text-muted-foreground text-xs">
{chartConfig[chart].label}
</span>
<span class="text-lg leading-none font-bold sm:text-3xl">
{total[key as keyof typeof total].toLocaleString()}
</span>
</button>
{/each}
</div>
</CardHeader>
<CardContent class="px-2 sm:p-6">
<ChartContainer aria-label="Bar Chart - Interactive" config={chartConfig} class="aspect-auto h-[250px] w-full">
<BarChart
bind:context
data={chartData}
x="date"
axis="x"
series={activeSeries}
props={{
bars: {
stroke: 'none',
rounded: 'none',
// use the height of the chart to animate the bars
initialY: context?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
highlight: { area: { fill: 'none' } },
xAxis: {
format: (d: Date) => {
return d.toLocaleDateString('en-US', {
month: 'short',
day: '2-digit',
});
},
ticks: (scale) => scaleUtc(scale.domain(), scale.range()).ticks(),
tickOcclusion: { padding: 32 },
},
}}
>
{#snippet belowMarks()}
<Highlight area={{ class: 'fill-muted' }} />
{/snippet}
{#snippet tooltip()}
<ChartTooltip
class="w-[150px]"
nameKey="views"
labelFormatter={(v: Date) => {
return v.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
});
}}
/>
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
</Card>Line
Line Chart
<script lang="ts">
import { LineChart } from 'layerchart';
import { scaleUtc } from 'd3-scale';
import { curveNatural } from 'd3-shape';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186 },
{ date: new Date('2024-02-01'), desktop: 305 },
{ date: new Date('2024-03-01'), desktop: 237 },
{ date: new Date('2024-04-01'), desktop: 73 },
{ date: new Date('2024-05-01'), desktop: 209 },
{ date: new Date('2024-06-01'), desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Line Chart</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Line Chart" config={chartConfig}>
<LineChart
data={chartData}
x="date"
xScale={scaleUtc()}
axis="x"
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
props={{
spline: { curve: curveNatural, motion: 'tween', strokeWidth: 2 },
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
highlight: { points: { r: 4 } },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Line Chart - Linear
<script lang="ts">
import { LineChart } from 'layerchart';
import { scaleUtc } from 'd3-scale';
import { curveLinear } from 'd3-shape';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186 },
{ date: new Date('2024-02-01'), desktop: 305 },
{ date: new Date('2024-03-01'), desktop: 237 },
{ date: new Date('2024-04-01'), desktop: 73 },
{ date: new Date('2024-05-01'), desktop: 209 },
{ date: new Date('2024-06-01'), desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Line Chart - Linear</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Line Chart - Linear" config={chartConfig}>
<LineChart
data={chartData}
x="date"
xScale={scaleUtc()}
axis="x"
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
props={{
spline: { curve: curveLinear, motion: 'tween', strokeWidth: 2 },
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
highlight: { points: { r: 4 } },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Line Chart - Step
<script lang="ts">
import { LineChart } from 'layerchart';
import { scaleUtc } from 'd3-scale';
import { curveStep } from 'd3-shape';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186 },
{ date: new Date('2024-02-01'), desktop: 305 },
{ date: new Date('2024-03-01'), desktop: 237 },
{ date: new Date('2024-04-01'), desktop: 73 },
{ date: new Date('2024-05-01'), desktop: 209 },
{ date: new Date('2024-06-01'), desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Line Chart - Step</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Line Chart - Step" config={chartConfig}>
<LineChart
data={chartData}
x="date"
xScale={scaleUtc()}
axis="x"
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
props={{
spline: { curve: curveStep, motion: 'tween', strokeWidth: 2 },
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
highlight: { points: { r: 4 } },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Line Chart - Multiple
<script lang="ts">
import { LineChart } from 'layerchart';
import { scaleUtc } from 'd3-scale';
import { curveNatural } from 'd3-shape';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186, mobile: 80 },
{ date: new Date('2024-02-01'), desktop: 305, mobile: 200 },
{ date: new Date('2024-03-01'), desktop: 237, mobile: 120 },
{ date: new Date('2024-04-01'), desktop: 73, mobile: 190 },
{ date: new Date('2024-05-01'), desktop: 209, mobile: 130 },
{ date: new Date('2024-06-01'), desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Line Chart - Multiple</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Line Chart - Multiple" config={chartConfig}>
<LineChart
data={chartData}
x="date"
xScale={scaleUtc()}
axis="x"
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
},
]}
props={{
spline: { curve: curveNatural, motion: 'tween', strokeWidth: 2 },
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
highlight: { points: { r: 4 } },
}}
>
{#snippet tooltip()}
<ChartTooltip
labelFormatter={(v: Date) => v.toLocaleDateString('en-US', { month: 'long' })}
/>
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Line Chart - Dots
<script lang="ts">
import { LineChart } from 'layerchart';
import { scaleUtc } from 'd3-scale';
import { curveNatural } from 'd3-shape';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186 },
{ date: new Date('2024-02-01'), desktop: 305 },
{ date: new Date('2024-03-01'), desktop: 237 },
{ date: new Date('2024-04-01'), desktop: 73 },
{ date: new Date('2024-05-01'), desktop: 209 },
{ date: new Date('2024-06-01'), desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Line Chart - Dots</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Line Chart - Dots" config={chartConfig}>
<LineChart
points={{ r: 4 }}
data={chartData}
x="date"
xScale={scaleUtc()}
axis="x"
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
props={{
spline: { curve: curveNatural, motion: 'tween', strokeWidth: 2 },
highlight: {
points: {
motion: 'none',
r: 6,
},
},
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Line Chart - Dots Custom
<script lang="ts">
import { LineChart, Points } from 'layerchart';
import { scaleUtc } from 'd3-scale';
import { curveNatural } from 'd3-shape';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186 },
{ date: new Date('2024-02-01'), desktop: 305 },
{ date: new Date('2024-03-01'), desktop: 237 },
{ date: new Date('2024-04-01'), desktop: 73 },
{ date: new Date('2024-05-01'), desktop: 209 },
{ date: new Date('2024-06-01'), desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Line Chart - Dots Custom</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Line Chart - Dots Custom" config={chartConfig}>
<LineChart
data={chartData}
x="date"
xScale={scaleUtc()}
axis="x"
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
props={{
spline: { curve: curveNatural, motion: 'tween', strokeWidth: 2 },
highlight: {
points: {
motion: 'none',
r: 3,
},
},
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
{#snippet points({ context })}
{#each context.series.visibleSeries as s (s.key)}
<Points seriesKey={s.key}>
{#snippet children({ points })}
{#each points as p, i (i)}
<IconPlaceholder
lucide="GitCommitVerticalIcon"
tabler="IconGitCommit"
hugeicons="GitCommitIcon"
phosphor="GitCommitIcon"
remixicon="RiGitCommitLine"
x={p.x - 12}
y={p.y - 12}
width={24}
height={24}
fill="var(--background)"
color="var(--color-desktop)"
/>
{/each}
{/snippet}
</Points>
{/each}
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Line Chart - Dots Colors
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { LineChart } from 'layerchart';
import { curveNatural } from 'd3-shape';
import { scalePoint } from 'd3-scale';
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 187, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 90, color: 'var(--color-other)' },
];
const chartConfig = {
visitors: { label: 'Visitors', color: 'var(--chart-2)' },
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;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Line Chart - Dots Colors</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Line Chart - Dots Colors" config={chartConfig}>
<LineChart
data={chartData}
x="browser"
xScale={scalePoint()}
c="color"
cRange={chartData.map((d) => d.color)}
series={[{ key: 'visitors', value: 'visitors' }]}
padding={{ left: 24, right: 24 }}
yPadding={[0, 25]}
axis={false}
points={{ r: 5, stroke: 'none' }}
props={{
spline: { curve: curveNatural, motion: 'tween', strokeWidth: 2, stroke: 'var(--color-visitors)' },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel indicator="line" nameKey="browser" />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Line Chart - Label
<script lang="ts">
import { LineChart } from 'layerchart';
import { scaleUtc } from 'd3-scale';
import { curveNatural } from 'd3-shape';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ date: new Date('2024-01-01'), desktop: 186 },
{ date: new Date('2024-02-01'), desktop: 305 },
{ date: new Date('2024-03-01'), desktop: 237 },
{ date: new Date('2024-04-01'), desktop: 73 },
{ date: new Date('2024-05-01'), desktop: 209 },
{ date: new Date('2024-06-01'), desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Line Chart - Label</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Line Chart - Label" config={chartConfig}>
<LineChart
points={{ r: 4 }}
labels={{ offset: 12 }}
data={chartData}
x="date"
axis="x"
xScale={scaleUtc()}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
props={{
spline: { curve: curveNatural, motion: 'tween', strokeWidth: 2 },
highlight: {
points: {
motion: 'none',
r: 6,
},
},
xAxis: {
format: (v: Date) => v.toLocaleDateString('en-US', { month: 'short' }),
},
}}
>
{#snippet tooltip()}
<ChartTooltip
labelFormatter={(v: Date) => {
return v.toLocaleDateString('en-US', {
month: 'long',
});
}}
indicator="line"
/>
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Line Chart - Custom Label
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { LineChart } from 'layerchart';
import { curveNatural } from 'd3-shape';
import { scalePoint } from 'd3-scale';
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 187, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 90, color: 'var(--color-other)' },
];
const chartConfig = {
visitors: { label: 'Visitors', color: 'var(--chart-2)' },
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;
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Line Chart - Custom Label</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Line Chart - Custom Label" config={chartConfig}>
<LineChart
data={chartData}
x="browser"
xScale={scalePoint()}
c="color"
cRange={chartData.map((d) => d.color)}
series={[{ key: 'visitors', value: 'visitors' }]}
padding={{ left: 24, right: 24 }}
yPadding={[0, 25]}
axis={false}
points={{ r: 5, stroke: 'none' }}
labels={{ offset: 12, value: (d) => chartConfig[d.browser as keyof typeof chartConfig].label }}
props={{
spline: { curve: curveNatural, motion: 'tween', strokeWidth: 2, stroke: 'var(--color-visitors)' },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel indicator="line" nameKey="browser" />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div class="flex w-full items-start gap-2 text-sm">
<div class="grid gap-2">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>Line Chart - Interactive
<script lang="ts">
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { scaleUtc } from 'd3-scale';
import { LineChart } from 'layerchart';
import { curveMonotoneX } from 'd3-shape';
const chartData = [
{ date: new Date('2024-04-01'), desktop: 222, mobile: 150 },
{ date: new Date('2024-04-02'), desktop: 97, mobile: 180 },
{ date: new Date('2024-04-03'), desktop: 167, mobile: 120 },
{ date: new Date('2024-04-04'), desktop: 242, mobile: 260 },
{ date: new Date('2024-04-05'), desktop: 373, mobile: 290 },
{ date: new Date('2024-04-06'), desktop: 301, mobile: 340 },
{ date: new Date('2024-04-07'), desktop: 245, mobile: 180 },
{ date: new Date('2024-04-08'), desktop: 409, mobile: 320 },
{ date: new Date('2024-04-09'), desktop: 59, mobile: 110 },
{ date: new Date('2024-04-10'), desktop: 261, mobile: 190 },
{ date: new Date('2024-04-11'), desktop: 327, mobile: 350 },
{ date: new Date('2024-04-12'), desktop: 292, mobile: 210 },
{ date: new Date('2024-04-13'), desktop: 342, mobile: 380 },
{ date: new Date('2024-04-14'), desktop: 137, mobile: 220 },
{ date: new Date('2024-04-15'), desktop: 120, mobile: 170 },
{ date: new Date('2024-04-16'), desktop: 138, mobile: 190 },
{ date: new Date('2024-04-17'), desktop: 446, mobile: 360 },
{ date: new Date('2024-04-18'), desktop: 364, mobile: 410 },
{ date: new Date('2024-04-19'), desktop: 243, mobile: 180 },
{ date: new Date('2024-04-20'), desktop: 89, mobile: 150 },
{ date: new Date('2024-04-21'), desktop: 137, mobile: 200 },
{ date: new Date('2024-04-22'), desktop: 224, mobile: 170 },
{ date: new Date('2024-04-23'), desktop: 138, mobile: 230 },
{ date: new Date('2024-04-24'), desktop: 387, mobile: 290 },
{ date: new Date('2024-04-25'), desktop: 215, mobile: 250 },
{ date: new Date('2024-04-26'), desktop: 75, mobile: 130 },
{ date: new Date('2024-04-27'), desktop: 383, mobile: 420 },
{ date: new Date('2024-04-28'), desktop: 122, mobile: 180 },
{ date: new Date('2024-04-29'), desktop: 315, mobile: 240 },
{ date: new Date('2024-04-30'), desktop: 454, mobile: 380 },
{ date: new Date('2024-05-01'), desktop: 165, mobile: 220 },
{ date: new Date('2024-05-02'), desktop: 293, mobile: 310 },
{ date: new Date('2024-05-03'), desktop: 247, mobile: 190 },
{ date: new Date('2024-05-04'), desktop: 385, mobile: 420 },
{ date: new Date('2024-05-05'), desktop: 481, mobile: 390 },
{ date: new Date('2024-05-06'), desktop: 498, mobile: 520 },
{ date: new Date('2024-05-07'), desktop: 388, mobile: 300 },
{ date: new Date('2024-05-08'), desktop: 149, mobile: 210 },
{ date: new Date('2024-05-09'), desktop: 227, mobile: 180 },
{ date: new Date('2024-05-10'), desktop: 293, mobile: 330 },
{ date: new Date('2024-05-11'), desktop: 335, mobile: 270 },
{ date: new Date('2024-05-12'), desktop: 197, mobile: 240 },
{ date: new Date('2024-05-13'), desktop: 197, mobile: 160 },
{ date: new Date('2024-05-14'), desktop: 448, mobile: 490 },
{ date: new Date('2024-05-15'), desktop: 473, mobile: 380 },
{ date: new Date('2024-05-16'), desktop: 338, mobile: 400 },
{ date: new Date('2024-05-17'), desktop: 499, mobile: 420 },
{ date: new Date('2024-05-18'), desktop: 315, mobile: 350 },
{ date: new Date('2024-05-19'), desktop: 235, mobile: 180 },
{ date: new Date('2024-05-20'), desktop: 177, mobile: 230 },
{ date: new Date('2024-05-21'), desktop: 82, mobile: 140 },
{ date: new Date('2024-05-22'), desktop: 81, mobile: 120 },
{ date: new Date('2024-05-23'), desktop: 252, mobile: 290 },
{ date: new Date('2024-05-24'), desktop: 294, mobile: 220 },
{ date: new Date('2024-05-25'), desktop: 201, mobile: 250 },
{ date: new Date('2024-05-26'), desktop: 213, mobile: 170 },
{ date: new Date('2024-05-27'), desktop: 420, mobile: 460 },
{ date: new Date('2024-05-28'), desktop: 233, mobile: 190 },
{ date: new Date('2024-05-29'), desktop: 78, mobile: 130 },
{ date: new Date('2024-05-30'), desktop: 340, mobile: 280 },
{ date: new Date('2024-05-31'), desktop: 178, mobile: 230 },
{ date: new Date('2024-06-01'), desktop: 178, mobile: 200 },
{ date: new Date('2024-06-02'), desktop: 470, mobile: 410 },
{ date: new Date('2024-06-03'), desktop: 103, mobile: 160 },
{ date: new Date('2024-06-04'), desktop: 439, mobile: 380 },
{ date: new Date('2024-06-05'), desktop: 88, mobile: 140 },
{ date: new Date('2024-06-06'), desktop: 294, mobile: 250 },
{ date: new Date('2024-06-07'), desktop: 323, mobile: 370 },
{ date: new Date('2024-06-08'), desktop: 385, mobile: 320 },
{ date: new Date('2024-06-09'), desktop: 438, mobile: 480 },
{ date: new Date('2024-06-10'), desktop: 155, mobile: 200 },
{ date: new Date('2024-06-11'), desktop: 92, mobile: 150 },
{ date: new Date('2024-06-12'), desktop: 492, mobile: 420 },
{ date: new Date('2024-06-13'), desktop: 81, mobile: 130 },
{ date: new Date('2024-06-14'), desktop: 426, mobile: 380 },
{ date: new Date('2024-06-15'), desktop: 307, mobile: 350 },
{ date: new Date('2024-06-16'), desktop: 371, mobile: 310 },
{ date: new Date('2024-06-17'), desktop: 475, mobile: 520 },
{ date: new Date('2024-06-18'), desktop: 107, mobile: 170 },
{ date: new Date('2024-06-19'), desktop: 341, mobile: 290 },
{ date: new Date('2024-06-20'), desktop: 408, mobile: 450 },
{ date: new Date('2024-06-21'), desktop: 169, mobile: 210 },
{ date: new Date('2024-06-22'), desktop: 317, mobile: 270 },
{ date: new Date('2024-06-23'), desktop: 480, mobile: 530 },
{ date: new Date('2024-06-24'), desktop: 132, mobile: 180 },
{ date: new Date('2024-06-25'), desktop: 141, mobile: 190 },
{ date: new Date('2024-06-26'), desktop: 434, mobile: 380 },
{ date: new Date('2024-06-27'), desktop: 448, mobile: 490 },
{ date: new Date('2024-06-28'), desktop: 149, mobile: 200 },
{ date: new Date('2024-06-29'), desktop: 103, mobile: 160 },
{ date: new Date('2024-06-30'), desktop: 446, mobile: 400 },
];
const chartConfig = {
views: { label: 'Page Views', color: '' },
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
let activeChart = $state<keyof typeof chartConfig>('desktop');
const total = $derived({
desktop: chartData.reduce((acc, curr) => acc + curr.desktop, 0),
mobile: chartData.reduce((acc, curr) => acc + curr.mobile, 0),
});
const activeSeries = $derived([
{
key: activeChart,
label: chartConfig[activeChart].label,
color: `var(--color-${activeChart})`,
},
]);
</script>
<Card class="w-full max-w-3xl">
<CardHeader class="flex flex-col items-stretch space-y-0 border-b p-0 sm:flex-row">
<div class="flex flex-1 flex-col justify-center gap-1 px-6 py-5 sm:py-6">
<CardTitle>Line Chart - Interactive</CardTitle>
<CardDescription>Showing total visitors for the last 3 months</CardDescription>
</div>
<div class="flex">
{#each ['desktop', 'mobile'] as key (key)}
{const chart = key as keyof typeof chartConfig}
<button
data-active={activeChart === chart}
class="data-[active=true]:bg-muted/50 relative z-30 flex flex-1 flex-col justify-center gap-1 border-t px-6 py-4 text-start even:border-s sm:border-s sm:border-t-0 sm:px-8 sm:py-6"
onclick={() => (activeChart = chart)}
>
<span class="text-muted-foreground text-xs">
{chartConfig[chart].label}
</span>
<span class="text-lg leading-none font-bold sm:text-3xl">
{total[key as keyof typeof total].toLocaleString()}
</span>
</button>
{/each}
</div>
</CardHeader>
<CardContent class="px-2 sm:p-6">
<ChartContainer aria-label="Line Chart - Interactive" config={chartConfig} class="aspect-auto h-[250px] w-full">
<LineChart
data={chartData}
x="date"
xScale={scaleUtc()}
axis="x"
series={activeSeries}
props={{
spline: { curve: curveMonotoneX, motion: 'tween', strokeWidth: 2 },
xAxis: {
format: (v: Date) => {
return v.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
});
},
},
highlight: { points: { r: 4 } },
}}
>
{#snippet tooltip()}
<ChartTooltip
class="w-[150px]"
nameKey="views"
labelFormatter={(v: Date) => {
return v.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
});
}}
/>
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
</Card>Pie
Pie Chart
<script lang="ts">
import { PieChart } from 'layerchart';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 187, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 90, color: '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;
</script>
<Card class="flex flex-col w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Pie Chart</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Pie Chart" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
data={chartData}
key="browser"
value="visitors"
cRange={chartData.map((d) => d.color)}
c="color"
props={{
pie: {
motion: 'tween',
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>Pie Chart - Separator None
<script lang="ts">
import { PieChart } from 'layerchart';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 187, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 90, color: '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;
</script>
<Card class="flex flex-col w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Pie Chart - Separator None</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Pie Chart - Separator None" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
data={chartData}
key="browser"
value="visitors"
cRange={chartData.map((d) => d.color)}
c="color"
props={{
pie: { motion: 'tween' },
arc: { strokeWidth: 0 },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>Pie Chart - Label
<script lang="ts">
import { Arc, PieChart, Text } from 'layerchart';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 187, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 90, color: '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;
</script>
<Card class="flex flex-col w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Pie Chart - Label</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Pie Chart - Label" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
data={chartData}
key="browser"
value="visitors"
cRange={chartData.map((d) => d.color)}
c="color"
props={{
pie: {
motion: 'tween',
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
{#snippet arc({ props, visibleData, index })}
{const browser = visibleData[index].browser}
<Arc {...props}>
{#snippet children({ getArcTextProps })}
<Text
value={browser}
{...getArcTextProps('centroid')}
font-size="12"
class="fill-background capitalize"
/>
{/snippet}
</Arc>
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>Pie Chart - Custom Label
<script lang="ts">
import { Arc, PieChart, Text } from 'layerchart';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 187, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 90, color: '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;
</script>
<Card class="flex flex-col w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Pie Chart - Custom Label</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Pie Chart - Custom Label" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
data={chartData}
key="browser"
value="visitors"
cRange={chartData.map((d) => d.color)}
c="color"
props={{
pie: {
motion: 'tween',
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
{#snippet arc({ props, visibleData, index })}
<Arc {...props}>
{#snippet children({ getArcTextProps })}
<Text
value={visibleData[index].visitors}
{...getArcTextProps('outer', {
startOffset: '50%',
outerPadding: 10,
})}
class="fill-foreground"
/>
{/snippet}
</Arc>
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>Pie Chart - Label List
<script lang="ts">
import { Arc, PieChart, Text } from 'layerchart';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 187, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 90, color: '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;
</script>
<Card class="flex flex-col w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Pie Chart - Label List</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Pie Chart - Label List" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
data={chartData}
key="browser"
value="visitors"
cRange={chartData.map((d) => d.color)}
c="color"
props={{
pie: {
motion: 'tween',
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
{#snippet arc({ props, visibleData, index })}
{const browser = visibleData[index].browser}
<Arc {...props}>
{#snippet children({ centroid })}
<Text
value={browser}
x={centroid[0]}
y={centroid[1]}
textAnchor="middle"
verticalAnchor="middle"
font-size="12"
class="fill-background capitalize"
/>
{/snippet}
</Arc>
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>Pie Chart - Legend
<script lang="ts">
import { PieChart } from 'layerchart';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartLegend, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 187, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 90, color: '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;
</script>
<Card class="flex flex-col w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Pie Chart - Legend</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Pie Chart - Legend" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
data={chartData}
key="browser"
value="visitors"
cRange={chartData.map((d) => d.color)}
padding={{ bottom: 32 }}
props={{
pie: {
motion: 'tween',
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
{#snippet legend()}
<ChartLegend nameKey="browser" />
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>Pie Chart - Donut
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { PieChart } from 'layerchart';
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 287, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 190, color: '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;
</script>
<Card class="flex flex-col w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Pie Chart - Donut</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Pie Chart - Donut" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
data={chartData}
key="browser"
value="visitors"
c="color"
innerRadius={60}
padding={29}
props={{ pie: { motion: 'tween' } }}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>Pie Chart - Donut Active
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { Arc, PieChart } from 'layerchart';
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 287, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 190, color: '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;
</script>
<Card class="flex w-full max-w-md flex-col">
<CardHeader class="items-center">
<CardTitle>Pie Chart - Donut Active</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Pie Chart - Donut Active" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
data={chartData}
key="browser"
value="visitors"
c="color"
innerRadius={60}
outerRadius={-10}
props={{
pie: { motion: 'tween' },
arc: {
strokeWidth: 5,
},
}}
padding={29}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
{#snippet arc({ props, index })}
<Arc {...props} outerRadius={index === 0 ? 0 : props.outerRadius} />
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>Pie Chart - Donut with Text
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { PieChart, Text } from 'layerchart';
const chartData = [
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'firefox', visitors: 287, color: 'var(--color-firefox)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'other', visitors: 190, color: '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;
const totalVisitors = chartData.reduce((acc, curr) => acc + curr.visitors, 0);
</script>
<Card class="flex flex-col w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Pie Chart - Donut with Text</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Pie Chart - Donut with Text" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
data={chartData}
key="browser"
value="visitors"
c="color"
innerRadius={60}
padding={28}
props={{ pie: { motion: 'tween' } }}
>
{#snippet aboveMarks()}
<Text
value={String(totalVisitors)}
textAnchor="middle"
verticalAnchor="middle"
class="fill-foreground text-3xl! font-bold"
dy={3}
/>
<Text
value="Visitors"
textAnchor="middle"
verticalAnchor="middle"
class="fill-muted-foreground! text-muted-foreground"
dy={22}
/>
{/snippet}
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>Pie Chart - Stacked
<script lang="ts">
import { PieChart } from 'layerchart';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const desktopData = [
{ month: 'january', desktop: 186, color: 'var(--color-january)' },
{ month: 'february', desktop: 305, color: 'var(--color-february)' },
{ month: 'march', desktop: 237, color: 'var(--color-march)' },
{ month: 'april', desktop: 173, color: 'var(--color-april)' },
{ month: 'may', desktop: 209, color: 'var(--color-may)' },
];
const mobileData = [
{ month: 'january', mobile: 80, color: 'var(--color-january)' },
{ month: 'february', mobile: 200, color: 'var(--color-february)' },
{ month: 'march', mobile: 120, color: 'var(--color-march)' },
{ month: 'april', mobile: 190, color: 'var(--color-april)' },
{ month: 'may', mobile: 130, color: 'var(--color-may)' },
];
const chartConfig = {
desktop: { label: 'Desktop' },
mobile: { label: 'Mobile' },
january: { label: 'January', color: 'var(--chart-1)' },
february: { label: 'February', color: 'var(--chart-2)' },
march: { label: 'March', color: 'var(--chart-3)' },
april: { label: 'April', color: 'var(--chart-4)' },
may: { label: 'May', color: 'var(--chart-5)' },
} satisfies ChartConfig;
</script>
<Card class="flex flex-col w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Pie Chart - Stacked</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Pie Chart - Stacked" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
key="month"
label="month"
c="color"
props={{
pie: {
sort: (a, b) => {
const monthOrder = ['january', 'february', 'march', 'april', 'may'];
return monthOrder.indexOf(a.month) - monthOrder.indexOf(b.month);
},
motion: 'tween',
},
}}
series={[
{
key: 'desktop',
data: desktopData.map((d) => ({ month: d.month, value: d.desktop, color: d.color, series: 'desktop' })),
props: { innerRadius: -20 },
},
{
key: 'mobile',
data: mobileData.map((d) => ({ month: d.month, value: d.mobile, color: d.color, series: 'mobile' })),
props: { outerRadius: -30 },
},
]}
padding={29}
>
{#snippet tooltip()}
<ChartTooltip>
{#snippet children({ data })}
<div class="border-border/50 bg-background grid min-w-[8rem] gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl">
<div class="font-medium">{chartConfig[data.series as keyof typeof chartConfig].label}</div>
<div class="flex items-center gap-2">
<div class="h-2.5 w-1 shrink-0 rounded-[2px]" style:background={data.color as string}></div>
<span class="text-muted-foreground">{chartConfig[data.month as keyof typeof chartConfig].label}</span>
<span class="text-foreground ms-auto font-mono font-medium tabular-nums">{(data.value as number).toLocaleString()}</span>
</div>
</div>
{/snippet}
</ChartTooltip>
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>Pie Chart - Interactive
<script lang="ts">
import { Arc, PieChart, Text } from 'layerchart';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { NativeSelect, NativeSelectOption } from '@sveltery/components/native-select';
const desktopData = [
{ month: 'january', desktop: 186, color: 'var(--color-january)' },
{ month: 'february', desktop: 305, color: 'var(--color-february)' },
{ month: 'march', desktop: 237, color: 'var(--color-march)' },
{ month: 'april', desktop: 173, color: 'var(--color-april)' },
{ month: 'may', desktop: 209, color: 'var(--color-may)' },
];
const chartConfig = {
desktop: { label: 'Desktop' },
january: { label: 'January', color: 'var(--chart-1)' },
february: { label: 'February', color: 'var(--chart-2)' },
march: { label: 'March', color: 'var(--chart-3)' },
april: { label: 'April', color: 'var(--chart-4)' },
may: { label: 'May', color: 'var(--chart-5)' },
} satisfies ChartConfig;
let activeMonth = $state(desktopData[0].month);
const activeIndex = $derived(desktopData.findIndex((item) => item.month === activeMonth));
const months = $derived(desktopData.map((item) => item.month));
</script>
<Card class="flex w-full max-w-md flex-col">
<CardHeader class="flex flex-row items-start space-y-0 pb-0">
<div class="grid gap-1">
<CardTitle>Pie Chart - Interactive</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</div>
<NativeSelect bind:value={activeMonth} size="sm" class="ms-auto" aria-label="Select a month">
{#each months as month (month)}
<NativeSelectOption value={month}>{chartConfig[month as keyof typeof chartConfig].label}</NativeSelectOption>
{/each}
</NativeSelect>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Pie Chart - Interactive" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
data={desktopData}
label="month"
key="month"
value="desktop"
c="color"
props={{
pie: {
sort: (a, b) => {
const monthOrder = ['january', 'february', 'march', 'april', 'may'];
return monthOrder.indexOf(a.month) - monthOrder.indexOf(b.month);
},
motion: 'tween',
},
}}
innerRadius={60}
outerRadius={-35}
padding={4}
>
{#snippet aboveMarks()}
<Text
value={desktopData[activeIndex].desktop.toLocaleString()}
textAnchor="middle"
verticalAnchor="middle"
class="fill-foreground !text-3xl font-bold"
dy={3}
/>
<Text
value="Visitors"
textAnchor="middle"
verticalAnchor="middle"
class="!fill-muted-foreground text-muted-foreground"
dy={22}
/>
{/snippet}
{#snippet arc({ props, index })}
{#if index === activeIndex}
<Arc {...props} outerRadius={-25} />
<Arc {...props} outerRadius={-10} innerRadius={-13} />
{:else}
<Arc {...props} />
{/if}
{/snippet}
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="month" />
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>Radar
Radar Chart
<script lang="ts">
import { LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186 },
{ month: 'February', desktop: 305 },
{ month: 'March', desktop: 237 },
{ month: 'April', desktop: 273 },
{ month: 'May', desktop: 209 },
{ month: 'June', desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
radial
x="month"
xScale={scaleBand()}
padding={12}
props={{
spline: {
curve: curveLinearClosed,
fill: 'var(--color-desktop)',
fillOpacity: 0.6,
stroke: '0',
motion: 'tween',
},
xAxis: {
tickLength: 0,
},
yAxis: {
format: () => '',
},
grid: {
radialY: 'linear',
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
},
}}
>
{#snippet tooltip()}
<ChartTooltip />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Dots
<script lang="ts">
import { LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186 },
{ month: 'February', desktop: 305 },
{ month: 'March', desktop: 237 },
{ month: 'April', desktop: 273 },
{ month: 'May', desktop: 209 },
{ month: 'June', desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Dots</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Dots" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
radial
x="month"
xScale={scaleBand()}
points={{ r: 4 }}
padding={12}
props={{
spline: {
curve: curveLinearClosed,
fill: 'var(--color-desktop)',
fillOpacity: 0.6,
stroke: '0',
motion: 'tween',
},
xAxis: {
tickLength: 0,
},
yAxis: {
format: () => '',
},
grid: {
radialY: 'linear',
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
points: false,
},
}}
>
{#snippet tooltip()}
<ChartTooltip />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Lines Only
<script lang="ts">
import { LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186, mobile: 160 },
{ month: 'February', desktop: 185, mobile: 170 },
{ month: 'March', desktop: 207, mobile: 180 },
{ month: 'April', desktop: 173, mobile: 160 },
{ month: 'May', desktop: 160, mobile: 190 },
{ month: 'June', desktop: 174, mobile: 204 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Lines Only</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Lines Only" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
radial
data={chartData}
x="month"
xScale={scaleBand()}
padding={12}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
props: { class: 'fill-none stroke-[2]' },
},
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
props: { class: 'fill-none stroke-[2]' },
},
]}
props={{
spline: { curve: curveLinearClosed, motion: 'tween' },
grid: { radialY: 'linear', x: false },
yAxis: { format: () => '' },
tooltip: { context: { mode: 'band' } },
}}
>
{#snippet tooltip()}
<ChartTooltip indicator="line" />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Custom Label
<script lang="ts">
import { Axis, LineChart, Text } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186, mobile: 80 },
{ month: 'February', desktop: 305, mobile: 200 },
{ month: 'March', desktop: 237, mobile: 120 },
{ month: 'April', desktop: 73, mobile: 190 },
{ month: 'May', desktop: 209, mobile: 130 },
{ month: 'June', desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Custom Label</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Custom Label" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
props: {
fill: 'var(--color-desktop)',
fillOpacity: 0.6,
},
},
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
props: {
fill: 'var(--color-mobile)',
},
},
]}
radial
x="month"
xScale={scaleBand()}
padding={12}
props={{
spline: {
curve: curveLinearClosed,
stroke: '0',
motion: 'tween',
},
grid: {
radialY: 'linear',
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
points: { r: 4 },
},
}}
>
{#snippet axis()}
<Axis placement="angle" tickLength={0}>
{#snippet tickLabel({ props, index })}
{const y = Number(props.y ?? 0)}
{const data = chartData[index]}
<Text {...props} {y} value="{data.desktop} / {data.mobile}" class="fill-foreground" />
<Text {...props} y={y + 14} />
{/snippet}
</Axis>
<Axis placement="radius" format={() => ''} />
{/snippet}
{#snippet tooltip()}
<ChartTooltip indicator="line" />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Radius Axis
<script lang="ts">
import { LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186, mobile: 80 },
{ month: 'February', desktop: 305, mobile: 200 },
{ month: 'March', desktop: 237, mobile: 120 },
{ month: 'April', desktop: 73, mobile: 190 },
{ month: 'May', desktop: 209, mobile: 130 },
{ month: 'June', desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Radius Axis</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Radius Axis" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
props: {
fill: 'var(--color-desktop)',
fillOpacity: 0.6,
},
},
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
props: {
fill: 'var(--color-mobile)',
},
},
]}
radial
x="month"
y="desktop"
xScale={scaleBand()}
padding={12}
props={{
spline: {
curve: curveLinearClosed,
stroke: '0',
motion: 'tween',
},
yAxis: {
format: 'metric',
},
grid: {
yTicks: 6,
radialY: 'linear',
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
points: { r: 4 },
},
}}
>
{#snippet tooltip()}
<ChartTooltip indicator="line" />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Grid Custom
<script lang="ts">
import { Grid, LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186 },
{ month: 'February', desktop: 305 },
{ month: 'March', desktop: 237 },
{ month: 'April', desktop: 273 },
{ month: 'May', desktop: 209 },
{ month: 'June', desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Grid Custom</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Grid Custom" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
radial
x="month"
xScale={scaleBand()}
padding={12}
props={{
spline: {
curve: curveLinearClosed,
fill: 'var(--color-desktop)',
fillOpacity: 0.6,
stroke: '0',
motion: 'tween',
},
xAxis: {
tickLength: 0,
},
yAxis: {
format: () => '',
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
},
}}
>
{#snippet grid()}
<Grid
y
radialY="linear"
yTicks={[Math.max(...chartData.map((m) => m.desktop))]}
/>
{/snippet}
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Grid Circle
<script lang="ts">
import { LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186 },
{ month: 'February', desktop: 305 },
{ month: 'March', desktop: 237 },
{ month: 'April', desktop: 273 },
{ month: 'May', desktop: 209 },
{ month: 'June', desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Grid Circle</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Grid Circle" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
radial
x="month"
y="desktop"
xScale={scaleBand()}
points={{ r: 4 }}
padding={12}
props={{
spline: {
curve: curveLinearClosed,
fill: 'var(--color-desktop)',
fillOpacity: 0.6,
stroke: '0',
motion: 'tween',
},
xAxis: {
tickLength: 0,
},
yAxis: {
format: () => '',
},
grid: {
radialY: 'circle',
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
points: false,
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Grid Circle - No Lines
<script lang="ts">
import { LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186 },
{ month: 'February', desktop: 305 },
{ month: 'March', desktop: 237 },
{ month: 'April', desktop: 203 },
{ month: 'May', desktop: 209 },
{ month: 'June', desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Grid Circle - No Lines</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Grid Circle - No Lines" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
radial
x="month"
xScale={scaleBand()}
points={{ r: 4 }}
padding={12}
props={{
spline: {
curve: curveLinearClosed,
fill: 'var(--color-desktop)',
fillOpacity: 0.6,
stroke: '0',
motion: 'tween',
},
xAxis: {
tickLength: 0,
},
yAxis: {
format: () => '',
},
grid: {
radialY: 'circle',
x: false,
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
points: false,
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Grid Circle Filled
<script lang="ts">
import { LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186 },
{ month: 'February', desktop: 285 },
{ month: 'March', desktop: 237 },
{ month: 'April', desktop: 203 },
{ month: 'May', desktop: 209 },
{ month: 'June', desktop: 264 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Grid Circle Filled</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Grid Circle Filled" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
radial
x="month"
xScale={scaleBand()}
padding={12}
yPadding={[0, 8]}
props={{
spline: {
curve: curveLinearClosed,
fill: 'var(--color-desktop)',
fillOpacity: 0.5,
stroke: '0',
motion: 'tween',
},
xAxis: {
tickLength: 0,
},
yAxis: {
format: () => '',
},
grid: {
radialY: 'circle',
class: 'fill-(--color-desktop)',
classes: {
line: 'fill-(--color-desktop) opacity-20!',
},
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
},
}}
>
{#snippet tooltip()}
<ChartTooltip />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Grid Filled
<script lang="ts">
import { LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186 },
{ month: 'February', desktop: 285 },
{ month: 'March', desktop: 237 },
{ month: 'April', desktop: 203 },
{ month: 'May', desktop: 209 },
{ month: 'June', desktop: 264 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Grid Filled</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Grid Filled" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
radial
x="month"
xScale={scaleBand()}
padding={12}
yPadding={[0, 8]}
props={{
spline: {
curve: curveLinearClosed,
fill: 'var(--color-desktop)',
fillOpacity: 0.5,
stroke: '0',
motion: 'tween',
},
xAxis: {
tickLength: 0,
},
yAxis: {
format: () => '',
},
grid: {
radialY: 'linear',
class: 'fill-(--color-desktop)',
classes: {
line: 'fill-(--color-desktop) opacity-20!',
},
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Grid None
<script lang="ts">
import { LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186 },
{ month: 'February', desktop: 305 },
{ month: 'March', desktop: 237 },
{ month: 'April', desktop: 273 },
{ month: 'May', desktop: 209 },
{ month: 'June', desktop: 214 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Grid None</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Grid None" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
},
]}
radial
x="month"
xScale={scaleBand()}
points={{ r: 4 }}
padding={12}
grid={false}
props={{
spline: {
curve: curveLinearClosed,
fill: 'var(--color-desktop)',
fillOpacity: 0.6,
stroke: '0',
motion: 'tween',
},
xAxis: {
tickLength: 0,
},
yAxis: {
format: () => '',
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
points: false,
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Icons
<script lang="ts">
import { LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartLegend, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import ArrowDownFromLineIcon from './icons/ArrowDownFromLineIcon.svelte';
import ArrowUpFromLineIcon from './icons/ArrowUpFromLineIcon.svelte';
const chartData = [
{ month: 'January', desktop: 186, mobile: 80 },
{ month: 'February', desktop: 305, mobile: 200 },
{ month: 'March', desktop: 237, mobile: 120 },
{ month: 'April', desktop: 73, mobile: 190 },
{ month: 'May', desktop: 209, mobile: 130 },
{ month: 'June', desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)', icon: ArrowDownFromLineIcon },
mobile: { label: 'Mobile', color: 'var(--chart-2)', icon: ArrowUpFromLineIcon },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Icons</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Icons" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
props: {
fill: 'var(--color-desktop)',
fillOpacity: 0.6,
},
},
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
props: {
fill: 'var(--color-mobile)',
},
},
]}
radial
x="month"
xScale={scaleBand()}
padding={{ top: 8, right: 8, bottom: 32, left: 8 }}
props={{
spline: {
curve: curveLinearClosed,
stroke: '0',
motion: 'tween',
},
xAxis: {
tickLength: -8,
},
yAxis: {
format: () => '',
},
grid: {
radialY: 'linear',
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
points: { r: 4 },
},
}}
>
{#snippet tooltip()}
<ChartTooltip indicator="line" />
{/snippet}
{#snippet legend()}
<ChartLegend />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 pt-4 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Legend
<script lang="ts">
import { LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartLegend, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186, mobile: 80 },
{ month: 'February', desktop: 305, mobile: 200 },
{ month: 'March', desktop: 237, mobile: 120 },
{ month: 'April', desktop: 73, mobile: 190 },
{ month: 'May', desktop: 209, mobile: 130 },
{ month: 'June', desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Legend</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Legend" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
props: {
fill: 'var(--color-desktop)',
fillOpacity: 0.6,
},
},
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
props: {
fill: 'var(--color-mobile)',
},
},
]}
radial
x="month"
xScale={scaleBand()}
padding={{ top: 8, right: 8, bottom: 32, left: 8 }}
props={{
spline: {
curve: curveLinearClosed,
stroke: '0',
motion: 'tween',
},
xAxis: {
tickLength: -8,
},
yAxis: {
format: () => '',
},
grid: {
radialY: 'linear',
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
points: { r: 4 },
},
}}
>
{#snippet tooltip()}
<ChartTooltip indicator="line" />
{/snippet}
{#snippet legend()}
<ChartLegend />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 pt-4 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radar Chart - Multiple
<script lang="ts">
import { LineChart } from 'layerchart';
import { curveLinearClosed } from 'd3-shape';
import { scaleBand } from 'd3-scale';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
const chartData = [
{ month: 'January', desktop: 186, mobile: 80 },
{ month: 'February', desktop: 305, mobile: 200 },
{ month: 'March', desktop: 237, mobile: 120 },
{ month: 'April', desktop: 73, mobile: 190 },
{ month: 'May', desktop: 209, mobile: 130 },
{ month: 'June', desktop: 214, mobile: 140 },
];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radar Chart - Multiple</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radar Chart - Multiple" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<LineChart
data={chartData}
series={[
{
key: 'desktop',
label: 'Desktop',
color: 'var(--color-desktop)',
props: {
fill: 'var(--color-desktop)',
fillOpacity: 0.6,
},
},
{
key: 'mobile',
label: 'Mobile',
color: 'var(--color-mobile)',
props: {
fill: 'var(--color-mobile)',
},
},
]}
radial
x="month"
xScale={scaleBand()}
padding={12}
props={{
spline: {
curve: curveLinearClosed,
stroke: '0',
motion: 'tween',
},
xAxis: {
tickLength: 0,
},
yAxis: {
format: () => '',
},
grid: {
radialY: 'linear',
},
tooltip: {
context: {
mode: 'band',
},
},
highlight: {
lines: false,
points: { r: 4 },
},
}}
>
{#snippet tooltip()}
<ChartTooltip indicator="line" />
{/snippet}
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radial
Radial Chart
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { ArcChart } from 'layerchart';
const chartData = [
{ browser: 'other', visitors: 90, color: 'var(--color-other)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'firefox', visitors: 187, color: 'var(--color-firefox)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
];
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;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radial Chart</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radial Chart" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<ArcChart
label="browser"
value="visitors"
outerRadius={-17}
innerRadius={-12.5}
padding={20}
range={[90, -270]}
maxValue={Math.max(...chartData.map((d) => d.visitors))}
series={chartData.map((d) => ({
key: d.browser,
color: d.color,
data: [d],
}))}
props={{
arc: { track: { fill: 'var(--muted)' }, motion: 'tween' },
tooltip: { context: { hideDelay: 350 } },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
</ArcChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radial Chart - Label
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { Arc, ArcChart, Text } from 'layerchart';
const chartData = [
{ browser: 'other', visitors: 90, color: 'var(--color-other)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'firefox', visitors: 187, color: 'var(--color-firefox)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
];
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;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radial Chart - Label</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radial Chart - Label" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<ArcChart
label="browser"
value="visitors"
outerRadius={-17}
innerRadius={-12.5}
padding={20}
range={[180, -180]}
maxValue={Math.max(...chartData.map((d) => d.visitors)) + 0}
series={chartData.map((d) => ({
key: d.browser,
color: d.color,
data: [d],
label: d.browser,
}))}
props={{
arc: { track: { fill: 'var(--muted)' }, motion: 'tween' },
tooltip: { context: { hideDelay: 350 } },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
{#snippet arc({ context, props, seriesIndex })}
<Arc {...props}>
{#snippet children({ getTrackTextProps })}
<Text
{...getTrackTextProps('middle', { startOffset: '1%' })}
class="pointer-events-none capitalize select-none"
value={context.series.visibleSeries[seriesIndex].label}
fill="white"
/>
{/snippet}
</Arc>
{/snippet}
</ArcChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radial Chart - Grid
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { ArcChart } from 'layerchart';
const chartData = [
{ browser: 'other', visitors: 90, color: 'var(--color-other)' },
{ browser: 'edge', visitors: 173, color: 'var(--color-edge)' },
{ browser: 'firefox', visitors: 187, color: 'var(--color-firefox)' },
{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' },
{ browser: 'chrome', visitors: 275, color: 'var(--color-chrome)' },
];
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;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radial Chart - Grid</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radial Chart - Grid" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<ArcChart
label="browser"
value="visitors"
outerRadius={-17}
innerRadius={-12.5}
padding={20}
range={[90, -270]}
maxValue={Math.max(...chartData.map((d) => d.visitors))}
series={chartData.map((d) => ({
key: d.browser,
color: d.color,
data: [d],
}))}
props={{
arc: { track: { fill: 'var(--muted)' }, motion: 'tween' },
tooltip: { context: { hideDelay: 350 } },
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="browser" />
{/snippet}
</ArcChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radial Chart - Text
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { ArcChart, Text } from 'layerchart';
const chartData = [{ browser: 'safari', visitors: 200, color: 'var(--color-safari)' }];
const chartConfig = {
visitors: { label: 'Visitors' },
safari: { label: 'Safari', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radial Chart - Text</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radial Chart - Text" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<ArcChart
label="browser"
value="visitors"
outerRadius={-20}
innerRadius={-12}
padding={40}
range={[90, -270]}
maxValue={300}
cornerRadius={20}
series={chartData.map((d) => ({
key: d.browser,
color: d.color,
data: [d],
}))}
props={{
arc: { track: { fill: 'var(--muted)' }, motion: 'tween' },
tooltip: { context: { hideDelay: 350 } },
}}
tooltipContext={false}
>
{#snippet belowMarks()}
<circle cx="0" cy="0" r="60" class="fill-background" />
{/snippet}
{#snippet aboveMarks()}
<Text
value={String(chartData[0].visitors)}
textAnchor="middle"
verticalAnchor="middle"
class="fill-foreground text-4xl! font-bold"
dy={3}
/>
<Text
value="Visitors"
textAnchor="middle"
verticalAnchor="middle"
class="fill-muted-foreground!"
dy={22}
/>
{/snippet}
</ArcChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radial Chart - Shape
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { ArcChart, Text } from 'layerchart';
const chartData = [{ browser: 'safari', visitors: 1260, color: 'var(--color-safari)' }];
const chartConfig = {
visitors: { label: 'Visitors' },
safari: { label: 'Safari', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radial Chart - Shape</CardTitle>
<CardDescription>Showing total visitors for the last 6 months</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radial Chart - Shape" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<ArcChart
label="browser"
value="visitors"
outerRadius={88}
innerRadius={66}
trackOuterRadius={83}
trackInnerRadius={72}
padding={40}
range={[90, -270]}
maxValue={chartData[0].visitors * 4}
series={chartData.map((d) => ({
key: d.browser,
color: d.color,
data: [d],
}))}
props={{
arc: { track: { fill: 'var(--muted)' }, motion: 'tween' },
tooltip: { context: { hideDelay: 350 } },
}}
tooltipContext={false}
>
{#snippet belowMarks()}
<circle cx="0" cy="0" r="80" class="fill-background" />
{/snippet}
{#snippet aboveMarks()}
<Text
value={String(chartData[0].visitors)}
textAnchor="middle"
verticalAnchor="middle"
class="fill-foreground text-4xl! font-bold"
dy={3}
/>
<Text
value="Visitors"
textAnchor="middle"
verticalAnchor="middle"
class="fill-muted-foreground!"
dy={22}
/>
{/snippet}
</ArcChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>Radial Chart - Stacked
<script lang="ts">
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { IconPlaceholder } from '@sveltery/components/icons';
import { PieChart, Text } from 'layerchart';
const chartData = [{ month: 'january', desktop: 1260, mobile: 570 }];
const chartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
} satisfies ChartConfig;
</script>
<Card class="flex flex-col w-full max-w-md">
<CardHeader class="items-center">
<CardTitle>Radial Chart - Stacked</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent class="flex-1">
<ChartContainer aria-label="Radial Chart - Stacked" config={chartConfig} class="mx-auto aspect-square max-h-[250px]">
<PieChart
data={[
{ platform: 'mobile', visitors: 570, color: 'var(--color-mobile)' },
{ platform: 'desktop', visitors: 1260, color: 'var(--color-desktop)' },
]}
key="platform"
value="visitors"
c="color"
innerRadius={76}
padding={29}
range={[-90, 90]}
props={{ pie: { sort: null } }}
cornerRadius={4}
>
{#snippet aboveMarks()}
<Text
value={String(chartData[0].desktop + chartData[0].mobile)}
textAnchor="middle"
verticalAnchor="middle"
class="fill-foreground text-2xl! font-bold"
dy={-24}
/>
<Text
value="Visitors"
textAnchor="middle"
verticalAnchor="middle"
class="fill-muted-foreground! text-muted-foreground"
dy={-4}
/>
{/snippet}
{#snippet tooltip()}
<ChartTooltip hideLabel nameKey="platform" />
{/snippet}
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter class="flex-col gap-2 text-sm">
<div class="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month <IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="TradeUpIcon"
phosphor="TrendUpIcon"
remixicon="RiLineChartLine"
class="size-4"
/>
</div>
<div class="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>Tooltip examples
Tooltip - Default
<script lang="ts">
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { scaleBand } from 'd3-scale';
import { BarChart, type ChartContextValue } from 'layerchart';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
const chartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Tooltip - Default</CardTitle>
<CardDescription>Default tooltip with ChartTooltip.</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Tooltip - Default" config={chartConfig}>
<BarChart
bind:context
data={chartData}
xScale={scaleBand().padding(0.25)}
x="date"
axis="x"
rule={false}
series={[
{
key: 'running',
label: 'Running',
color: 'var(--color-running)',
props: { rounded: 'bottom' },
},
{
key: 'swimming',
label: 'Swimming',
color: 'var(--color-swimming)',
},
]}
seriesLayout="stack"
grid={false}
highlight={false}
props={{
bars: {
stroke: 'none',
initialY: context?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
xAxis: {
format: (d) =>
new Date(d).toLocaleDateString('en-US', {
weekday: 'short',
}),
tickLabelProps: {
svgProps: {
y: 13,
},
},
},
}}
>
{#snippet tooltip()}
<ChartTooltip />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
</Card>Tooltip - Line Indicator
<script lang="ts">
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { scaleBand } from 'd3-scale';
import { BarChart, type ChartContextValue } from 'layerchart';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
const chartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Tooltip - Line Indicator</CardTitle>
<CardDescription>Tooltip with line indicator.</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Tooltip - Line Indicator" config={chartConfig}>
<BarChart
bind:context
data={chartData}
xScale={scaleBand().padding(0.25)}
x="date"
axis="x"
rule={false}
series={[
{
key: 'running',
label: 'Running',
color: 'var(--color-running)',
props: { rounded: 'bottom' },
},
{
key: 'swimming',
label: 'Swimming',
color: 'var(--color-swimming)',
},
]}
seriesLayout="stack"
grid={false}
highlight={false}
props={{
bars: {
stroke: 'none',
initialY: context?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
xAxis: {
format: (d) =>
new Date(d).toLocaleDateString('en-US', {
weekday: 'short',
}),
tickLabelProps: {
svgProps: {
y: 13,
},
},
},
}}
>
{#snippet tooltip()}
<ChartTooltip indicator="line" />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
</Card>Tooltip - No Indicator
<script lang="ts">
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { scaleBand } from 'd3-scale';
import { BarChart, type ChartContextValue } from 'layerchart';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
const chartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Tooltip - No Indicator</CardTitle>
<CardDescription>Tooltip with no indicator.</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Tooltip - No Indicator" config={chartConfig}>
<BarChart
bind:context
data={chartData}
xScale={scaleBand().padding(0.25)}
x="date"
axis="x"
rule={false}
series={[
{
key: 'running',
label: 'Running',
color: 'var(--color-running)',
props: { rounded: 'bottom' },
},
{
key: 'swimming',
label: 'Swimming',
color: 'var(--color-swimming)',
},
]}
seriesLayout="stack"
grid={false}
highlight={false}
props={{
bars: {
stroke: 'none',
initialY: context?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
xAxis: {
format: (d) =>
new Date(d).toLocaleDateString('en-US', {
weekday: 'short',
}),
tickLabelProps: {
svgProps: {
y: 13,
},
},
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideIndicator />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
</Card>Tooltip - Custom Label
<script lang="ts">
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { scaleBand } from 'd3-scale';
import { BarChart, type ChartContextValue } from 'layerchart';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
const chartConfig = {
activities: { label: 'Activities' },
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Tooltip - Custom Label</CardTitle>
<CardDescription>Tooltip with custom label from chartConfig.</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Tooltip - Custom Label" config={chartConfig}>
<BarChart
bind:context
data={chartData}
xScale={scaleBand().padding(0.25)}
x="date"
axis="x"
rule={false}
series={[
{
key: 'running',
label: 'Running',
color: 'var(--color-running)',
props: { rounded: 'bottom' },
},
{
key: 'swimming',
label: 'Swimming',
color: 'var(--color-swimming)',
},
]}
seriesLayout="stack"
grid={false}
highlight={false}
props={{
bars: {
stroke: 'none',
initialY: context?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
xAxis: {
format: (d) =>
new Date(d).toLocaleDateString('en-US', {
weekday: 'short',
}),
tickLabelProps: {
svgProps: {
y: 13,
},
},
},
}}
>
{#snippet tooltip()}
<ChartTooltip labelKey="activities" indicator="line" />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
</Card>Tooltip - Label Formatter
<script lang="ts">
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { scaleBand } from 'd3-scale';
import { BarChart, type ChartContextValue } from 'layerchart';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
const chartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Tooltip - Label Formatter</CardTitle>
<CardDescription>Tooltip with label formatter.</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Tooltip - Label Formatter" config={chartConfig}>
<BarChart
bind:context
data={chartData}
xScale={scaleBand().padding(0.25)}
x="date"
axis="x"
rule={false}
series={[
{
key: 'running',
label: 'Running',
color: 'var(--color-running)',
props: { rounded: 'bottom' },
},
{
key: 'swimming',
label: 'Swimming',
color: 'var(--color-swimming)',
},
]}
seriesLayout="stack"
grid={false}
highlight={false}
props={{
bars: {
stroke: 'none',
initialY: context?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
xAxis: {
format: (d) =>
new Date(d).toLocaleDateString('en-US', {
weekday: 'short',
}),
tickLabelProps: {
svgProps: {
y: 13,
},
},
},
}}
>
{#snippet tooltip()}
<ChartTooltip
labelFormatter={(d) =>
new Date(d).toLocaleDateString('en-US', {
day: 'numeric',
month: 'long',
year: 'numeric',
})}
/>
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
</Card>Tooltip - No Label
<script lang="ts">
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { scaleBand } from 'd3-scale';
import { BarChart, type ChartContextValue } from 'layerchart';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
const chartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Tooltip - No Label</CardTitle>
<CardDescription>Tooltip with no label.</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Tooltip - No Label" config={chartConfig}>
<BarChart
bind:context
data={chartData}
xScale={scaleBand().padding(0.25)}
x="date"
axis="x"
rule={false}
series={[
{
key: 'running',
label: 'Running',
color: 'var(--color-running)',
props: { rounded: 'bottom' },
},
{
key: 'swimming',
label: 'Swimming',
color: 'var(--color-swimming)',
},
]}
seriesLayout="stack"
grid={false}
highlight={false}
props={{
bars: {
stroke: 'none',
initialY: context?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
xAxis: {
format: (d) =>
new Date(d).toLocaleDateString('en-US', {
weekday: 'short',
}),
tickLabelProps: {
svgProps: {
y: 13,
},
},
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel hideIndicator />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
</Card>Tooltip - Formatter
<script lang="ts">
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { scaleBand } from 'd3-scale';
import { BarChart, type ChartContextValue } from 'layerchart';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
const chartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Tooltip - Formatter</CardTitle>
<CardDescription>Tooltip with custom formatter.</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Tooltip - Formatter" config={chartConfig}>
<BarChart
bind:context
data={chartData}
xScale={scaleBand().padding(0.25)}
x="date"
axis="x"
rule={false}
series={[
{
key: 'running',
label: 'Running',
color: 'var(--color-running)',
props: { rounded: 'bottom' },
},
{
key: 'swimming',
label: 'Swimming',
color: 'var(--color-swimming)',
},
]}
seriesLayout="stack"
grid={false}
highlight={false}
props={{
bars: {
stroke: 'none',
initialY: context?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
xAxis: {
format: (d) =>
new Date(d).toLocaleDateString('en-US', {
weekday: 'short',
}),
tickLabelProps: {
svgProps: {
y: 13,
},
},
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel>
{#snippet formatter({ name, value })}
<div
class="text-muted-foreground flex min-w-[130px] items-center text-xs"
>
{name}
<div
class="text-foreground ms-auto flex items-baseline gap-0.5 font-mono font-medium tabular-nums"
>
{value}
<span class="text-muted-foreground font-normal"> kcal </span>
</div>
</div>
{/snippet}
</ChartTooltip>
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
</Card>Tooltip - Icons
<script lang="ts">
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import FootprintsIcon from './icons/FootprintsIcon.svelte';
import WavesIcon from './icons/WavesIcon.svelte';
import { scaleBand } from 'd3-scale';
import { BarChart, type ChartContextValue } from 'layerchart';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
const chartConfig = {
running: { label: 'Running', color: 'var(--chart-1)', icon: FootprintsIcon },
swimming: { label: 'Swimming', color: 'var(--chart-2)', icon: WavesIcon },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Tooltip - Icons</CardTitle>
<CardDescription>Tooltip with icons.</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Tooltip - Icons" config={chartConfig}>
<BarChart
bind:context
data={chartData}
xScale={scaleBand().padding(0.25)}
x="date"
axis="x"
rule={false}
series={[
{
key: 'running',
label: 'Running',
color: 'var(--color-running)',
props: { rounded: 'bottom' },
},
{
key: 'swimming',
label: 'Swimming',
color: 'var(--color-swimming)',
},
]}
seriesLayout="stack"
grid={false}
highlight={false}
props={{
bars: {
stroke: 'none',
initialY: context?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
xAxis: {
format: (d) =>
new Date(d).toLocaleDateString('en-US', {
weekday: 'short',
}),
tickLabelProps: {
svgProps: {
y: 13,
},
},
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel />
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
</Card>Tooltip - Advanced
<script lang="ts">
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@sveltery/components/card';
import { type ChartConfig, ChartContainer, ChartTooltip } from '@sveltery/components/chart';
import { scaleBand } from 'd3-scale';
import { BarChart, type ChartContextValue } from 'layerchart';
import { cubicInOut } from 'svelte/easing';
const chartData = [
{ date: '2024-07-15', running: 450, swimming: 300 },
{ date: '2024-07-16', running: 380, swimming: 420 },
{ date: '2024-07-17', running: 520, swimming: 120 },
{ date: '2024-07-18', running: 140, swimming: 550 },
{ date: '2024-07-19', running: 600, swimming: 350 },
{ date: '2024-07-20', running: 480, swimming: 400 },
];
const chartConfig = {
running: { label: 'Running', color: 'var(--chart-1)' },
swimming: { label: 'Swimming', color: 'var(--chart-2)' },
} satisfies ChartConfig;
let context = $state<ChartContextValue>();
</script>
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Tooltip - Advanced</CardTitle>
<CardDescription>Tooltip with custom formatter and total.</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer aria-label="Tooltip - Advanced" config={chartConfig}>
<BarChart
bind:context
data={chartData}
xScale={scaleBand().padding(0.25)}
x="date"
axis="x"
rule={false}
series={[
{
key: 'running',
label: 'Running',
color: 'var(--color-running)',
props: { rounded: 'bottom' },
},
{
key: 'swimming',
label: 'Swimming',
color: 'var(--color-swimming)',
},
]}
seriesLayout="stack"
grid={false}
highlight={false}
props={{
bars: {
stroke: 'none',
initialY: context?.height,
initialHeight: 0,
motion: {
y: { type: 'tween', duration: 500, easing: cubicInOut },
height: { type: 'tween', duration: 500, easing: cubicInOut },
},
},
xAxis: {
format: (d) =>
new Date(d).toLocaleDateString('en-US', {
weekday: 'short',
}),
tickLabelProps: {
svgProps: {
y: 13,
},
},
},
}}
>
{#snippet tooltip()}
<ChartTooltip hideLabel class="w-[180px]">
{#snippet formatter({ item, name, index, value, data })}
<div
style="--color-bg: var(--color-{item.key})"
class="size-2.5 shrink-0 rounded-[2px] bg-(--color-bg)"
></div>
{name}
<div
class="text-foreground ms-auto flex items-baseline gap-0.5 font-mono font-medium tabular-nums"
>
{value}
<span class="text-muted-foreground font-normal"> kcal </span>
</div>
<!-- Add this after the last item-->
{#if index === 1}
<div
class="text-foreground mt-1.5 flex basis-full items-center border-t pt-1.5 text-xs font-medium"
>
Total
<div
class="text-foreground ms-auto flex items-baseline gap-0.5 font-mono font-medium tabular-nums"
>
{Number(data.running) + Number(data.swimming)}
<span class="text-muted-foreground font-normal">
kcal
</span>
</div>
</div>
{/if}
{/snippet}
</ChartTooltip>
{/snippet}
</BarChart>
</ChartContainer>
</CardContent>
</Card>