Claude Code Plugins

Community-maintained marketplace

Feedback
1
0

Use when creating SVG shapes, paths, or generators for charts. Invoke for line/area/arc generators, curves, symbols, pie/donut charts, stacks, ribbons, or path manipulation operations.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name d3-shapes-paths
description Use when creating SVG shapes, paths, or generators for charts. Invoke for line/area/arc generators, curves, symbols, pie/donut charts, stacks, ribbons, or path manipulation operations.
allowed-tools Read, Grep, Glob

D3 Shapes & Paths Expert

Purpose

Expert knowledge of D3's shape generators and path manipulation. Covers line, area, arc, pie, symbol, stack, ribbon generators, curve interpolation, and SVG path construction.

When to Use

Invoke this skill when:

  • Creating line or area charts
  • Building pie or donut charts
  • Generating arc segments (gauges, progress indicators)
  • Creating stacked charts (bar, area)
  • Working with curve interpolation
  • Drawing symbols (circles, squares, diamonds)
  • Building chord diagrams
  • Generating contour plots
  • Manipulating SVG paths
  • Debugging shape rendering issues

Documentation Available

Location: /Users/zach/Documents/cc-skills/docs/d3/

Coverage (203 files):

  • Shapes (146 files):

    • Lines: line generator, curve interpolation
    • Areas: area generator, radial areas
    • Arcs: arc generator, pie layout
    • Symbols: symbol types and custom symbols
    • Stacks: stack layout, stack order
    • Links: link generators (orthogonal, radial)
    • Curves: 15+ interpolation types
  • Paths (12 files):

    • Path construction and serialization
    • Path data parsing
    • Geometric operations
  • Contours (17 files):

    • Contour generation
    • Density estimation
    • Marching squares algorithm
  • Chords (22 files):

    • Chord layout
    • Ribbon generator
    • Chord diagrams
  • Polygons (6 files):

    • Polygon operations
    • Hull, centroid, area calculations

Related Skills

  • d3-core-data: For scales used with shapes
  • d3-geo: For geographic path generators
  • d3-interaction-animation: For animating shapes
  • d3-layouts-hierarchies: For tree/network shapes

Best Practices

  • Define accessors consistently - Use x/y accessors for data binding
  • Use curve interpolators - Choose appropriate curve type for data
  • Handle null data - Set .defined() to skip gaps in lines
  • Use radial variants - For circular/polar charts
  • Optimize path rendering - Simplify paths for large datasets
  • Set arc padding - Add spacing in pie charts
  • Use stack keys - Define series for stacked charts
  • Apply proper transforms - Translate arcs to center

Examples

Example 1: Line Chart with Multiple Series

Question: "How do I create a multi-series line chart?"

Response:

import * as d3 from 'd3';

// Sample data
const data = [
  { date: new Date('2024-01-01'), series1: 30, series2: 20 },
  { date: new Date('2024-01-02'), series1: 45, series2: 35 },
  { date: new Date('2024-01-03'), series1: 40, series2: 30 },
  { date: new Date('2024-01-04'), series1: null, series2: 40 }, // Gap in series1
  { date: new Date('2024-01-05'), series1: 60, series2: 50 },
];

// Create scales
const xScale = d3.scaleTime()
  .domain(d3.extent(data, d => d.date))
  .range([0, 800]);

const yScale = d3.scaleLinear()
  .domain([0, d3.max(data, d => Math.max(d.series1 || 0, d.series2))])
  .range([400, 0])
  .nice();

// Create line generator
const line = d3.line()
  .x(d => xScale(d.date))
  .y(d => yScale(d.value))
  .curve(d3.curveMonotoneX) // Smooth curve
  .defined(d => d.value != null); // Skip null values

// Transform data for each series
const series1Data = data.map(d => ({ date: d.date, value: d.series1 }));
const series2Data = data.map(d => ({ date: d.date, value: d.series2 }));

// Generate path data
const path1 = line(series1Data);
const path2 = line(series2Data);

// Create SVG
const svg = d3.create('svg')
  .attr('width', 800)
  .attr('height', 400);

// Add lines
svg.append('path')
  .attr('d', path1)
  .attr('fill', 'none')
  .attr('stroke', 'steelblue')
  .attr('stroke-width', 2);

svg.append('path')
  .attr('d', path2)
  .attr('fill', 'none')
  .attr('stroke', 'orange')
  .attr('stroke-width', 2);

// Add axes
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale);

svg.append('g')
  .attr('transform', 'translate(0, 400)')
  .call(xAxis);

svg.append('g')
  .call(yAxis);

