BizCharts provides a comprehensive theming system built on top of @antv/g2's theme capabilities. It supports built-in themes, custom theme creation, and dynamic theme switching for creating visually consistent and branded data visualizations.
BizCharts comes with pre-registered themes that can be applied to charts.
/**
* Built-in theme names available in BizCharts
*/
type BuiltInTheme = 'default' | 'light' | 'dark';
/**
* Built-in light theme style sheet from @antv/g2
*/
declare const antvLight: object;
/**
* Built-in dark theme style sheet from @antv/g2
*/
declare const antvDark: object;Usage Examples:
import React from "react";
import { Chart, Line } from "bizcharts";
// Using built-in themes
function ThemedCharts() {
return (
<div>
{/* Default theme */}
<Chart height={300} data={data} theme="default" autoFit>
<Line position="x*y" />
</Chart>
{/* Light theme */}
<Chart height={300} data={data} theme="light" autoFit>
<Line position="x*y" />
</Chart>
{/* Dark theme */}
<Chart height={300} data={data} theme="dark" autoFit>
<Line position="x*y" />
</Chart>
</div>
);
}Create custom themes using style sheets and register them for reuse.
/**
* Create a theme object from a style sheet configuration
* @param styleSheet - Style sheet object defining theme properties
* @returns Theme object that can be used with charts
*/
function createThemeByStyleSheet(styleSheet: ThemeStyleSheet): Theme;
/**
* Style sheet structure for theme creation
*/
interface ThemeStyleSheet {
/** Brand color palette */
brand?: {
brandColor?: string;
brandColorLight?: string;
brandColorDark?: string;
};
/** Background colors */
background?: {
color?: string;
opacity?: number;
};
/** Sub-color for secondary elements */
subColor?: string;
/** Semantic colors */
semanticRed?: string;
semanticGreen?: string;
semanticYellow?: string;
/** Color palette for data visualization */
colors10?: string[];
colors20?: string[];
/** Shape palette */
shapes?: {
point?: string[];
line?: string[];
area?: string[];
interval?: string[];
};
/** Size palette */
sizes?: number[];
/** Font family */
fontFamily?: string;
/** Component-specific styling */
components?: {
axis?: {
common?: object;
top?: object;
bottom?: object;
left?: object;
right?: object;
};
legend?: {
common?: object;
horizontal?: object;
vertical?: object;
};
tooltip?: {
container?: object;
title?: object;
list?: object;
listItem?: object;
marker?: object;
value?: object;
};
annotation?: {
arc?: object;
line?: object;
text?: object;
region?: object;
dataMarker?: object;
dataRegion?: object;
};
geometry?: {
point?: object;
line?: object;
area?: object;
interval?: object;
polygon?: object;
edge?: object;
schema?: object;
};
};
}Usage Examples:
import React from "react";
import { Chart, Line, createThemeByStyleSheet } from "bizcharts";
// Create custom theme
function CustomThemeChart() {
const customStyleSheet = {
brand: {
brandColor: '#FF6B6B'
},
background: {
color: '#FAFAFA',
opacity: 1
},
subColor: '#666666',
semanticRed: '#E74C3C',
semanticGreen: '#2ECC71',
colors10: [
'#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7',
'#DDA0DD', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E9'
],
fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif',
components: {
axis: {
common: {
label: { style: { fill: '#666', fontSize: 12 } },
line: { style: { stroke: '#CCCCCC' } },
grid: { style: { stroke: '#EEEEEE' } }
}
},
legend: {
common: {
itemName: { style: { fill: '#333', fontSize: 12 } }
}
}
}
};
const customTheme = createThemeByStyleSheet(customStyleSheet);
return (
<Chart height={400} data={data} theme={customTheme} autoFit>
<Line position="x*y" color="category" />
</Chart>
);
}
// Corporate brand theme
function BrandedChart() {
const corporateTheme = createThemeByStyleSheet({
brand: {
brandColor: '#1F4E79' // Corporate blue
},
colors10: [
'#1F4E79', '#FF6B35', '#F7931E', '#2E8B57', '#8B0000',
'#4B0082', '#FF1493', '#00CED1', '#FFD700', '#32CD32'
],
background: {
color: '#FFFFFF'
},
components: {
axis: {
common: {
label: {
style: {
fill: '#1F4E79',
fontSize: 11,
fontWeight: 'bold'
}
},
title: {
style: {
fill: '#1F4E79',
fontSize: 14,
fontWeight: 'bold'
}
}
}
}
}
});
return (
<Chart height={400} data={data} theme={corporateTheme} autoFit>
<Line position="month*revenue" color="department" />
</Chart>
);
}Apply themes dynamically using React state and theme switching.
/**
* Theme object structure that can be passed to Chart components
*/
interface Theme {
name?: string;
colors10?: string[];
colors20?: string[];
backgroundColor?: string;
subColor?: string;
semanticRed?: string;
semanticGreen?: string;
semanticYellow?: string;
fontFamily?: string;
[key: string]: any;
}Usage Examples:
import React, { useState } from "react";
import { Chart, Line, createThemeByStyleSheet, antvLight, antvDark } from "bizcharts";
// Dynamic theme switching
function DynamicThemeChart() {
const [currentTheme, setCurrentTheme] = useState('light');
const themes = {
light: createThemeByStyleSheet(antvLight),
dark: createThemeByStyleSheet(antvDark),
custom: createThemeByStyleSheet({
brand: { brandColor: '#722ED1' },
colors10: ['#722ED1', '#13C2C2', '#52C41A', '#FAAD14', '#F5222D'],
background: { color: '#F0F2F5' }
})
};
return (
<div>
<div style={{ marginBottom: 20 }}>
<button
onClick={() => setCurrentTheme('light')}
style={{
marginRight: 10,
backgroundColor: currentTheme === 'light' ? '#1890ff' : '#fff',
color: currentTheme === 'light' ? '#fff' : '#000'
}}
>
Light
</button>
<button
onClick={() => setCurrentTheme('dark')}
style={{
marginRight: 10,
backgroundColor: currentTheme === 'dark' ? '#1890ff' : '#fff',
color: currentTheme === 'dark' ? '#fff' : '#000'
}}
>
Dark
</button>
<button
onClick={() => setCurrentTheme('custom')}
style={{
backgroundColor: currentTheme === 'custom' ? '#1890ff' : '#fff',
color: currentTheme === 'custom' ? '#fff' : '#000'
}}
>
Custom
</button>
</div>
<Chart
height={400}
data={data}
theme={themes[currentTheme]}
autoFit
>
<Line position="x*y" color="series" />
</Chart>
</div>
);
}
// Responsive theme based on system preference
function ResponsiveThemeChart() {
const [isDarkMode, setIsDarkMode] = useState(
window.matchMedia('(prefers-color-scheme: dark)').matches
);
useEffect(() => {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handler = (e) => setIsDarkMode(e.matches);
mediaQuery.addListener(handler);
return () => mediaQuery.removeListener(handler);
}, []);
const theme = isDarkMode ? 'dark' : 'light';
return (
<div style={{
backgroundColor: isDarkMode ? '#141414' : '#ffffff',
padding: 20,
minHeight: 500
}}>
<p style={{ color: isDarkMode ? '#ffffff' : '#000000' }}>
Current theme: {theme} (auto-detected)
</p>
<Chart height={400} data={data} theme={theme} autoFit>
<Line position="date*value" color="category" />
</Chart>
</div>
);
}Advanced patterns for theme customization and component-specific styling.
// Component-specific theme overrides
function ComponentThemedChart() {
const baseTheme = createThemeByStyleSheet(antvLight);
// Override specific component styles
const customizedTheme = {
...baseTheme,
components: {
...baseTheme.components,
axis: {
...baseTheme.components.axis,
common: {
...baseTheme.components.axis.common,
label: {
style: {
fill: '#FF6B6B',
fontSize: 14,
fontWeight: 'bold'
}
}
}
},
legend: {
...baseTheme.components.legend,
common: {
...baseTheme.components.legend.common,
itemName: {
style: {
fill: '#1890FF',
fontSize: 13
}
}
}
}
}
};
return (
<Chart height={400} data={data} theme={customizedTheme} autoFit>
<Line position="x*y" color="category" />
</Chart>
);
}
// Multi-chart consistent theming
function ThemedDashboard() {
const dashboardTheme = createThemeByStyleSheet({
colors10: ['#1F77B4', '#FF7F0E', '#2CA02C', '#D62728', '#9467BD'],
background: { color: '#FAFAFA' },
fontFamily: 'Inter, sans-serif',
components: {
axis: {
common: {
label: { style: { fontSize: 11 } },
title: { style: { fontSize: 13, fontWeight: '600' } }
}
}
}
});
return (
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20 }}>
<Chart height={300} data={salesData} theme={dashboardTheme} autoFit>
<Line position="month*sales" />
</Chart>
<Chart height={300} data={revenueData} theme={dashboardTheme} autoFit>
<Line position="month*revenue" color="region" />
</Chart>
<Chart height={300} data={userGrowth} theme={dashboardTheme} autoFit>
<Line position="date*users" />
</Chart>
<Chart height={300} data={conversionData} theme={dashboardTheme} autoFit>
<Line position="funnel*rate" />
</Chart>
</div>
);
}Combining theme system with React hooks for advanced theme management.
import { useTheme } from "bizcharts";
// Advanced theme management with hooks
function HookedThemeChart() {
const [theme, setTheme] = useTheme('light');
const [customColors, setCustomColors] = useState([]);
const applyCustomColors = (colors) => {
const customTheme = createThemeByStyleSheet({
...antvLight,
colors10: colors
});
setTheme(customTheme);
setCustomColors(colors);
};
return (
<div>
<div style={{ marginBottom: 20 }}>
<button onClick={() => setTheme('light')}>Light</button>
<button onClick={() => setTheme('dark')}>Dark</button>
<button onClick={() => applyCustomColors([
'#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'
])}>
Custom Palette
</button>
</div>
<Chart height={400} data={data} theme={theme} autoFit>
<Line position="x*y" color="category" />
</Chart>
{customColors.length > 0 && (
<div style={{ marginTop: 10 }}>
<p>Custom colors:</p>
<div style={{ display: 'flex', gap: 5 }}>
{customColors.map((color, i) => (
<div
key={i}
style={{
width: 20,
height: 20,
backgroundColor: color,
border: '1px solid #ccc'
}}
/>
))}
</div>
</div>
)}
</div>
);
}// Core theme types
interface Theme {
name?: string;
colors10?: string[];
colors20?: string[];
backgroundColor?: string;
subColor?: string;
semanticRed?: string;
semanticGreen?: string;
semanticYellow?: string;
fontFamily?: string;
brand?: BrandConfig;
background?: BackgroundConfig;
components?: ComponentStyleConfig;
[key: string]: any;
}
interface BrandConfig {
brandColor?: string;
brandColorLight?: string;
brandColorDark?: string;
}
interface BackgroundConfig {
color?: string;
opacity?: number;
}
interface ComponentStyleConfig {
axis?: AxisStyleConfig;
legend?: LegendStyleConfig;
tooltip?: TooltipStyleConfig;
annotation?: AnnotationStyleConfig;
geometry?: GeometryStyleConfig;
}
interface AxisStyleConfig {
common?: StyleObject;
top?: StyleObject;
bottom?: StyleObject;
left?: StyleObject;
right?: StyleObject;
}
interface LegendStyleConfig {
common?: StyleObject;
horizontal?: StyleObject;
vertical?: StyleObject;
}
interface TooltipStyleConfig {
container?: StyleObject;
title?: StyleObject;
list?: StyleObject;
listItem?: StyleObject;
marker?: StyleObject;
value?: StyleObject;
}
interface AnnotationStyleConfig {
arc?: StyleObject;
line?: StyleObject;
text?: StyleObject;
region?: StyleObject;
dataMarker?: StyleObject;
dataRegion?: StyleObject;
}
interface GeometryStyleConfig {
point?: StyleObject;
line?: StyleObject;
area?: StyleObject;
interval?: StyleObject;
polygon?: StyleObject;
edge?: StyleObject;
schema?: StyleObject;
}
interface StyleObject {
fill?: string;
stroke?: string;
lineWidth?: number;
lineDash?: number[];
opacity?: number;
fontSize?: number;
fontFamily?: string;
fontWeight?: string | number;
textAlign?: 'start' | 'middle' | 'end';
textBaseline?: 'top' | 'middle' | 'bottom';
[key: string]: any;
}
// Theme creation function types
type CreateThemeFunction = (styleSheet: ThemeStyleSheet) => Theme;
type BuiltInThemeName = 'default' | 'light' | 'dark';
// Hook types
type UseThemeReturn = [Theme, (theme: string | Theme) => void];