Skip to main content

build-dashboard

Build an interactive HTML dashboard with charts, filters, and tables. Use when creating an executive overview with KPI cards, turning query results into a shareable self-contained report, building a team monitoring snapshot, or needing multiple charts with filters in one browser-openable file.

来源信息

仓库
autonomous-ai/autonomous-intern
最近来源活动
2026年5月29日 11:00
检测到的 SKILL.md 语言
英语
星标
18
分支
1

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
build-dashboard
description
Build an interactive HTML dashboard with charts, filters, and tables. Use when creating an executive overview with KPI cards, turning query results into a shareable self-contained report, building a team monitoring snapshot, or needing multiple charts with filters in one browser-openable file.
argument-hint
<description> [data source]
# /build-dashboard - Build Interactive Dashboards Build a self-contained interactive HTML dashboard with charts, filters, tables, and professional styling. Opens directly in a browser -- no server or dependencies required. ## Usage ``` /build-dashboard <description of dashboard> [data source] ``` ## Workflow ### 1. Understand the Dashboard Requirements Determine: - **Purpose**: Executive overview, operational monitoring, deep-dive analysis, team reporting - **Audience**: Who will use this dashboard? - **Key metrics**: What numbers matter most? - **Dimensions**: What should users be able to filter or slice by? - **Data source**: Live query, pasted data, CSV file, or sample data ### 2. Gather the Data **If data warehouse is connected:** 1. Query the necessary data 2. Embed the results as JSON within the HTML file **If data is pasted or uploaded:** 1. Parse and clean the data 2. Embed as JSON in the dashboard **If working from a description without data:** 1. Create a realistic sample dataset matching the described schema 2. Note in the dashboard that it uses sample data 3. Provide instructions for swapping in real data ### 3. Design the Dashboard Layout Follow a standard dashboard layout pattern: ``` ┌──────────────────────────────────────────────────┐ │ Dashboard Title [Filters ▼] │ ├────────────┬────────────┬────────────┬───────────┤ │ KPI Card │ KPI Card │ KPI Card │ KPI Card │ ├────────────┴────────────┼────────────┴───────────┤ │ │ │ │ Primary Chart │ Secondary Chart │ │ (largest area) │ │ │ │ │ ├─────────────────────────┴────────────────────────┤ │ │ │ Detail Table (sortable, scrollable) │ │ │ └──────────────────────────────────────────────────┘ ``` **Adapt the layout to the content:** - 2-4 KPI cards at the top for headline numbers - 1-3 charts in the middle section for trends and breakdowns - Optional detail table at the bottom for drill-down data - Filters in the header or sidebar depending on complexity ### 4. Build the HTML Dashboard Generate a single self-contained HTML file using the base template below. The file includes: **Structure (HTML):** - Semantic HTML5 layout - Responsive grid using CSS Grid or Flexbox - Filter controls (dropdowns, date pickers, toggles) - KPI cards with values and labels - Chart containers - Data table with sortable headers **Styling (CSS):** - Professional color scheme (clean whites, grays, with accent colors for data) - Card-based layout with subtle shadows - Consistent typography (system fonts for fast loading) - Responsive design that works on different screen sizes - Print-friendly styles **Interactivity (JavaScript):** - Chart.js for interactive charts (included via CDN) - Filter dropdowns that update all charts and tables simultaneously - Sortable table columns - Hover tooltips on charts - Number formatting (commas, currency, percentages) **Data (embedded JSON):** - All data embedded directly in the HTML as JavaScript variables - No external data fetches required - Dashboard works completely offline ### 5. Implement Chart Types Use Chart.js for all charts. Common dashboard chart patterns: - **Line chart**: Time series trends - **Bar chart**: Category comparisons - **Doughnut chart**: Composition (when <6 categories) - **Stacked bar**: Composition over time - **Mixed (bar + line)**: Volume with rate overlay Use the Chart.js integration patterns below for each chart type. ### 6. Add Interactivity Use the filter and interactivity implementation patterns below for dropdown filters, date range filters, combined filter logic, sortable tables, and chart updates. ### 7. Save and Open 1. Save the dashboard as an HTML file with a descriptive name (e.g., `sales_dashboard.html`) 2. Open it in the user's default browser 3. Confirm it renders correctly 4. Provide instructions for updating data or customizing --- ## Base Template Every dashboard follows this structure: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Dashboard Title</title> <script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1" integrity="sha384-jb8JQMbMoBUzgWatfe6COACi2ljcDdZQ2OxczGA3bGNeWe+6DChMTBJemed7ZnvJ" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3.0.0" integrity="sha384-cVMg8E3QFwTvGCDuK+ET4PD341jF3W8nO1auiXfuZNQkzbUUiBGLsIQUE+b1mxws" crossorigin="anonymous"></script> <style> /* Dashboard styles go here */ </style> </head> <body> <div class="dashboard-container"> <header class="dashboard-header"> <h1>Dashboard Title</h1> <div class="filters"> <!-- Filter controls --> </div> </header> <section class="kpi-row"> <!-- KPI cards --> </section> <section class="chart-row"> <!-- Chart containers --> </section> <section class="table-section"> <!-- Data table --> </section> <footer class="dashboard-footer"> <span>Data as of: <span id="data-date"></span></span> </footer> </div> <script> // Embedded data const DATA = []; // Dashboard logic class Dashboard { constructor(data) { this.rawData = data; this.filteredData = data; this.charts = {}; this.init(); } init() { this.setupFilters(); this.renderKPIs(); this.renderCharts(); this.renderTable(); } applyFilters() { // Filter logic this.filteredData = this.rawData.filter(row => { // Apply each active filter return true; // placeholder }); this.renderKPIs(); this.updateCharts(); this.renderTable(); } // ... methods for each section } const dashboard = new Dashboard(DATA); </script> </body> </html> ``` ## KPI Card Pattern ```html <div class="kpi-card"> <div class="kpi-label">Total Revenue</div> <div class="kpi-value" id="kpi-revenue">$0</div> <div class="kpi-change positive" id="kpi-revenue-change">+0%</div> </div> ``` ```javascript function renderKPI(elementId, value, previousValue, format = 'number') { const el = document.getElementById(elementId); const changeEl = document.getElementById(elementId + '-change'); // Format the value el.textContent = formatValue(value, format); // Calculate and display change if (previousValue && previousValue !== 0) { const pctChange = ((value - previousValue) / previousValue) * 100; const sign = pctChange >= 0 ? '+' : ''; changeEl.textContent = `${sign}${pctChange.toFixed(1)}% vs prior period`; changeEl.className = `kpi-change ${pctChange >= 0 ? 'positive' : 'negative'}`; } } function formatValue(value, format) { switch (format) { case 'currency': if (value >= 1e6) return `$${(value / 1e6).toFixed(1)}M`; if (value >= 1e3) return `$${(value / 1e3).toFixed(1)}K`; return `$${value.toFixed(0)}`; case 'percent': return `${value.toFixed(1)}%`; case 'number': if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`; if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`; return value.toLocaleString(); default: return value.toString(); } } ``` ## Chart.js Integration ### Chart Container Pattern ```html <div class="chart-container"> <h3 class="chart-title">Monthly Revenue Trend</h3> <canvas id="revenue-chart"></canvas> </div> ``` ### Line Chart ```javascript function createLineChart(canvasId, labels, datasets) { const ctx = document.getElementById(canvasId).getContext('2d'); return new Chart(ctx, { type: 'line', data: { labels: labels, datasets: datasets.map((ds, i) => ({ label: ds.label, data: ds.data, borderColor: COLORS[i % COLORS.length], backgroundColor: COLORS[i % COLORS.length] + '20', borderWidth: 2, fill: ds.fill || false, tension: 0.3, pointRadius: 3, pointHoverRadius: 6, })) }, options: { responsive: true, maintainAspectRatio: false, interaction: { mode: 'index', intersect: false, }, plugins: { legend: { position: 'top', labels: { usePointStyle: true, padding: 20 } }, tooltip: { callbacks: { label: function(context) { return `${context.dataset.label}: ${formatValue(context.parsed.y, 'currency')}`; } } } }, scales: { x: { grid: { display: false } }, y: { beginAtZero: true, ticks: { callback: function(value) { return formatValue(value, 'currency'); } } } } } }); } ``` ### Bar Chart ```javascript function createBarChart(canvasId, labels, data, options = {}) { const ctx = document.getElementById(canvasId).getContext('2d'); const isHorizontal = options.horizontal || labels.length > 8; return new Chart(ctx, { type: 'bar', data: { labels: labels, datasets: [{ label: options.label || 'Value', data: data, backgroundColor: options.colors || COLORS.map(c => c + 'CC'), borderColor: options.colors || COLORS, borderWidth: 1, borderRadius: 4, }] }, options: { responsive: true, maintainAspectRatio: false, indexAxis: isHorizontal ? 'y' : 'x', plugins: { legend: { display: false }, tooltip: { callbacks: { label: function(context) { return formatValue(context.parsed[isHorizontal ? 'x' : 'y'], options.format || 'number'); } } } }, scales: { x: { beginAtZero: true, grid: { display: isHorizontal }, ticks: isHorizontal ? { callback: function(value) { return formatValue(value, options.format || 'number'); } } : {} }, y: { beginAtZero: !isHorizontal, grid: { display: !isHorizontal }, ticks: !isHorizontal ? { callback: function(value) { return formatValue(value, options.format || 'number'); } } : {} } } } }); } ``` ### Doughnut Chart ```javascript function createDoughnutChart(canvasId, labels, data) { const ctx = document.getElementById(canvasId).getContext('2d'); return new Chart(ctx, { type: 'doughnut', data: { labels: labels, datasets: [{ data: data, backgroundColor: COLORS.map(c => c + 'CC'), borderColor: '#ffffff', borderWidth: 2, }] }, options: { responsive: true, maintainAspectRatio: false, cutout: '60%', plugins: { legend: { position: 'right', labels: { usePointStyle: true, padding: 15 } }, tooltip: { callbacks: { label: function(context) { const total = context.dataset.data.reduce((a, b) => a + b, 0); const pct = ((context.parsed / total) * 100).toFixed(1); return `${context.label}: ${formatValue(context.parsed, 'number')} (${pct}%)`; } } } } } }); } ``` ### Updating Charts on Filter Change ```javascript function updateChart(chart, newLabels, newData) { chart.data.labels = newLabels; if (Array.isArray(newData[0])) { // Multiple datasets newData.forEach((data, i) => { chart.data.datasets[i].data = data; }); } else { chart.data.datasets[0].data = newData; } chart.update('none'); // 'none' disables animation for instant update } ``` ## Filter and Interactivity Implementation ### Dropdown Filter ```html <div class="filter-group"> <label for="filter-region">Region</label>
在 GitHub 查看
这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看