Curve Types:

  • curveLinear - Straight lines (default)
  • curveMonotoneX - Smooth, no overshoot
  • curveCatmullRom - Smooth, passes through points
  • curveBasis - Smooth B-spline
  • curveStep - Step function

References:

  • See: docs/d3/shape/line.md
  • See: docs/d3/shape/curve.md

Example 2: Area Chart with Gradient

Question: "How do I create an area chart with gradient fill?"

Response:

import * as d3 from 'd3';

const data = [
  { x: 0, y0: 0, y1: 30 },
  { x: 1, y0: 0, y1: 45 },
  { x: 2, y0: 0, y1: 40 },
  { x: 3, y0: 0, y1: 60 },
  { x: 4, y0: 0, y1: 50 },
];

// Create scales
const xScale = d3.scaleLinear()
  .domain([0, 4])
  .range([0, 800]);

const yScale = d3.scaleLinear()
  .domain([0, 60])
  .range([400, 0]);

// Create area generator
const area = d3.area()
  .x(d => xScale(d.x))
  .y0(d => yScale(d.y0)) // Baseline
  .y1(d => yScale(d.y1)) // Top line
  .curve(d3.curveMonotoneX);

// Create SVG
const svg = d3.create('svg')
  .attr('width', 800)
  .attr('height', 400);

// Define gradient
const gradient = svg.append('defs')
  .append('linearGradient')
  .attr('id', 'area-gradient')
  .attr('x1', '0%')
  .attr('y1', '0%')
  .attr('x2', '0%')
  .attr('y2', '100%');

gradient.append('stop')
  .attr('offset', '0%')
  .attr('stop-color', 'steelblue')
  .attr('stop-opacity', 0.8);

gradient.append('stop')
  .attr('offset', '100%')
  .attr('stop-color', 'steelblue')
  .attr('stop-opacity', 0.1);

// Add area
svg.append('path')
  .datum(data)
  .attr('d', area)
  .attr('fill', 'url(#area-gradient)');

// Add top line
const line = d3.line()
  .x(d => xScale(d.x))
  .y(d => yScale(d.y1))
  .curve(d3.curveMonotoneX);

svg.append('path')
  .datum(data)
  .attr('d', line)
  .attr('fill', 'none')
  .attr('stroke', 'steelblue')
  .attr('stroke-width', 2);

Radial Area (for circular charts):

const radialArea = d3.areaRadial()
  .angle(d => angleScale(d.angle))
  .innerRadius(d => radiusScale(d.inner))
  .outerRadius(d => radiusScale(d.outer));

References:

  • See: docs/d3/shape/area.md
  • See: docs/d3/shape/radial.md

Example 3: Pie and Donut Charts

Question: "How do I create a pie chart with labels?"

Response:

import * as d3 from 'd3';

const data = [
  { category: 'A', value: 30 },
  { category: 'B', value: 80 },
  { category: 'C', value: 45 },
  { category: 'D', value: 60 },
];

// Create pie layout
const pie = d3.pie()
  .value(d => d.value)
  .sort(null) // Keep original order
  .padAngle(0.02); // Spacing between slices

// Create arc generator
const arc = d3.arc()
  .innerRadius(0) // Use innerRadius > 0 for donut
  .outerRadius(150);

// Arc for labels (slightly outside)
const labelArc = d3.arc()
  .innerRadius(170)
  .outerRadius(170);

// Color scale
const color = d3.scaleOrdinal()
  .domain(data.map(d => d.category))
  .range(d3.schemeCategory10);

// Create SVG
const svg = d3.create('svg')
  .attr('width', 400)
  .attr('height', 400);

const g = svg.append('g')
  .attr('transform', 'translate(200, 200)'); // Center

// Generate pie data
const pieData = pie(data);

// Add arcs
g.selectAll('path')
  .data(pieData)
  .join('path')
  .attr('d', arc)
  .attr('fill', d => color(d.data.category))
  .attr('stroke', 'white')
  .attr('stroke-width', 2);

// Add labels
g.selectAll('text')
  .data(pieData)
  .join('text')
  .attr('transform', d => `translate(${labelArc.centroid(d)})`)
  .attr('text-anchor', 'middle')
  .text(d => d.data.category);

// Add percentage labels
g.selectAll('.percentage')
  .data(pieData)
  .join('text')
  .attr('class', 'percentage')
  .attr('transform', d => `translate(${arc.centroid(d)})`)
  .attr('text-anchor', 'middle')
  .attr('fill', 'white')
  .attr('font-weight', 'bold')
  .text(d => {
    const percent = ((d.endAngle - d.startAngle) / (2 * Math.PI) * 100).toFixed(1);
    return `${percent}%`;
  });

Donut Chart (add inner radius):

