or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

annotations.mdchart-components.mdchart-container.mdg-components.mdg2-integration.mdgeometry-components.mdindex.mdmigration-guide.mdreact-hooks.mdstatistical-charts.mdtheme-system.mdutilities.md
tile.json

theme-system.mddocs/

Theme System

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.

Capabilities

Built-in Themes

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>
  );
}

Theme Creation

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>
  );
}

Dynamic Theme Application

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>
  );
}

Theme Customization Patterns

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>
  );
}

Theme Integration with Hooks

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>
  );
}

Types

// 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];