
Svelte Layerchart
- 60 installs
- 92 repo stars
- Updated April 29, 2026
- spences10/svelte-skills-kit
Helps with ai & agent building tasks.
About
svelte-layerchart is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- svelte-layerchart
- AI & Agent Building
- AI-coding skill
Svelte Layerchart by the numbers
- 60 all-time installs (skills.sh)
- +6 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #6,460 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/spences10/svelte-skills-kit --skill svelte-layerchartAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 60 |
|---|---|
| repo stars | ★ 92 |
| Last updated | April 29, 2026 |
| Repository | spences10/svelte-skills-kit ↗ |
What it does
Helps with ai & agent building tasks.
Files
Svelte LayerChart
Docs: layerchart.com
Install
npm i layerchart d3-scaleQuick Start
<Chart {data} x="date" y="value" tooltip={{ mode: 'bisect-x' }}>
<Svg><Area class="fill-primary/20" /><Highlight points /></Svg>
<Tooltip.Root>{#snippet children({ data })}{data.value}{/snippet}</Tooltip.Root>
</Chart>Core Patterns
- Tooltip:
{#snippet children({ data })}- NOTlet:data - Chart context:
{#snippet children({ context })} - Gradient:
{#snippet children({ gradient })} - Enable tooltip:
tooltip={{ mode: 'band' | 'bisect-x' }} - Type data:
{#snippet children({ data }: { data: MyType })}
Tooltip Modes
| Mode | Use Case |
|---|---|
band | Bar charts (scaleBand) |
bisect-x | Time-series area/line |
quadtree-x | Area (nearest x) |
quadtree | Scatter plots |
References
- full-patterns.md - Area, Bar, Pie,
Calendar
- tooltip-modes.md - All modes
- graph-patterns.md - ForceGraph,
zoom/pan
LayerChart Svelte 5 Full Patterns
Svelte 5 Snippet Patterns
Tooltip.Root children snippet
WRONG (Svelte 4):
<Tooltip.Root let:data>
<Tooltip.Header>{data.label}</Tooltip.Header>
</Tooltip.Root>CORRECT (Svelte 5):
<Tooltip.Root>
{#snippet children({ data })}
<Tooltip.Header>{data.label}</Tooltip.Header>
<Tooltip.List>
<Tooltip.Item label="Value" value={data.value} />
</Tooltip.List>
{/snippet}
</Tooltip.Root>The children snippet receives { data, payload }:
data- The chart data point that triggered the tooltippayload- Array of tooltip payloads for multi-series charts
Chart children snippet
Access context via the children snippet:
<Chart {data} x="date" y="value">
{#snippet children({ context })}
<!-- Access scales, dimensions, tooltip state -->
{@const avg = mean(data, (d) => d.value)}
<Svg>
<Rule x={avg} />
<Text x={context.xScale(avg)} y={0} value="Avg" />
</Svg>
{/snippet}
</Chart>LinearGradient children snippet
<LinearGradient class="from-primary/50 to-primary/1" vertical>
{#snippet children({ gradient })}
<Area
fill={gradient}
line={{ class: 'stroke-primary stroke-2' }}
/>
{/snippet}
</LinearGradient>Highlight area snippet
<Highlight>
{#snippet area({ area })}
<RectClipPath
x={area.x}
y={area.y}
width={area.width}
height={area.height}
>
<Bars class="fill-primary" />
</RectClipPath>
{/snippet}
</Highlight>Axis tickLabel snippet
<Axis
placement="bottom"
format="day"
ticks={(scale) => scale.domain()}
>
{#snippet tickLabel({ props, index })}
<Text {...props} textAnchor={index ? 'end' : 'start'} />
{/snippet}
</Axis>Spline endContent snippet
<Spline {data} class="stroke-2" stroke={color}>
{#snippet endContent()}
<Circle r={4} fill={color} />
<Text value={label} dx={6} class="text-xs" fill={color} />
{/snippet}
</Spline>Typing the Snippet Data
To avoid implicit any errors, type the data:
<script lang="ts">
type YearlyData = { year: string; visitors: number }
</script>
<Tooltip.Root>
{#snippet children({ data }: { data: YearlyData })}
<Tooltip.Header>{data.year}</Tooltip.Header>
{/snippet}
</Tooltip.Root>Complete Bar Chart Example
<script lang="ts">
import { scaleBand } from 'd3-scale'
import {
Axis,
Bars,
Chart,
Highlight,
Svg,
Tooltip,
} from 'layerchart'
type DataPoint = { label: string; value: number }
let data: DataPoint[] = [
{ label: '2023', value: 100 },
{ label: '2024', value: 150 },
]
</script>
<div class="h-64">
<Chart
{data}
x="value"
xDomain={[0, null]}
xNice
y="label"
yScale={scaleBand().padding(0.4)}
padding={{ left: 48, bottom: 24 }}
tooltip={{ mode: 'band' }}
>
<Svg>
<Axis placement="bottom" grid rule />
<Axis placement="left" rule />
<Bars radius={4} class="fill-primary" />
<Highlight area />
</Svg>
<Tooltip.Root>
{#snippet children({ data }: { data: DataPoint })}
<Tooltip.Header>{data.label}</Tooltip.Header>
<Tooltip.List>
<Tooltip.Item label="Value" value={data.value} />
</Tooltip.List>
{/snippet}
</Tooltip.Root>
</Chart>
</div>Complete Area Chart Example
<script lang="ts">
import { Area, Axis, Chart, Highlight, Svg, Tooltip } from 'layerchart'
type TimeData = { date: Date; value: number }
let data: TimeData[] = [...]
</script>
<div class="h-48">
<Chart
{data}
x="date"
y="value"
yDomain={[0, null]}
yNice
padding={{ left: 40, bottom: 24 }}
tooltip={{ mode: 'bisect-x' }}
>
<Svg>
<Axis placement="left" grid rule />
<Axis placement="bottom" rule />
<Area
line={{ class: 'stroke-primary stroke-2' }}
class="fill-primary/20"
/>
<Highlight points lines />
</Svg>
<Tooltip.Root>
{#snippet children({ data }: { data: TimeData })}
<Tooltip.Header
>{data.date.toLocaleDateString()}</Tooltip.Header
>
<Tooltip.List>
<Tooltip.Item label="Value" value={data.value} />
</Tooltip.List>
{/snippet}
</Tooltip.Root>
</Chart>
</div>Multi-series with Context Access
<Chart
data={flatData}
x="date"
y="value"
c="series"
cDomain={['apples', 'bananas']}
cRange={['var(--color-info)', 'var(--color-success)']}
tooltip={{ mode: 'quadtree' }}
>
{#snippet children({ context })}
<Svg>
{#each seriesData as [series, data]}
{@const color = context.cScale?.(series)}
{@const active =
context.tooltip.data == null ||
context.tooltip.data.series === series}
<g class={!active ? 'opacity-20' : ''}>
<Spline {data} stroke={color} class="stroke-2" />
</g>
{/each}
<Highlight points lines />
</Svg>
<Tooltip.Root>
{#snippet children({ data })}
<Tooltip.Header value={data.date} format="day" />
<Tooltip.List>
<Tooltip.Item
label={data.series}
value={data.value}
color={context.cScale?.(data.series)}
/>
</Tooltip.List>
{/snippet}
</Tooltip.Root>
{/snippet}
</Chart>Manual Tooltip Control
For custom tooltip behaviour (e.g., individual bar tooltips):
<Chart {data} x="values" y="year">
{#snippet children({ context })}
<Svg>
{#each data as d}
<Bar
data={d}
onpointerenter={(e) => context.tooltip.show(e, d)}
onpointermove={(e) => context.tooltip.show(e, d)}
onpointerleave={() => context.tooltip.hide()}
onclick={() => alert(JSON.stringify(d))}
/>
{/each}
</Svg>
<Tooltip.Root>
{#snippet children({ data })}
<Tooltip.Header>{data.year}</Tooltip.Header>
{/snippet}
</Tooltip.Root>
{/snippet}
</Chart>Calendar Heatmap
<script lang="ts">
import { Calendar, Chart, Svg, Tooltip } from 'layerchart'
import { scaleSequential } from 'd3-scale'
import { interpolateGreens } from 'd3-scale-chromatic'
type DayData = { date: Date; value: number }
let { data }: { data: DayData[] } = $props()
const colorScale = scaleSequential(interpolateGreens).domain([0, 10])
</script>
<div class="h-32">
<Chart {data} x="date" tooltip={{ mode: 'band' }}>
<Svg>
<Calendar
{colorScale}
cellSize={12}
cellGap={2}
monthLabels
weekdayLabels
/>
</Svg>
<Tooltip.Root>
{#snippet children({ data }: { data: DayData })}
<Tooltip.Header>
{data.date.toLocaleDateString()}
</Tooltip.Header>
<Tooltip.Item label="Count" value={data.value} />
{/snippet}
</Tooltip.Root>
</Chart>
</div>Pie/Donut Chart
<script lang="ts">
import { Arc, Chart, Pie, Svg, Tooltip } from 'layerchart'
type SliceData = { label: string; value: number; color: string }
let { data }: { data: SliceData[] } = $props()
</script>
<div class="h-64">
<Chart {data} tooltip={{ mode: 'manual' }}>
<Svg>
<Pie
value="value"
innerRadius={40}
padAngle={0.02}
cornerRadius={4}
>
{#snippet children({ arcs })}
{#each arcs as arc}
<Arc data={arc} fill={arc.data.color} />
{/each}
{/snippet}
</Pie>
</Svg>
</Chart>
</div>Common Imports
import { scaleBand, scaleTime, scaleOrdinal } from "d3-scale";
import {
Arc,
Area,
Axis,
Bar,
Bars,
Calendar,
Canvas,
Chart,
Circle,
ForceGraph,
ForceSimulation,
Group,
Highlight,
Labels,
Layer,
LinearGradient,
Link,
Pie,
Points,
RectClipPath,
Rule,
Spline,
Svg,
Text,
Tooltip,
Transform,
} from "layerchart";LayerChart Graph & Network Patterns
ForceGraph Basic
<script lang="ts">
import {
Chart,
ForceSimulation,
Group,
Link,
ForceGraph,
Svg,
Text,
} from 'layerchart'
import {
forceCenter,
forceCollide,
forceLink,
forceManyBody,
} from 'd3-force'
type Node = { id: string; label: string; group?: string }
type LinkType = { source: string; target: string }
let { nodes, links }: { nodes: Node[]; links: LinkType[] } = $props()
</script>
<div class="h-96">
<Chart>
<Svg>
<ForceGraph {nodes} {links}>
<ForceSimulation
forces={{
charge: forceManyBody().strength(-100),
center: forceCenter(),
collide: forceCollide(20),
link: forceLink().id((d) => d.id),
}}
>
{#snippet children({ simulation })}
{#each simulation.links as link}
<Link
data={link}
class="stroke-surface-content/30"
/>
{/each}
{#each simulation.nodes as node}
<Group x={node.x} y={node.y}>
<circle r="8" class="fill-primary" />
<Text
value={node.label}
dy={-12}
textAnchor="middle"
class="text-xs"
/>
</Group>
{/each}
{/snippet}
</ForceSimulation>
</ForceGraph>
</Svg>
</Chart>
</div>ForceGraph with Transform (Zoom/Pan)
<Chart>
<Canvas>
<Transform mode="canvas" initialTransform={{ scale: 0.8 }}>
<ForceGraph {nodes} {links}>
<ForceSimulation>
<!-- ... -->
</ForceSimulation>
</ForceGraph>
</Transform>
</Canvas>
</Chart>CRITICAL: Use mode="canvas" for zoom/pan controls in Canvas context.
Force Configuration
import {
forceCenter,
forceCollide,
forceLink,
forceManyBody,
forceX,
forceY,
} from "d3-force";
const forces = {
// Repulsion between nodes
charge: forceManyBody().strength(-200),
// Center gravity
center: forceCenter(),
// Prevent overlap
collide: forceCollide(30),
// Link distance
link: forceLink()
.id((d) => d.id)
.distance(50),
// Pull toward x/y positions
x: forceX().strength(0.1),
y: forceY().strength(0.1),
};Node Styling by Group
{#each simulation.nodes as node}
<Group x={node.x} y={node.y}>
<circle
r={node.size ?? 8}
class={node.group === 'primary'
? 'fill-primary'
: 'fill-secondary'}
/>
</Group>
{/each}Link Styling
{#each simulation.links as link}
<Link
data={link}
class="stroke-surface-content/20"
strokeWidth={link.weight ?? 1}
/>
{/each}Common Imports
import {
Canvas,
Chart,
ForceGraph,
ForceSimulation,
Group,
Link,
Svg,
Text,
Transform,
} from "layerchart";
import { forceCenter, forceCollide, forceLink, forceManyBody } from "d3-force";LayerChart Tooltip Modes
Required: Enable tooltip on Chart
The Chart component MUST have a tooltip prop to enable tooltip detection:
<!-- Bar charts with scaleBand -->
<Chart tooltip={{ mode: 'band' }} ...>
<!-- Area/Line charts with scaleTime -->
<Chart tooltip={{ mode: 'bisect-x' }} ...>
<Chart tooltip={{ mode: 'quadtree-x' }} ...>
<!-- Scatter plots -->
<Chart tooltip={{ mode: 'quadtree' }} ...>All Tooltip Modes
| Mode | Use Case | Notes |
|---|---|---|
band | Bar charts with scaleBand() | |
bisect-x | Time-series area/line charts | Requires sorted values |
bisect-y | Vertical time-series charts | Requires sorted values |
bisect-band | Mixed band/continuous scales | Requires sorted values |
quadtree | Scatter plots (finds nearest point) | |
quadtree-x | Area charts (ignores y, finds nearest x) | |
quadtree-y | Vertical charts (ignores x, finds nearest y) | |
bounds | Duration/range charts | |
voronoi | Complex scatter plots with voronoi cells | |
manual | Custom tooltip control via context.tooltip | Default mode |
Tooltip with click handler
<Chart
tooltip={{
mode: 'band',
onclick(e, { data }) {
alert('Clicked: ' + JSON.stringify(data))
},
}}
>TooltipContext Props
From the source (TooltipContext.svelte):
type TooltipContextProps = {
mode?: TooltipMode // default: 'manual'
findTooltipData?: 'closest' | 'left' | 'right' // default: 'closest'
raiseTarget?: boolean // default: false
locked?: boolean // default: false
touchEvents?: 'none' | 'pan-x' | 'pan-y' | 'auto' // default: 'pan-y'
radius?: number // default: Infinity (for quadtree/voronoi)
debug?: boolean // default: false
onclick?: (e: MouseEvent, { data }: { data: any }) => any
hideDelay?: number // default: 0
}Mode Selection Guide
For Bar Charts
<!-- Standard horizontal bars -->
<Chart yScale={scaleBand()} tooltip={{ mode: 'band' }}>
<!-- Grouped/stacked bars -->
<Chart yScale={scaleBand()} tooltip={{ mode: 'band' }}>For Line/Area Charts
<!-- Time-series (sorted by date) -->
<Chart x="date" tooltip={{ mode: 'bisect-x' }}>
<!-- Alternative: quadtree for unsorted -->
<Chart x="date" tooltip={{ mode: 'quadtree-x' }}>For Scatter Plots
<!-- Find nearest point -->
<Chart tooltip={{ mode: 'quadtree' }}>
<!-- With voronoi cells (visible regions) -->
<Chart tooltip={{ mode: 'voronoi' }}>For Duration/Range Charts
<!-- Charts with start/end values -->
<Chart x={['start', 'end']} tooltip={{ mode: 'bounds' }}>Debug Mode
Enable debug to see tooltip hit areas:
<Chart tooltip={{ mode: 'band', debug: true }}>This shows red outlines around tooltip detection areas.