const arc = d3.arc()
  .innerRadius(80)  // Creates donut hole
  .outerRadius(150);

Corner Radius (rounded corners):

const arc = d3.arc()
  .innerRadius(80)
  .outerRadius(150)
  .cornerRadius(5);

References:

  • See: docs/d3/shape/pie.md
  • See: docs/d3/shape/arc.md

Example 4: Stacked Area Chart

Question: "How do I create a stacked area chart?"

Response:

import * as d3 from 'd3';

const data = [
  { date: new Date('2024-01-01'), apples: 30, bananas: 20, oranges: 10 },
  { date: new Date('2024-01-02'), apples: 45, bananas: 35, oranges: 15 },
  { date: new Date('2024-01-03'), apples: 40, bananas: 30, oranges: 20 },
  { date: new Date('2024-01-04'), apples: 60, bananas: 40, oranges: 25 },
];

// Define stack keys (series)
const keys = ['apples', 'bananas', 'oranges'];

// Create stack layout
const stack = d3.stack()
  .keys(keys)
  .order(d3.stackOrderNone) // Keep original order
  .offset(d3.stackOffsetNone); // Start from zero

// Generate stack data
const stackedData = stack(data);
// [
//   [[0, 30], [0, 45], ...],     // apples layer
//   [[30, 50], [45, 80], ...],   // bananas layer
//   [[50, 60], [80, 95], ...],   // oranges layer
// ]

// Create scales
const xScale = d3.scaleTime()
  .domain(d3.extent(data, d => d.date))
  .range([0, 800]);

const yScale = d3.scaleLinear()
  .domain([0, d3.max(stackedData[stackedData.length - 1], d => d[1])])
  .range([400, 0])
  .nice();

// Create area generator
const area = d3.area()
  .x(d => xScale(d.data.date))
  .y0(d => yScale(d[0])) // Bottom of stack
  .y1(d => yScale(d[1])) // Top of stack
  .curve(d3.curveMonotoneX);

// Color scale
const color = d3.scaleOrdinal()
  .domain(keys)
  .range(d3.schemeCategory10);

// Create SVG
const svg = d3.create('svg')
  .attr('width', 800)
  .attr('height', 400);

// Add layers
svg.selectAll('path')
  .data(stackedData)
  .join('path')
  .attr('d', area)
  .attr('fill', d => color(d.key))
  .attr('stroke', 'white')
  .attr('stroke-width', 1);

// Add legend
const legend = svg.append('g')
  .attr('transform', 'translate(700, 20)');

legend.selectAll('rect')
  .data(keys)
  .join('rect')
  .attr('y', (d, i) => i * 25)
  .attr('width', 20)
  .attr('height', 20)
  .attr('fill', d => color(d));

legend.selectAll('text')
  .data(keys)
  .join('text')
  .attr('x', 25)
  .attr('y', (d, i) => i * 25 + 15)
  .text(d => d);

Stack Orders:

  • stackOrderNone - Original order
  • stackOrderAscending - Smallest on top
  • stackOrderDescending - Largest on top
  • stackOrderInsideOut - Largest in middle

Stack Offsets:

  • stackOffsetNone - Zero baseline
  • stackOffsetExpand - Normalize to [0, 1]
  • stackOffsetSilhouette - Center around zero
  • stackOffsetWiggle - Minimize changes in slope

References:

  • See: docs/d3/shape/stack.md

Example 5: Symbols and Custom Shapes

Question: "How do I use D3 symbols for scatter plots?"

Response:

import * as d3 from 'd3';

const data = [
  { x: 30, y: 20, type: 'A' },
  { x: 50, y: 80, type: 'B' },
  { x: 80, y: 50, type: 'A' },
  { x: 120, y: 90, type: 'C' },
];

// Create scales
const xScale = d3.scaleLinear()
  .domain([0, 150])
  .range([0, 800]);

const yScale = d3.scaleLinear()
  .domain([0, 100])
  .range([400, 0]);

// Symbol types
const symbolTypes = [
  d3.symbolCircle,
  d3.symbolSquare,
  d3.symbolTriangle,
  d3.symbolStar,
  d3.symbolDiamond,
  d3.symbolCross,
];

// Symbol scale
const symbolScale = d3.scaleOrdinal()
  .domain(['A', 'B', 'C'])
  .range([d3.symbolCircle, d3.symbolSquare, d3.symbolTriangle]);

// Create symbol generator
const symbol = d3.symbol()
  .size(200); // Area in square pixels

// Create SVG
const svg = d3.create('svg')
  .attr('width', 800)
  .attr('height', 400);

