Data Visualizer Skill
I help you build beautiful, interactive data visualizations and dashboards.
What I Do
Chart Creation:
Line charts, bar charts, pie charts Area charts, scatter plots, heatmaps Complex visualizations (Sankey, treemaps, network graphs)
Dashboard Building:
KPI cards and metrics Real-time data dashboards Interactive filters and drill-downs Responsive layouts
Data Presentation:
Data storytelling Color schemes and accessibility Animation and interactions Export capabilities Library Selection Guide Recharts (Recommended for React)
Best for:
Quick, simple charts React/Next.js projects Standard chart types Responsive design
Example:
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from 'recharts'
const data = [ { month: 'Jan', revenue: 4000, expenses: 2400 }, { month: 'Feb', revenue: 3000, expenses: 1398 }, { month: 'Mar', revenue: 2000, expenses: 9800 }, ]
function RevenueChart() {
return (
Chart.js (Recommended for Vue/Angular)
Best for:
Framework-agnostic Simple API Good documentation Standard chart types
Example:
import { Chart } from 'chart.js/auto'
const ctx = document.getElementById('myChart') const chart = new Chart(ctx, { type: 'bar', data: { labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'], datasets: [ { label: 'Sales', data: [12, 19, 3, 5, 2, 3], backgroundColor: 'rgba(54, 162, 235, 0.5)' } ] }, options: { responsive: true, plugins: { legend: { position: 'top' }, title: { display: true, text: 'Monthly Sales' } } } })
D3.js (Advanced)
Best for:
Custom visualizations Complex interactions Full control over rendering Data-driven documents
When to use:
Need custom chart type Complex data transformations Advanced interactions Publication-quality graphics
Example:
import * as d3 from 'd3'
function createBarChart(data: Array<{ name: string; value: number }>) { const width = 600 const height = 400 const margin = { top: 20, right: 20, bottom: 30, left: 40 }
const svg = d3.select('#chart').append('svg').attr('width', width).attr('height', height)
const x = d3 .scaleBand() .domain(data.map(d => d.name)) .range([margin.left, width - margin.right]) .padding(0.1)
const y = d3 .scaleLinear() .domain([0, d3.max(data, d => d.value)]) .range([height - margin.bottom, margin.top])
svg .selectAll('rect') .data(data) .join('rect') .attr('x', d => x(d.name)) .attr('y', d => y(d.value)) .attr('height', d => y(0) - y(d.value)) .attr('width', x.bandwidth()) .attr('fill', 'steelblue')
// Add axes
svg
.append('g')
.attr('transform', translate(0,${height - margin.bottom}))
.call(d3.axisBottom(x))
svg.append('g').attr('transform', translate(${margin.left},0)).call(d3.axisLeft(y))
}
Dashboard Patterns Pattern 1: KPI Dashboard
Use case: Executive dashboard with key metrics
// components/KPIDashboard.tsx import { Card } from '@/components/ui/card'
interface KPICardProps { title: string value: string | number change: number trend: 'up' | 'down' }
function KPICard({ title, value, change, trend }: KPICardProps) { const trendColor = trend === 'up' ? 'text-green-600' : 'text-red-600' const trendIcon = trend === 'up' ? '↑' : '↓'
return (
{value}{title}
export default function Dashboard() { return (
Pattern 2: Real-Time Dashboard
Use case: Live data monitoring
// components/RealtimeDashboard.tsx 'use client'
import { useEffect, useState } from 'react' import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts'
interface DataPoint { time: string value: number }
export default function RealtimeDashboard() {
const [data, setData] = useState
useEffect(() => { // Fetch initial data fetch('/api/metrics/realtime') .then(res => res.json()) .then(setData)
// Subscribe to real-time updates
const eventSource = new EventSource('/api/metrics/stream')
eventSource.onmessage = (event) => {
const newDataPoint = JSON.parse(event.data)
setData(prev => {
const updated = [...prev, newDataPoint]
// Keep last 20 data points
return updated.slice(-20)
})
}
return () => eventSource.close()
}, [])
return (
Live Traffic
API Route for SSE:
// app/api/metrics/stream/route.ts export async function GET(req: Request) { const encoder = new TextEncoder()
const stream = new ReadableStream({ async start(controller) { const interval = setInterval(async () => { const value = Math.floor(Math.random() * 100) const time = new Date().toLocaleTimeString()
const data = `data: ${JSON.stringify({ time, value })}\n\n`
controller.enqueue(encoder.encode(data))
}, 1000)
// Cleanup on close
req.signal.addEventListener('abort', () => {
clearInterval(interval)
controller.close()
})
}
})
return new Response(stream, { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' } }) }
Pattern 3: Interactive Dashboard with Filters // components/SalesDashboard.tsx 'use client'
import { useState } from 'react' import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts'
type Period = '7d' | '30d' | '90d' type Region = 'all' | 'us' | 'eu' | 'asia'
export default function SalesDashboard() {
const [period, setPeriod] = useState
const { data, loading } = useSalesData({ period, region })
return (
<select
value={region}
onChange={(e) => setRegion(e.target.value as Region)}
className="px-4 py-2 border rounded"
>
<option value="all">All Regions</option>
<option value="us">United States</option>
<option value="eu">Europe</option>
<option value="asia">Asia</option>
</select>
</div>
{/* Chart */}
{loading ? (
<div>Loading...</div>
) : (
<ResponsiveContainer width="100%" height={400}>
<BarChart data={data}>
<XAxis dataKey="date" />
<YAxis />
<Tooltip />
<Bar dataKey="sales" fill="#8884d8" />
</BarChart>
</ResponsiveContainer>
)}
</div>
) }
// Custom hook for data fetching function useSalesData({ period, region }: { period: Period, region: Region }) { const [data, setData] = useState([]) const [loading, setLoading] = useState(true)
useEffect(() => {
setLoading(true)
fetch(/api/sales?period=${period}®ion=${region})
.then(res => res.json())
.then(data => {
setData(data)
setLoading(false)
})
}, [period, region])
return { data, loading } }
Chart Types Guide Line Chart
Best for: Trends over time, continuous data
Use when:
Stock prices, temperature, website traffic Showing change over time Multiple data series comparison Bar Chart
Best for: Comparing categories
Use when:
Sales by product, users by country Discrete categories Ranking/comparison Pie/Donut Chart
Best for: Part-to-whole relationships
Use when:
Market share, budget allocation Proportions (max 5-7 slices) Simple percentages
⚠️ Avoid when:
Too many categories (> 7) Precise comparison needed (use bar chart) Area Chart
Best for: Volume over time
Use when:
Cumulative totals Filled regions show magnitude Stacked categories Scatter Plot
Best for: Correlation between variables
Use when:
Finding correlations Outlier detection Distribution analysis Heatmap
Best for: Intensity across two dimensions
// Using D3 const colorScale = d3.scaleSequential(d3.interpolateBlues).domain([0, d3.max(data)])
svg .selectAll('rect') .data(data) .join('rect') .attr('fill', d => colorScale(d.value))
Use when:
Time-based patterns (day/hour) Geographic intensity Matrix data Responsive Design Pattern: Mobile-Friendly Charts 'use client'
import { useEffect, useState } from 'react' import { LineChart, Line, ResponsiveContainer } from 'recharts'
export default function ResponsiveChart({ data }) { const [isMobile, setIsMobile] = useState(false)
useEffect(() => { const checkMobile = () => setIsMobile(window.innerWidth < 768) checkMobile() window.addEventListener('resize', checkMobile) return () => window.removeEventListener('resize', checkMobile) }, [])
return (
Color Schemes Accessible Colors // colors.ts export const chartColors = { // WCAG AA compliant primary: '#0066CC', // Blue success: '#007A3D', // Green warning: '#C87000', // Orange danger: '#D32F2F', // Red
// Multi-series (colorblind-safe) series: [ '#0066CC', // Blue '#CC6600', // Orange '#7A00CC', // Purple '#00CC66', // Green '#CC0066' // Magenta ] }
Colorblind-Safe Palettes:
// For up to 5 data series const colorblindSafe = [ '#000000', // Black '#E69F00', // Orange '#56B4E9', // Sky Blue '#009E73', // Green '#F0E442' // Yellow ]
Data Formatting Number Formatting // utils/formatters.ts
export function formatCurrency(value: number): string { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 0, maximumFractionDigits: 0, }).format(value) }
export function formatPercent(value: number): string { return new Intl.NumberFormat('en-US', { style: 'percent', minimumFractionDigits: 1, maximumFractionDigits: 1, }).format(value / 100) }
export function formatNumber(value: number): string {
if (value >= 1000000) {
return ${(value / 1000000).toFixed(1)}M
}
if (value >= 1000) {
return ${(value / 1000).toFixed(1)}K
}
return value.toFixed(0)
}
// Usage in chart
Export Functionality Export Chart as PNG 'use client'
import html2canvas from 'html2canvas'
export function ExportableChart({ children }) {
const chartRef = useRef
const exportToPNG = async () => { if (!chartRef.current) return
const canvas = await html2canvas(chartRef.current)
const link = document.createElement('a')
link.download = 'chart.png'
link.href = canvas.toDataURL()
link.click()
}
return (
Export Data as CSV export function exportToCSV(data: any[], filename: string) { const headers = Object.keys(data[0]) const csv = [ headers.join(','), ...data.map(row => headers.map(h => row[h]).join(',')) ].join('\n')
const blob = new Blob([csv], { type: 'text/csv' })
const link = document.createElement('a')
link.download = ${filename}.csv
link.href = URL.createObjectURL(blob)
link.click()
}
// Usage
Performance Optimization Lazy Loading Charts // Lazy load chart libraries (reduce initial bundle) import dynamic from 'next/dynamic'
const LineChart = dynamic( () => import('recharts').then(mod => mod.LineChart), { ssr: false } )
export default function ChartPage() {
return
Virtualization for Large Datasets import { useVirtualizer } from '@tanstack/react-virtual'
export function LargeDataTable({ data }: { data: any[] }) {
const parentRef = useRef
const virtualizer = useVirtualizer({ count: data.length, getScrollElement: () => parentRef.current, estimateSize: () => 50, })
return (
Animation Best Practices
Smooth Transitions
Disable Animation for Real-Time
// For real-time dashboards, disable animation
Common Patterns Pattern: Drill-Down Chart 'use client'
import { useState } from 'react' import { BarChart, Bar, XAxis, YAxis } from 'recharts'
export default function DrillDownChart() {
const [level, setLevel] = useState<'year' | 'month' | 'day'>('year')
const [selectedYear, setSelectedYear] = useState
const handleBarClick = (data: any) => { if (level === 'year') { setSelectedYear(data.year) setLevel('month') } else if (level === 'month') { setLevel('day') } }
const goBack = () => { if (level === 'day') setLevel('month') else if (level === 'month') { setLevel('year') setSelectedYear(null) } }
return (
<BarChart data={getData(level, selectedYear)} width={600} height={300}>
<Bar dataKey="value" fill="#8884d8" onClick={handleBarClick} />
<XAxis dataKey="name" />
<YAxis />
</BarChart>
</div>
) }
When to Use Me
Perfect for:
Building analytics dashboards Creating interactive charts Data storytelling Real-time monitoring Visualizing complex datasets
I'll help you:
Choose the right chart type Implement responsive layouts Add interactivity Optimize performance Ensure accessibility What I'll Create 📊 Charts and Visualizations 📈 KPI Dashboards 🎨 Custom Color Schemes 📱 Responsive Layouts ⚡ Real-Time Updates 💾 Export Functionality
Let's make your data beautiful and understandable!
← 返回排行榜