Theme Customization

Buckaroo tables automatically match your OS light/dark preference. But sometimes you want more control — a branded dashboard, a high-contrast accessibility mode, or just a color scheme you enjoy staring at for hours.

The component_config.theme dictionary gives you full control over the color scheme without touching CSS. Every example on this page is a live static embed — no server, no kernel, just HTML and JavaScript.

Quick start

import buckaroo

# Jupyter / IPython — just set component_config on the widget
w = buckaroo.BuckarooWidget(df, component_config={
    'theme': {
        'colorScheme': 'dark',
        'accentColor': '#00bcd4',
    }
})

# Static embed — inject theme into the artifact
from buckaroo.artifact import prepare_buckaroo_artifact, artifact_to_json

artifact = prepare_buckaroo_artifact(df)
artifact['df_viewer_config'].setdefault('component_config', {})['theme'] = {
    'colorScheme': 'dark',
    'accentColor': '#00bcd4',
}

# MCP server — pass component_config in the /load request body
{"session": "my-session", "path": "data.csv", "component_config": {
    "theme": {"colorScheme": "dark", "accentColor": "#00bcd4"}
}}

ThemeConfig reference

All properties are optional. Omitted properties use sensible defaults based on the resolved color scheme.

Color properties

Property

Type

Description

colorScheme

'light' | 'dark' | 'auto'

Override OS color scheme detection. 'auto' (the default) respects the user’s system preference.

accentColor

CSS color

Primary highlight color for column selection, active tabs, and buttons. Default: #2196F3 (blue).

accentHoverColor

CSS color

Hover state for accent elements. Should be a darker shade of accentColor.

backgroundColor

CSS color

Main table background. Default: #ffffff (light) or #181D1F (dark).

foregroundColor

CSS color

Text and icon color. Passed through to AG Grid’s theme system.

oddRowBackgroundColor

CSS color

Alternating row stripe color. Default: #f5f5f5 (light) or #222628 (dark).

borderColor

CSS color

Grid line and border color. Passed through to AG Grid’s theme system.

headerBorderColor

CSS color

Border color between column headers. Controls the vertical dividers between columns in the header row — including MultiIndex group headers.

headerBackgroundColor

CSS color

Background color for all header rows. With MultiIndex columns, this colors both the group header row and the leaf header row.

Layout properties

Property

Type

Description

spacing

number

Base spacing unit in pixels. Controls the overall density of the grid. Default: 5. Lower values = more compact.

cellHorizontalPaddingScale

number

Multiplier for horizontal cell padding. Default: 0.3. Use 0.1 for very tight or 1.0 for spacious.

rowVerticalPaddingScale

number

Multiplier for vertical row padding. Default: 0.5. Use 0.2 for compact or 1.2 for airy.

Auto light/dark with light and dark sub-dicts

When colorScheme is 'auto', the table follows the OS preference. But a single set of colors can’t look good in both modes. Use light and dark sub-dicts to define separate palettes:

component_config = {'theme': {
    'colorScheme': 'auto',
    'light': {
        'accentColor': '#e65100',
        'backgroundColor': '#fff8f0',
        'foregroundColor': '#3e2723',
        'oddRowBackgroundColor': '#fff3e0',
        'borderColor': '#ffe0b2',
    },
    'dark': {
        'accentColor': '#ffab40',
        'backgroundColor': '#1a1209',
        'foregroundColor': '#ffe0b2',
        'oddRowBackgroundColor': '#2a1e0f',
        'borderColor': '#4e342e',
    },
}}

The resolution order is: scheme-specific override > top-level color > built-in default. This means you can set shared properties at the top level and override only what differs per scheme:

component_config = {'theme': {
    'colorScheme': 'auto',
    'spacing': 8,                     # shared — same in light and dark
    'headerBorderColor': '#7c4dff',   # shared
    'light': {
        'accentColor': '#7c4dff',
        'backgroundColor': '#faf8ff',
    },
    'dark': {
        'accentColor': '#b388ff',
        'backgroundColor': '#1a1028',
    },
}}

Both light and dark accept all color and layout properties from ThemeColorConfig.

CSS custom properties

Theme properties are injected as CSS custom properties on the wrapper div, so they cascade into all child components:

  • --bk-accent-color — accent color

  • --bk-accent-hover-color — accent hover color

  • --bk-bg-color — background color (always set, with scheme-based fallback)

  • --bk-fg-color — foreground color

How theming works under the hood

Theme configuration flows through three layers:

  1. Pythoncomponent_config['theme'] is a dict that rides alongside the DataFrame display configuration. It’s stored in df_viewer_config and serialized to JSON.

  2. CSS custom properties — The React layer reads the theme dict and sets --bk-accent-color, --bk-bg-color, etc. as inline styles on the wrapper div. All child components inherit these variables.

  3. AG Grid theme APIbackgroundColor, foregroundColor, oddRowBackgroundColor, borderColor, spacing, and the padding scale properties are passed directly to AG Grid’s Theme.withParams() method, which handles the grid’s internal styling.

The resolveColorScheme() function is the single source of truth for light/dark resolution. It checks themeConfig.colorScheme first; if that’s 'auto' or absent, it falls back to the OS preference detected via window.matchMedia('(prefers-color-scheme: dark)').

After the color scheme is resolved, resolveThemeColors() merges the matching light or dark sub-dict (if present) with the top-level properties. Scheme-specific values take priority, so you can set shared defaults at the top level and only override what differs per scheme.

In server mode (mode="buckaroo"), component_config is persisted in the session state. When a user changes the cleaning method or post-processing option, the dataflow rebuilds df_display_args from scratch — but component_config is re-applied afterward, so the theme survives interaction.

Building your own theme

Start from the closest built-in and override what you need:

# Start with forced dark, customize from there
my_theme = {
    'colorScheme': 'dark',
    'accentColor': '#your-brand-color',
}

# Only add background/foreground/border if the defaults don't work
# for your accent color. The built-in dark/light palettes are designed
# to work with any accent.

Tips:

  • accentColor is the highest-impact single property — it controls column selection highlighting, active tab backgrounds, and button colors.

  • Always pair accentColor with accentHoverColor (a slightly darker shade) for consistent interaction feedback.

  • oddRowBackgroundColor should be close to backgroundColor — just enough contrast to distinguish rows without creating visual noise.

  • Use spacing, rowVerticalPaddingScale, and cellHorizontalPaddingScale to control density. Lower values = more compact. The defaults (5, 0.5, 0.3) are a good middle ground.

  • headerBorderColor is useful when you want headers to stand out from data rows — set it to your accent color for a subtle branded touch.

  • For auto light/dark, put shared values at the top level and scheme-specific colors in light/dark sub-dicts.

  • Test with actual data. A theme that looks great on 5 rows might be overwhelming on 500.

Generating static theme demos

The embeds on this page were generated with:

python scripts/generate_theme_static_html.py

This produces HTML files in docs/extra-html/themes/ that reference the shared static-embed.js and static-embed.css bundles.