--- name: data-visualizer description: Expert in creating charts, dashboards, and data visualizations using modern libraries version: 1.0.0 tags: [data-viz, charts, dashboards, d3, recharts, analytics] --- # 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:** ```typescript 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:** ```typescript 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:** ```typescript 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 ```typescript // 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 (

{title}

{value}

{trendIcon} {Math.abs(change)}%
) } export default function Dashboard() { return (
) } ``` --- ### Pattern 2: Real-Time Dashboard **Use case:** Live data monitoring ```typescript // 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:** ```typescript // 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 ```typescript // 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('30d') const [region, setRegion] = useState('all') const { data, loading } = useSalesData({ period, region }) return (
{/* Filters */}
{/* Chart */} {loading ? (
Loading...
) : ( )}
) } // 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 ```typescript ``` **Use when:** - Stock prices, temperature, website traffic - Showing change over time - Multiple data series comparison --- ### Bar Chart **Best for:** Comparing categories ```typescript ``` **Use when:** - Sales by product, users by country - Discrete categories - Ranking/comparison --- ### Pie/Donut Chart **Best for:** Part-to-whole relationships ```typescript ``` **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 ```typescript ``` **Use when:** - Cumulative totals - Filled regions show magnitude - Stacked categories --- ### Scatter Plot **Best for:** Correlation between variables ```typescript ``` **Use when:** - Finding correlations - Outlier detection - Distribution analysis --- ### Heatmap **Best for:** Intensity across two dimensions ```typescript // 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 ```typescript '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 ```typescript // 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:** ```typescript // For up to 5 data series const colorblindSafe = [ '#000000', // Black '#E69F00', // Orange '#56B4E9', // Sky Blue '#009E73', // Green '#F0E442' // Yellow ] ``` --- ## Data Formatting ### Number Formatting ```typescript // 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 ```typescript 'use client' import html2canvas from 'html2canvas' export function ExportableChart({ children }) { const chartRef = useRef(null) 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 (
{children}
) } ``` ### Export Data as CSV ```typescript 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 ```typescript // 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 ```typescript import { useVirtualizer } from '@tanstack/react-virtual' export function LargeDataTable({ data }: { data: any[] }) { const parentRef = useRef(null) const virtualizer = useVirtualizer({ count: data.length, getScrollElement: () => parentRef.current, estimateSize: () => 50, }) return (
{virtualizer.getVirtualItems().map((virtualRow) => (
{data[virtualRow.index].name}: {data[virtualRow.index].value}
))}
) } ``` --- ## Animation Best Practices ### Smooth Transitions ```typescript ``` ### Disable Animation for Real-Time ```typescript // For real-time dashboards, disable animation ``` --- ## Common Patterns ### Pattern: Drill-Down Chart ```typescript '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(null) 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 (
{level !== 'year' && ( )}
) } ``` --- ## 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!