---
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 */}
setPeriod(e.target.value as Period)}
className="px-4 py-2 border rounded"
>
Last 7 days
Last 30 days
Last 90 days
setRegion(e.target.value as Region)}
className="px-4 py-2 border rounded"
>
All Regions
United States
Europe
Asia
{/* 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 (
)
}
```
### 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
exportToCSV(data, 'sales-data')}>
Export to CSV
```
---
## 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' && (
← Back
)}
)
}
```
---
## 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!