用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/nomos-guild/cgov --skill add-chart命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Create a new customizable dashboard with its own chart registry, provider, and page. Use when adding dashboards like DRep or SPO dashboard.
Context window conservation rules. Invoke when approaching context limits or before large tasks.
Deep reflection on the skill learning system itself. Analyzes what's working, what's stale, and proposes structural improvements. The meta-skill.
正在显示 SKILL.md
基于 SOC 职业分类
| name | add-chart |
| description | Scaffold a new dashboard chart component with registry, types, and proper theme integration. |
Create a new chart for a dashboard with proper theme integration for all 3 themes (light, dark, game).
For theming rules, Recharts gotchas, and i18n conventions, see _patterns.md.
$0 - Chart name in PascalCase (e.g., VoterTurnout)$1 - Chart type: bar, pie, line, area (default: bar)Create file at src/components/dashboards/{dashboard}/charts/${$0}Chart.tsx:
import { useMemo } from "react";
import { useAppSelector } from "@/store/hooks";
import { useTheme } from "@/lib/theme";
import { cn } from "@/lib/utils";
import { ChartSkeleton } from "@/components/dashboards/shared/ChartSkeleton";
import type { ChartProps } from "@/types/dashboard";
import {
getChartColors,
ChartTooltip,
chartCardClassName,
chartCardGameClassName,
} from "@/components/dashboards/shared/chartTheme";
// Import Recharts components based on chart type
// Bar: BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer
// Pie: PieChart, Pie, Cell, Tooltip, ResponsiveContainer
// Line: LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer
export function ${$0}Chart({ isLoading, className }: ChartProps) {
const { actions } = useAppSelector((state) => state.governance);
const { activeTheme } = useTheme();
const chartColors = getChartColors(activeTheme.id);
const isGame = activeTheme.id === "game";
const data = useMemo(() => {
// TODO: Transform data for this chart
return [];
}, [actions]);
if (isLoading) return <ChartSkeleton className={className} />;
return (
<div className={cn(chartCardClassName, isGame && chartCardGameClassName, className)}>
<h3
className="text-sm font-semibold mb-4 dark:text-[#0bd1a2]"
style={isGame ? { color: chartColors.tooltipText } : undefined}
>
Chart Title
</h3>
<div className="flex-1 min-h-0">
<ResponsiveContainer width="100%" height="100%">
{/* Chart implementation */}
</ResponsiveContainer>
</div>
</div>
);
}
<XAxis
dataKey="name"
tick={{ fontSize: 11, fill: chartColors.axisText }}
axisLine={{ stroke: chartColors.axisLine }}
tickLine={false}
/>
contentStyle)<Tooltip content={<ChartTooltip themeId={activeTheme.id} />} />
// With formatters:
<Tooltip content={<ChartTooltip themeId={activeTheme.id} valueFormatter={(v) => `${v} proposals`} />} />
<Bar dataKey="value" fill={chartColors.primary} radius={0} />
<Pie data={data} dataKey="count" innerRadius="30%" outerRadius="55%" paddingAngle={2}
animationDuration={500} animationEasing="ease-in-out">
{data.map((entry, i) => (
<Cell key={i} fill={entry.fill} stroke={chartColors.tooltipBg} strokeWidth={2} />
))}
</Pie>
Pie overflow clipping: See _patterns.md Recharts section for the 3-layer fix.
<Line type="monotone" dataKey="value" stroke={chartColors.primary} strokeWidth={2}
dot={false} activeDot={{ r: 5, cursor: "pointer" }} />
{data.length === 0 ? (
<p className="text-sm text-muted-foreground">No data available</p>
) : (
<div className="flex-1 min-h-0"><ResponsiveContainer>...</ResponsiveContainer></div>
)}
chartColors)// Status: .active, .ratified, .enacted, .expired
// Votes: .yes, .no, .abstain
// Participation: .participationLow/MedLow/MedHigh/High
// Categorical: .palette[0..6] (7 colors per theme)
// Chrome: .axisLine, .axisText, .gridLine, .tooltipBg, .tooltipBorder, .tooltipText
// Accent: .primary, .primaryMuted
Edit src/components/dashboards/{dashboard}/charts/index.tsx:
// Add dynamic import
const ${$0}Chart = dynamic(
() => import("./${$0}Chart").then((mod) => mod.${$0}Chart),
{ loading: () => <ChartSkeleton />, ssr: false }
);
// Add to CHART_REGISTRY array
{
id: "${kebab-case}",
title: "${Human Title}",
description: "${Description}",
component: ${$0}Chart,
defaultVisible: true,
defaultLayout: DEFAULT_CHART_LAYOUTS["${kebab-case}"],
icon: BarChart3, // Options: BarChart3, PieChart, TrendingUp, Users, Vote, Gauge
},
// Add to exports
export { ${$0}Chart };
"${kebab-case}" to the relevant ChartId union typeALL_CHART_IDS arrayDEFAULT_CHART_LAYOUTS:"${kebab-case}": { x: 0, y: 1000, width: 380, height: 320 },
// All values must be multiples of 20. Sizes: Small 380x320, Medium 580x320, Large 780x320
Allow users to click chart elements to customize colors via side panel:
import { useChartColors } from "@/components/dashboards/shared/ChartColorsContext";
import { useDashboard } from "@/components/dashboards/shared/DashboardProvider";
const CHART_ID = "my-chart";
const { getColor } = useChartColors();
const { setColorPickerTarget } = useDashboard();
// Get color with fallback
const barColor = getColor(CHART_ID, "Active", chartColors.active);
// Click handler
const handleClick = (key: string, label: string) =>
setColorPickerTarget({ chartId: CHART_ID, chartTitle: "My Chart", elementKey: key, elementLabel: label });
// On elements
<Cell fill={getColor(CHART_ID, entry.key, entry.defaultFill)} onClick={() => handleClick(entry.key, entry.key)} style={{ cursor: "pointer" }} />
import { useTranslations } from "next-intl";
const t = useTranslations("charts");
<h3>{t("myChart.title")}</h3>
Add entries to all 7 locale files under src/messages/{locale}.json → "charts" namespace.
For charts fetching their own data (e.g., DRep charts), use SWR hooks from src/hooks/useDRepData.ts:
const { dreps, isLoading: drepsLoading } = useDRepList({ pageSize: 50 });
When data requires N+1 calls, create a server-side API route instead (see add-api-route skill).
useTheme() and getChartColors()chartCardClassName / chartCardGameClassNameChartTooltip (not contentStyle)chartColors, not hardcoded<ChartSkeleton />npm run build passes_patterns.md)