Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Generates dark-themed, accessible data visualization components using Chart.js or Recharts. Produces glass morphism styled charts that match the user's design system with proper accessibility, responsive sizing, and performance optimization. Triggered when the user asks to create a chart, visualize data, add a graph, or build a dashboard component.
.claude/skills/0xjitsu-chart-builder/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 9% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 79% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 22% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 90% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 16% | 0% |
Dark-themed, accessible data visualization generator.
Activate this skill when the user:
| Scenario | Library | Reason | |----------|---------|--------| | Standalone chart, no React | Chart.js | Lightweight, canvas-based | | React/Next.js project | Recharts | Native React components, composable | | Complex interactive dashboards | Recharts | Better state management integration | | Static image export needed | Chart.js | Canvas toDataURL() support |
All charts must follow these design tokens to match the user's dark theme:
jsconst chartTheme = { background: '#18181B', // zinc-900 surface: 'rgba(255,255,255,0.05)', // glass bg border: 'rgba(255,255,255,0.10)', // glass border gridLines: 'rgba(255,255,255,0.06)', labelText: '#D4D4D8', // zinc-300 valueText: '#F4F4F5', // zinc-100 tooltip: { bg: 'rgba(24,24,27,0.90)', border: 'rgba(255,255,255,0.10)', blur: '16px', }, };
Use these for data series — ordered by visual priority:
| Index | Name | Hex | Use case | |-------|------|-----|----------| | 0 | Blue | #3B82F6 | Primary metric | | 1 | Purple | #8B5CF6 | Secondary metric | | 2 | Emerald | #10B981 | Positive/growth | | 3 | Amber | #F59E0B | Warning/attention | | 4 | Rose | #F43F5E | Negative/decline | | 5 | Cyan | #06B6D4 | Tertiary metric |
Wrap every chart in a glass container:
jsx<div className="backdrop-blur-xl bg-white/5 border border-white/10 rounded-2xl p-6"> <h3 className="text-zinc-100 text-lg font-semibold mb-4">{title}</h3> <div className="min-h-[300px]" role="img" aria-label={ariaLabel}> {/* Chart component */} </div> </div>
Best for: trends over time, continuous data.
linearGradient from accent to transparent)type="monotone" (Recharts) or tension: 0.4 (Chart.js)Best for: comparisons between categories.
radius={[4, 4, 0, 0]}Best for: volume/magnitude over time.
Best for: part-to-whole relationships (max 6 segments).
Best for: correlation between two variables.
Best for: multi-dimensional comparison (3-8 axes).
Every chart must include:
jsx <div role="img" aria-label="Monthly revenue trend showing 23% growth from January to June 2025">
css @media (prefers-reduced-motion: reduce) { .chart-container * { animation: none !important; transition: none !important; } }
jsx <table className="sr-only"> <caption>Monthly revenue data</caption> {/* Full data in tabular form */} </table>
zinc-900).responsive: true / width="100%")min-h-[300px] on the wrapper to prevent CLS@media print)Charts are heavy — always lazy load:
jsximport dynamic from 'next/dynamic'; const RevenueChart = dynamic(() => import('@/components/charts/RevenueChart'), { loading: () => ( <div className="backdrop-blur-xl bg-white/5 border border-white/10 rounded-2xl p-6 min-h-[300px] animate-pulse" /> ), ssr: false, });
ssr: false — canvas/SVG charts need the DOMjsxconst CustomTooltip = ({ active, payload, label }) => { if (!active || !payload) return null; return ( <div className="backdrop-blur-xl bg-zinc-900/90 border border-white/10 rounded-lg px-3 py-2 shadow-xl"> <p className="text-zinc-400 text-xs mb-1">{label}</p> {payload.map((entry, i) => ( <p key={i} className="text-zinc-100 text-sm font-medium"> <span style={{ color: entry.color }}>●</span> {entry.name}: {entry.value} </p> ))} </div> ); };
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 18,890 | 14,209 | -25% | 1 | 1 | 0% | 4,548 | 4,977 | +9% | 0 | 0 | — |
case-02 | fail→fail | 27,207 | 13,097 | -52% | 1 | 1 | 0% | 6,183 | 4,532 | -27% | 0 | 0 | — |
case-03 | fail→fail | 26,284 | 14,964 | -43% | 1 | 1 | 0% | 5,780 | 5,003 | -13% | 0 | 0 | — |
case-04 | pass→pass | 13,591 | 14,007 | +3% | 1 | 1 | 0% | 2,869 | 4,721 | +65% | 0 | 0 | — |
case-05 | pass→pass | 15,936 | 15,756 | -1% | 1 | 1 | 0% | 3,298 | 5,021 | +52% | 0 | 0 | — |
case-06 | pass→pass | 12,022 | 12,068 | +0% | 1 | 1 | 0% | 2,429 | 4,749 | +96% | 0 | 0 | — |
case-07 | fail→pass | 12,921 | 14,257 | +10% | 1 | 1 | 0% | 2,658 | 4,765 | +79% | 0 | 0 | — |
case-08 | pass→pass | 15,368 | 14,325 | -7% | 1 | 1 | 0% | 2,809 | 4,948 | +76% | 0 | 0 | — |
case-09 | pass→pass | 15,164 | 12,594 | -17% | 1 | 1 | 0% | 3,023 | 4,458 | +47% | 0 | 0 | — |
case-10 | fail→pass | 13,970 | 7,332 | -48% | 1 | 1 | 0% | 2,589 | 3,160 | +22% | 0 | 0 | — |
case-11 | fail→pass | 13,137 | 24,829 | +89% | 1 | 1 | 0% | 2,378 | 4,529 | +90% | 0 | 0 | — |
case-12 | fail→pass | 9,435 | 2,364 | -75% | 1 | 1 | 0% | 1,745 | 2,016 | +16% | 0 | 0 | — |
case-13 | pass→fail | 16,240 | 12,493 | -23% | 1 | 1 | 0% | 2,759 | 4,088 | +48% | 0 | 0 | — |
case-14 | pass→pass | 10,455 | 3,736 | -64% | 1 | 1 | 0% | 2,078 | 2,333 | +12% | 0 | 0 | — |
case-15 | pass→pass | 11,760 | 13,381 | +14% | 1 | 1 | 0% | 1,953 | 4,621 | +137% | 0 | 0 | — |
case-16 | fail→pass | 15,187 | 7,346 | -52% | 1 | 1 | 0% | 2,788 | 3,184 | +14% | 0 | 0 | — |
case-17 | fail→pass | 9,043 | 2,391 | -74% | 1 | 1 | 0% | 1,496 | 2,031 | +36% | 0 | 0 | — |
case-18 | pass→pass | 16,349 | 16,641 | +2% | 1 | 1 | 0% | 2,691 | 5,248 | +95% | 0 | 0 | — |
case-19 | fail→pass | 13,694 | 8,411 | -39% | 1 | 1 | 0% | 2,259 | 3,384 | +50% | 0 | 0 | — |
case-20 | fail→pass | 13,326 | 11,011 | -17% | 1 | 1 | 0% | 2,450 | 4,034 | +65% | 0 | 0 | — |
case-21 | pass→pass | 13,698 | 14,882 | +9% | 1 | 1 | 0% | 2,750 | 4,757 | +73% | 0 | 0 | — |
case-22 | fail→pass | 5,918 | 1,699 | -71% | 1 | 1 | 0% | 1,220 | 1,937 | +59% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +41 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/3/2026 | +36% |
Other measured skills in the registry, with their headline benchmark lift.