with one click
preview-d3
// Create interactive 2D data visualizations using D3.js with zoom, pan, and custom rendering
// Create interactive 2D data visualizations using D3.js with zoom, pan, and custom rendering
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | preview-d3 |
| description | Create interactive 2D data visualizations using D3.js with zoom, pan, and custom rendering |
| user-invocable | true |
| commands | ["preview-d3"] |
Interactive D3.js visualization viewer that renders custom data visualizations with built-in zoom, pan, and export capabilities.
When the user asks to create a D3 visualization, write the D3 code and pipe it to the script. Use the Bash tool to execute this skill's run.sh script:
# Pipe D3 code
cat visualization.js | ./run.sh
# Or from a file
./run.sh chart.d3
The script handles all HTML generation and automatically opens the result in the browser. Do NOT open the file manually to avoid duplicate tabs.
# Preview a D3 visualization file
/preview-d3 network-graph.d3
# Pipe D3 code (preferred for temporary content)
cat visualization.js | /preview-d3
echo "const svg = d3.select('#visualization').append('svg')..." | /preview-d3
Best Practice: For temporary or generated visualizations, prefer piping over creating temporary files. This avoids cluttering your filesystem and the content is automatically cleaned up.
The script works with sensible defaults but supports these flags for flexibility:
-o, --output PATH - Custom output path--no-browser - Skip browser, output file path onlyUse this skill when the user wants to:
Your D3 code should be self-contained JavaScript that:
// Get container dimensions
const container = document.querySelector('#visualization');
const rect = container.getBoundingClientRect();
const width = rect.width;
const height = rect.height;
const margin = { top: 60, right: 40, bottom: 60, left: 60 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
// Sample data
const data = [
{ category: 'A', value: 30 },
{ category: 'B', value: 80 },
{ category: 'C', value: 45 },
];
// Create SVG
const svg = d3.select('#visualization').append('svg').attr('width', width).attr('height', height);
const chart = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);
// Create scales, axes, and visualization elements
// Your D3 code here...
//Get container dimensions
const container = document.querySelector('#visualization');
const rect = container.getBoundingClientRect();
const width = rect.width;
const height = rect.height;
const margin = { top: 60, right: 40, bottom: 60, left: 60 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
// Sample data
const data = [
{ category: 'A', value: 30 },
{ category: 'B', value: 80 },
{ category: 'C', value: 45 },
{ category: 'D', value: 60 },
{ category: 'E', value: 20 },
];
// Create SVG
const svg = d3.select('#visualization').append('svg').attr('width', width).attr('height', height);
const chart = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);
// Scales
const xScale = d3
.scaleBand()
.domain(data.map((d) => d.category))
.range([0, innerWidth])
.padding(0.2);
const yScale = d3
.scaleLinear()
.domain([0, d3.max(data, (d) => d.value)])
.nice()
.range([innerHeight, 0]);
// Axes
chart.append('g').attr('transform', `translate(0,${innerHeight})`).call(d3.axisBottom(xScale));
chart.append('g').call(d3.axisLeft(yScale));
// Bars with tooltip
const tooltip = d3
.select('body')
.append('div')
.attr('class', 'd3-tooltip')
.style('position', 'absolute')
.style('opacity', 0);
chart
.selectAll('rect')
.data(data)
.join('rect')
.attr('x', (d) => xScale(d.category))
.attr('y', (d) => yScale(d.value))
.attr('width', xScale.bandwidth())
.attr('height', (d) => innerHeight - yScale(d.value))
.attr('fill', '#3498db')
.on('mouseover', (event, d) => {
tooltip.transition().duration(200).style('opacity', 1);
tooltip
.html(`<strong>${d.category}</strong><br/>Value: ${d.value}`)
.style('left', event.pageX + 10 + 'px')
.style('top', event.pageY - 10 + 'px');
})
.on('mouseout', () => {
tooltip.transition().duration(200).style('opacity', 0);
});
// Title
chart
.append('text')
.attr('x', innerWidth / 2)
.attr('y', -20)
.attr('text-anchor', 'middle')
.style('font-size', '18px')
.style('font-weight', 'bold')
.text('Sample Bar Chart');
const line = d3
.line()
.x((d) => xScale(d.date))
.y((d) => yScale(d.value));
svg
.append('path')
.datum(data)
.attr('fill', 'none')
.attr('stroke', '#3498db')
.attr('stroke-width', 2)
.attr('d', line);
svg
.selectAll('circle')
.data(data)
.join('circle')
.attr('cx', (d) => xScale(d.x))
.attr('cy', (d) => yScale(d.y))
.attr('r', 5)
.attr('fill', '#3498db');
const pie = d3.pie().value((d) => d.value);
const arc = d3.arc().innerRadius(0).outerRadius(radius);
svg
.selectAll('path')
.data(pie(data))
.join('path')
.attr('d', arc)
.attr('fill', (d, i) => d3.schemeCategory10[i]);
Your code runs with:
d3#visualization ready in the DOM#visualization)position: absolute CSSevent.pageX/pageY for positioning (not clientX/Y).d3The skill generates a standalone HTML file at:
.preview-skills/d3/{filename}.html
This skill is standalone and includes all dependencies:
lib/templates/To modify the skill:
config.sh for configurationtemplates/scripts/d3-renderer.js for behaviortemplates/styles/d3.css for stylingrun.sh to test changes