// Add symbols
svg.selectAll('path')
  .data(data)
  .join('path')
  .attr('d', d => {
    symbol.type(symbolScale(d.type));
    return symbol();
  })
  .attr('transform', d => `translate(${xScale(d.x)}, ${yScale(d.y)})`)
  .attr('fill', 'steelblue')
  .attr('stroke', 'white')
  .attr('stroke-width', 2);

Available Symbol Types:

  • symbolCircle - Circle
  • symbolSquare - Square
  • symbolTriangle - Upward triangle
  • symbolStar - Five-pointed star
  • symbolDiamond - Diamond
  • symbolCross - Plus sign
  • symbolWye - Y shape

Custom Symbol:

const customSymbol = {
  draw(context, size) {
    const r = Math.sqrt(size / 5) / 2;
    context.moveTo(-3 * r, -r);
    context.lineTo(-r, -r);
    context.lineTo(-r, -3 * r);
    context.lineTo(r, -3 * r);
    context.lineTo(r, -r);
    context.lineTo(3 * r, -r);
    context.lineTo(3 * r, r);
    context.lineTo(r, r);
    context.lineTo(r, 3 * r);
    context.lineTo(-r, 3 * r);
    context.lineTo(-r, r);
    context.lineTo(-3 * r, r);
    context.closePath();
  },
};

const symbol = d3.symbol()
  .type(customSymbol)
  .size(200);

References:

  • See: docs/d3/shape/symbol.md

Common Patterns

Responsive Line Chart

const line = d3.line()
  .x(d => xScale(d.x))
  .y(d => yScale(d.y))
  .curve(d3.curveMonotoneX);

svg.append('path')
  .datum(data)
  .attr('d', line)
  .attr('fill', 'none')
  .attr('stroke', 'steelblue')
  .attr('stroke-width', 2);

Arc with Hover Effect

const arc = d3.arc()
  .innerRadius(80)
  .outerRadius(150);

const arcHover = d3.arc()
  .innerRadius(80)
  .outerRadius(160); // Larger

svg.selectAll('path')
  .on('mouseenter', function() {
    d3.select(this).transition()
      .attr('d', arcHover);
  })
  .on('mouseleave', function() {
    d3.select(this).transition()
      .attr('d', arc);
  });

Link Generators (for node diagrams)

const link = d3.linkHorizontal()
  .x(d => d.x)
  .y(d => d.y);

const linkData = {
  source: { x: 0, y: 100 },
  target: { x: 200, y: 150 },
};

svg.append('path')
  .attr('d', link(linkData))
  .attr('fill', 'none')
  .attr('stroke', 'black');

Search Helpers

# Find line/area docs
grep -r "line\|area\|curve" /Users/zach/Documents/cc-skills/docs/d3/shape/

# Find pie/arc docs
grep -r "pie\|arc\|donut" /Users/zach/Documents/cc-skills/docs/d3/shape/

# Find stack docs
grep -r "stack\|layer" /Users/zach/Documents/cc-skills/docs/d3/shape/

# Find symbol docs
grep -r "symbol\|scatter" /Users/zach/Documents/cc-skills/docs/d3/shape/

# Find path operations
grep -r "path\|serialize" /Users/zach/Documents/cc-skills/docs/d3/path/

# List shape generators
ls /Users/zach/Documents/cc-skills/docs/d3/shape/

Common Errors

  • Path not rendering: Check scale domains match data range

    • Solution: Use d3.extent() to compute correct domain
  • Area chart inverted: Y scale range is backwards

    • Solution: Set range as [height, 0] (SVG y grows downward)
  • Pie chart off-center: Missing transform translate

    • Solution: Add transform="translate(cx, cy)" to group
  • Gaps in line: Null/undefined values in data

    • Solution: Set .defined(d => d.value != null)
  • Stack negative values: stackOffsetNone doesn't handle negatives

    • Solution: Use stackOffsetDiverging for +/- values

Performance Tips

  1. Use .curve(d3.curveLinear) - Fastest rendering
  2. Simplify paths - Use fewer data points for large datasets
  3. Avoid recomputing generators - Create once, reuse
  4. Use context rendering - For Canvas instead of SVG
  5. Batch path updates - Use .datum() instead of .data() when possible
  6. Optimize arc rendering - Use fewer padAngle for large datasets

Notes

  • Documentation covers D3 v7 (latest version)
  • All generators support both SVG and Canvas contexts
  • Curve interpolators are interchangeable across line/area generators
  • Pie layout computes startAngle and endAngle for each datum
  • Stack layout adds [y0, y1] arrays to each data point
  • Symbol size is in square pixels (area, not radius)
  • Path generators are immutable - methods return new generators
  • File paths reference local documentation cache
  • For latest updates, check https://d3js.org/d3-shape