chart
Skill0 starsChanged 44 days agoApache-2.0View on GitHub
Data visualization with Chart.js via the pre-built, protected `ChartWrapper`: line, bar and doughnut charts with loading/empty/error states and CSS-variable colours via `cssVar()`. Use when an analytics, dashboard or reporting page needs visual encoding beyond a table.
14 other projects use a version of this.
Adopted by
Most recently taken up by
- Tashila-109/tstack-skillstheir own version, first seen Nov 8, 2026
- remigius-labs/terminal-chartstheir own version, first seen Oct 20, 2026
- ivoryRabbit/analytics-copilottheir own version, first seen Oct 13, 2026
- Zafer-Liu/Data-Analysis-Agenttheir own version, first seen Oct 8, 2026
- metadist/synaplan-desktoptheir own version, first seen Sep 26, 2026
- yuanhaorannnnnn/agent-skillstheir own version, first seen Sep 18, 2026
Other versions14 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 14
- Zafer-Liu/Data-Analysis-Agent★ 2.6ksame name
- kansoku-trade/kansoku★ 322same name
- metadist/synaplan-desktop★ 257same name
- chenjackle45/html-visualizer★ 95same name
- rainday/smart-blog-skills★ 35same name
- Starchild-ai-agent/official-skills★ 32same name
- tvremix/claude-plugin★ 14same name
- npow/claude-skills★ 4same name
- Tashila-109/tstack-skills★ 1same name
- ivoryRabbit/analytics-copilot★ 0same name
4 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository15 other files it gives its agents.
- authSkill
- cart-checkoutSkill
- commerce-adminSkill
- commerce-coreSkill
- dashboard-motionSkill
- drawerSkill
- formSkill
- kanbanSkill
- mediaSkill
- metric-cardSkill
- modalSkill
- product-catalogSkill
- product-detailSkill
- sidenavSkill
- tableSkill
The file
We split this skill into the rules it gives an agent
2 rules. 0 are common, 2 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 9 edited versions we read keep these.
2
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 140
When two series differ in magnitude by more than ~10×, they MUST NOT share one axis — the smaller series flattens to zero and becomes …
- Distinctive: line 144
Never ship a legend entry for a series the user cannot see.
“Common” is measured: kept by at least 6 in 10 of the 9 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Chart Skill
When to use
Pages that display data trends, comparisons, or KPIs — analytics dashboards, reporting pages, metric overviews, financial summaries. Use when data needs visual encoding beyond a table.
Use the pre-built components — do NOT reconstruct them
ChartWrapper.vue and MetricCard.vue already exist in the scaffold at
app/components/shared/, fully implemented, tested, and theme-reactive. Never
recreate these files or write your own chart shell/metric card component — the
build system will reject any attempt to overwrite them (they're protected). You
almost never touch Chart.js directly. Just render the components and pass data:
<script setup lang="ts">
import type { ChartData } from 'chart.js'
import ChartWrapper from '~/components/shared/ChartWrapper.vue'
import MetricCard from '~/components/shared/MetricCard.vue'
import { DollarSign, Users } from 'lucide-vue-next'
import { cssVar, cssVarAlpha } from '~/utils/chartColors'
const revenueData: ChartData = {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
datasets: [{
label: 'Revenue',
data: [12000, 19000, 15000, 22000, 18000, 28000],
borderColor: cssVar('--primary'),
backgroundColor: cssVarAlpha('--primary', 0.15),
fill: true,
tension: 0.4,
pointRadius: 0,
pointHoverRadius: 5,
}],
}
</script>
<template>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<MetricCard label="Total Revenue" value="$42,800" variant="icon" :icon="DollarSign" icon-color="primary" :trend="{ value: 12.3, label: 'vs last month' }" />
<MetricCard label="Active Users" value="1,284" variant="icon" :icon="Users" icon-color="secondary" :trend="{ value: 8.1, label: 'vs last week' }" />
</div>
<!-- The wrapping card div controls height (e.g. h-72) — ChartWrapper fills it. -->
<div class="rounded-xl border border-border bg-card p-4 h-72">
<ChartWrapper type="line" :data="revenueData" title="Revenue Trend" />
</div>
</template>ChartWrapper.vue props
| Prop | Type | Notes |
type | 'line' | 'bar' | 'doughnut' | required |
data | ChartData (from chart.js) | required — build with cssVar() for colors, see below |
options | ChartOptions | optional — merged over sensible defaults |
title | string | optional heading above the chart |
loading / error | boolean / string | null | drive the 4 built-in states |
Height rule: the wrapping card <div> controls the chart's height (e.g. h-72). ChartWrapper fills it internally. Never put h-* on ChartWrapper itself, and never wrap it in anything that removes its h-full sizing chain — that's exactly what makes a doughnut/pie chart overflow its container, which is why this component is now pre-built and protected rather than something each project reimplements slightly differently.
MetricCard.vue props
| Prop | Type | Notes |
label | string | required |
value | string | number | required — pass it formatted exactly as you want it to read ("$48,250", "18.4%", "24"). The component parses out the numeric part and counts up to it on mount automatically — you don't need a separate count-up prop or composable call. |
variant | 'default' | 'icon' | 'sparkline' | 'progress' | 'hero' | default 'default'. Use hero for the one KPI that should read as more important than the rest of the grid (larger type, tinted surface) — pair it with a class="md:col-span-2" on the instance to actually span extra grid columns. |
icon / iconColor | Component / 'primary' | 'secondary' | 'accent' | 'success' | 'destructive' | icon variant only. Alternate iconColor across cards in a grid — never all primary. |
trend | { value: number; label?: string } | shown on default/icon/sparkline/hero |
sparkData | number[] | sparkline variant — 7–14 points with realistic variation, never [1,2,3,4,5] |
progress | { current: number; max: number; label?: string } | progress variant |
loading | boolean | shows a skeleton in place of content |
CSS variable color strategy for chart data (non-negotiable)
Chart.js colors passed into ChartWrapper's data prop MUST come from CSS variables extracted at runtime. Never use hardcoded hex, rgb, or hsl values.
import { cssVar, cssVarAlpha } from '~/utils/chartColors'Color mapping (raw tokens — no --color- prefix):
| Chart element | Token |
| Primary dataset | --primary |
| Secondary dataset | --secondary |
| Accent dataset | --accent |
Line/area fill: cssVarAlpha('--primary', 0.15) for backgroundColor on line charts with fill: true.
Bar fill: cssVar('--primary') for single-series; rotate ['--chart-1', '--chart-2', '--chart-3', '--chart-4', '--chart-5'] for multi-series.
Doughnut slices: [cssVar('--chart-1'), cssVar('--chart-2'), cssVar('--chart-3')].
ChartWrapper already handles grid/tick/legend/tooltip colors, dark-mode re-theming, and the loading/error/empty/data state machine internally — you only need to supply data in the shape above.
Page usage pattern
<template>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="rounded-xl border border-border bg-card p-4 h-72">
<ChartWrapper type="line" :data="revenueData" title="Revenue Trend" />
</div>
<div class="rounded-xl border border-border bg-card p-4 h-72">
<ChartWrapper type="doughnut" :data="pipelineData" title="Deal Stages" />
</div>
</div>
</template>Non-negotiables
- Never recreate
ChartWrapper.vueorMetricCard.vue— import and use them as-is. If a screen needs a chart/metric card they don't support, ask for a new variant rather than hand-rolling a parallel component. - All chart colors come from
cssVar()/cssVarAlpha()imported from~/utils/chartColors— never hardcoded hex/rgb/hsl, and NEVER append an alpha suffix to a color string (cssVar('--primary') + '20'). Tokens arehsl()functions, not hex — concatenation produces an invalid color and Chart.js silently renders it BLACK. UsecssVarAlpha(token, 0.15)instead. - The wrapping
<div>aroundChartWrappercontrols height (e.g.h-72) — never set a height onChartWrapperitself MetricCard'svalueis the already-formatted display string — do not also wire a separate count-up; it's built in- Alternate
iconColoracrossMetricCardinstances in a grid — never allprimary sparkDatamust be realistic (7–14 points with natural variation) — never[1, 2, 3, 4, 5]- Wrap a card grid or table body in
.stagger-children(seedashboard-motion/SKILL.md) for entrance motion — don't build a custom per-item animation - When two series differ in magnitude by more than ~10×, they MUST NOT share one axis —
the smaller series flattens to zero and becomes invisible. Either give the second series
its own axis with
yAxisID: 'y1'plus a matchingscales.y1entry (position: 'right',grid: { drawOnChartArea: false }), or split them into two charts. Never ship a legend entry for a series the user cannot see.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

