React Bubble Chart
A powerful, customizable bubble chart component for React applications with TypeScript support. Perfect for visualizing three-dimensional data relationships with interactive features, smooth animations, and extensive customization options.
Installation
npm install @aniruddha1806/bubble-chart
Features
- 🫧 Interactive bubble charts with three-dimensional data visualization
- 🎭 Smooth entrance animations with scroll-triggered effects
- 🖱️ Hover tooltips and click handlers
- 📊 Customizable axes with configurable ticks and labels
- 🎨 Extensive styling options (colors, sizing, formatting)
- 📱 Responsive SVG-based rendering
- 📏 Flexible bubble sizing (relative or absolute)
- 🔄 Real-time data updates with smooth transitions
- 📝 TypeScript support with full type definitions
- ♿ Accessibility-friendly structure
- 🪶 Zero dependencies for chart rendering
Quick Start
Basic Bubble Chart
import { BubbleChart } from '@aniruddha1806/bubble-chart';
function App() {
const data = [
{ x: 10, y: 20, size: 15, label: 'Product A', color: '#3b82f6' },
{ x: 25, y: 35, size: 25, label: 'Product B', color: '#10b981' },
{ x: 40, y: 15, size: 20, label: 'Product C', color: '#f59e0b' },
{ x: 30, y: 45, size: 30, label: 'Product D', color: '#ef4444' },
{ x: 50, y: 30, size: 18, label: 'Product E', color: '#8b5cf6' }
];
return (
<BubbleChart
data={data}
width="100%"
height={400}
xAxisLabel="Revenue (millions)"
yAxisLabel="Growth Rate (%)"
showTooltip={true}
animated={true}
/>
);
}
Advanced Configuration
import { BubbleChart } from '@aniruddha1806/bubble-chart';
function AdvancedExample() {
const data = [
];
return (
<BubbleChart
data={data}
width={800}
height={500}
xAxisLabel="Market Share (%)"
yAxisLabel="Customer Satisfaction"
minRadius={8}
maxRadius={60}
xAxisTicks={8}
yAxisTicks={6}
bubbleSizeMultiplier={1.2}
animated={true}
animationDuration={1000}
formatValue={(value) => `$${value}M`}
onBubbleClick={(bubble) => console.log('Clicked:', bubble)}
/>
);
}
Props
Core Props
data | BubbleDataPoint[] | required | Array of bubble data points |
width | number | string | "100%" | Chart width |
height | number | string | 400 | Chart height |
Styling Props
colors | string[] | default palette | Color palette for bubbles |
backgroundColor | string | "transparent" | Chart background color |
className | string | "" | CSS class for container |
bubbleClassName | string | "" | CSS class for bubbles |
tooltipClassName | string | "" | CSS class for tooltips |
Axis Props
xAxisLabel | string | "X-Axis" | X-axis label text |
yAxisLabel | string | "Y-Axis" | Y-axis label text |
xAxisTicks | number | 5 | Number of X-axis tick marks |
yAxisTicks | number | 5 | Number of Y-axis tick marks |
Bubble Sizing Props
minRadius | number | 10 | Minimum bubble radius |
maxRadius | number | 50 | Maximum bubble radius |
bubbleSizeMultiplier | number | 1 | Size scaling multiplier |
absoluteBubbleSize | boolean | false | Use absolute sizing instead of relative |
Formatting Props
formatValue | (value: number) => string | toString | General value formatter |
formatXAxisValue | (value: number) => string | formatValue | X-axis value formatter |
formatYAxisValue | (value: number) => string | formatValue | Y-axis value formatter |
Interaction Props
showTooltip | boolean | true | Show hover tooltips |
onBubbleClick | (dataPoint: BubbleDataPoint) => void | undefined | Bubble click handler |
tooltipContent | (bubble: BubbleDataPoint) => React.ReactNode | undefined | Custom tooltip content |
Animation Props
animated | boolean | true | Enable entrance animations |
animationDuration | number | 800 | Animation duration (ms) |
Data Types
type BubbleDataPoint = {
x: number;
y: number;
size: number;
label?: string;
color?: string;
[key: string]: any;
};
Examples
Sales Performance Dashboard
Visualize sales data with revenue, growth, and market size:
import { BubbleChart } from '@aniruddha1806/bubble-chart';
function SalesPerformance() {
const salesData = [
{
x: 45,
y: 12,
size: 25,
label: 'North America',
color: '#3b82f6',
region: 'NA',
customers: 1250
},
{
x: 32,
y: 18,
size: 20,
label: 'Europe',
color: '#10b981',
region: 'EU',
customers: 980
},
{
x: 28,
y: 25,
size: 30,
label: 'Asia Pacific',
color: '#f59e0b',
region: 'APAC',
customers: 1580
},
{
x: 15,
y: 35,
size: 15,
label: 'Latin America',
color: '#ef4444',
region: 'LATAM',
customers: 650
},
{
x: 8,
y: 42,
size: 12,
label: 'Middle East',
color: '#8b5cf6',
region: 'ME',
customers: 420
}
];
const handleBubbleClick = (bubble) => {
alert(`Region: ${bubble.label}\\nRevenue: $${bubble.x}M\\nGrowth: ${bubble.y}%\\nCustomers: ${bubble.customers}`);
};
const customTooltip = (bubble) => (
<div>
<div style={{ fontWeight: 'bold', marginBottom: '4px' }}>{bubble.label}</div>
<div>Revenue: $${bubble.x}M</div>
<div>Growth: \${bubble.y}%</div>
<div>Market Size: \${bubble.size}</div>
<div>Customers: \${bubble.customers?.toLocaleString()}</div>
</div>
);
return (
<div style={{ padding: '20px' }}>
<h2>Regional Sales Performance</h2>
<p>Revenue vs Growth Rate (Bubble size = Market opportunity)</p>
<BubbleChart
data={salesData}
width="100%"
height={500}
xAxisLabel="Revenue ($ millions)"
yAxisLabel="Growth Rate (%)"
minRadius={15}
maxRadius={45}
xAxisTicks={6}
yAxisTicks={8}
animated={true}
animationDuration={1200}
onBubbleClick={handleBubbleClick}
tooltipContent={customTooltip}
formatXAxisValue={(value) => `$${value}M`}
formatYAxisValue={(value) => `${value}%`}
/>
<div style={{
marginTop: '20px',
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
gap: '16px'
}}>
{salesData.map((region, index) => (
<div
key={index}
style={{
padding: '16px',
backgroundColor: 'white',
border: '1px solid #e2e8f0',
borderRadius: '8px',
textAlign: 'center'
}}
>
<div style={{
width: '20px',
height: '20px',
backgroundColor: region.color,
borderRadius: '50%',
margin: '0 auto 8px'
}}></div>
<h4 style={{ margin: '0 0 4px 0' }}>{region.label}</h4>
<p style={{ margin: 0, fontSize: '14px', color: '#666' }}>
$${region.x}M revenue
</p>
</div>
))}
</div>
</div>
);
}
TypeScript Usage
The component provides full TypeScript support:
import { BubbleChart, BubbleDataPoint, BubbleChartProps } from '@aniruddha1806/bubble-chart';
import { useState, useCallback } from 'react';
interface AnalyticsData extends BubbleDataPoint {
category: string;
revenue: number;
customers: number;
}
interface ChartConfig {
title: string;
xLabel: string;
yLabel: string;
colors: string[];
}
const AnalyticsDashboard: React.FC = () => {
const [analyticsData, setAnalyticsData] = useState<AnalyticsData[]>([
{
x: 45,
y: 12,
size: 25,
label: 'Product A',
color: '#3b82f6',
category: 'Electronics',
revenue: 2500000,
customers: 1250
},
{
x: 32,
y: 18,
size: 20,
label: 'Product B',
color: '#10b981',
category: 'Software',
revenue: 1800000,
customers: 980
}
]);
const handleBubbleClick = useCallback((dataPoint: BubbleDataPoint): void => {
const analyticsPoint = dataPoint as AnalyticsData;
console.log('Analytics data:', analyticsPoint);
}, []);
const formatCurrency = useCallback((value: number): string => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 0,
maximumFractionDigits: 0
}).format(value);
}, []);
const customTooltip = useCallback((bubble: BubbleDataPoint): React.ReactNode => {
const data = bubble as AnalyticsData;
return (
<div>
<div style={{ fontWeight: 'bold', marginBottom: '4px' }}>{data.label}</div>
<div>Category: {data.category}</div>
<div>Revenue: {formatCurrency(data.revenue)}</div>
<div>Customers: {data.customers.toLocaleString()}</div>
<div>Market Share: \${data.x}%</div>
<div>Growth: \${data.y}%</div>
</div>
);
}, [formatCurrency]);
const chartConfig: ChartConfig = {
title: 'Product Performance Analysis',
xLabel: 'Market Share (%)',
yLabel: 'Growth Rate (%)',
colors: ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6']
};
const bubbleChartProps: BubbleChartProps = {
data: analyticsData,
width: '100%',
height: 500,
colors: chartConfig.colors,
xAxisLabel: chartConfig.xLabel,
yAxisLabel: chartConfig.yLabel,
minRadius: 15,
maxRadius: 45,
animated: true,
animationDuration: 1000,
onBubbleClick: handleBubbleClick,
tooltipContent: customTooltip,
formatXAxisValue: (value) => `\${value}%`,
formatYAxisValue: (value) => `\${value}%`
};
return (
<div>
<h2>{chartConfig.title}</h2>
<BubbleChart {...bubbleChartProps} />
<div>
<h3>Summary Statistics:</h3>
<p>Total Products: {analyticsData.length}</p>
<p>Total Revenue: {formatCurrency(analyticsData.reduce((sum, item) => sum + item.revenue, 0))}</p>
<p>Total Customers: {analyticsData.reduce((sum, item) => sum + item.customers, 0).toLocaleString()}</p>
</div>
</div>
);
};