# Theming > Theme configuration, colors, and conditional styling. --- .. llms_copy::references/theming .. toc:: ### Overview Dash Glide Grid supports comprehensive theming with 24 color properties. Customize colors at the grid, row, column, or cell level. ### Theme Builder Build and export custom themes interactively. Adjust any color and copy the resulting theme dict directly into your app. .. exec::examples.reference.theming.builder :code: false ```python # File: examples/reference/theming/builder.py import dash_glide_grid as dgg import dash_mantine_components as dmc from dash import callback, Input, Output, State, ALL, dcc from dash_iconify import DashIconify from lib.constants import GRID_LIGHT_THEME, GRID_DARK_THEME # Common color swatches SWATCHES = [ "#FFFFFF", "#F8F9FA", "#E9ECEF", "#DEE2E6", "#CED4DA", "#ADB5BD", "#6C757D", "#495057", "#343A40", "#212529", "#4F5DFF", "#228BE6", "#12B886", "#40C057", "#FAB005", "#FD7E14", "#FA5252", "#E64980", "#BE4BDB", "#7950F2", ] # Sample data for the grid preview - showcases multiple theme properties columns = [ { "title": "Name", "id": "name", "width": 120, "icon": "headerString", "group": "Person", }, { "title": "Role", "id": "role", "width": 100, "icon": "headerArray", "hasMenu": True, "filterable": True, "group": "Person", }, {"title": "Tags", "id": "tags", "width": 130, "group": "Details"}, {"title": "Projects", "id": "projects", "width": 120, "group": "Details"}, { "title": "Profile", "id": "profile", "width": 90, "icon": "headerUri", "group": "Details", }, ] data = [ { "name": "Alice Johnson", "role": "Engineer", "tags": {"kind": "bubble", "data": ["backend", "api"]}, "projects": {"kind": "drilldown", "data": [{"text": "API v2"}]}, "profile": { "kind": "uri", "data": "https://github.com", "displayData": "GitHub", }, }, { "name": "Bob Smith", "role": "Designer", "tags": {"kind": "bubble", "data": ["ui", "ux"]}, "projects": {"kind": "drilldown", "data": [{"text": "App"}, {"text": "Web"}]}, "profile": { "kind": "uri", "data": "https://dribbble.com", "displayData": "Dribbble", }, }, { "name": "Carol White", "role": "Manager", "tags": {"kind": "bubble", "data": ["ops"]}, "projects": {"kind": "drilldown", "data": [{"text": "Infra"}]}, "profile": { "kind": "uri", "data": "https://linkedin.com", "displayData": "LinkedIn", }, }, { "name": "David Brown", "role": "Developer", "tags": {"kind": "bubble", "data": ["react", "ts"]}, "projects": {"kind": "drilldown", "data": [{"text": "Dashboard"}]}, "profile": {"kind": "uri", "data": "https://dev.to", "displayData": "Dev.to"}, }, { "name": "Eve Davis", "role": "Analyst", "tags": {"kind": "bubble", "data": ["data", "sql"]}, "projects": {"kind": "drilldown", "data": [{"text": "Reports"}]}, "profile": { "kind": "uri", "data": "https://kaggle.com", "displayData": "Kaggle", }, }, ] # Theme property definitions organized by category THEME_SECTIONS = [ { "title": "Grid", "props": [ ("accentColor", "Accent Color"), ("accentLight", "Accent Light"), ("accentFg", "Accent Foreground"), ("borderColor", "Border Color"), ("horizontalBorderColor", "Horizontal Border"), ("bgRowHovered", "Row Hovered"), ], }, { "title": "Cells", "props": [ ("bgCell", "Cell Background"), ("bgCellMedium", "Cell Medium"), ("bgSearchResult", "Search Result"), ("textDark", "Text Dark"), ("textMedium", "Text Medium"), ("textLight", "Text Light"), ], }, { "title": "Headers", "props": [ ("bgHeader", "Header Background"), ("bgHeaderHasFocus", "Header Focus"), ("bgHeaderHovered", "Header Hovered"), ("textHeader", "Header Text"), ("textHeaderSelected", "Header Selected"), ("textGroupHeader", "Group Header Text"), ("bgIconHeader", "Icon Background"), ("fgIconHeader", "Icon Foreground"), ], }, { "title": "Cell Editors", "props": [ ("bgBubble", "Bubble Background"), ("bgBubbleSelected", "Bubble Selected"), ("textBubble", "Bubble Text"), ("drilldownBorder", "Drilldown Border"), ("linkColor", "Link Color"), ], }, ] def create_color_input(prop_name, label): """Create a ColorInput for a theme property.""" return dmc.ColorInput( id={"type": "theme-builder-color", "prop": prop_name}, label=label, value=GRID_LIGHT_THEME[prop_name], # Initial value, will be updated by callback format="rgba", swatches=SWATCHES, swatchesPerRow=10, size="xs", ) def create_tab_panel(props, value): """Create a tab panel with color inputs.""" return dmc.TabsPanel( dmc.SimpleGrid( cols=3, spacing="xs", children=[create_color_input(prop, label) for prop, label in props], ), value=value, pt="md", ) # Build tabs list and panels tabs_list = [ dmc.TabsTab( s["title"], value=s["title"].lower().replace(" ", "-"), rightSection=dmc.Badge( str(len(s["props"])), variant="filled", color="rgba(0, 0, 0, 0.4)", circle=True, ), ) for s in THEME_SECTIONS ] tabs_panels = [ create_tab_panel(s["props"], s["title"].lower().replace(" ", "-")) for s in THEME_SECTIONS ] component = dmc.Stack( [ # Store to track base theme mode for reset dcc.Store(id="theme-builder-mode", data="light"), # Grid preview - showcases icons, bubbles, links, selection, search dgg.GlideGrid( id={"type": "glide-grid", "index": "theme-builder"}, columns=columns, data=data, height=250, theme=GRID_LIGHT_THEME, rowSelect="multi", rowMarkers="checkbox-visible", columnSelect="multi", columnFilters={}, showSearch=False, hoverRow=True, ), # Action buttons dmc.Group( [ dmc.Group( [ dmc.Button( "Reset to Defaults", id="theme-builder-reset", variant="light", size="xs", ), dmc.CopyButton( id="theme-builder-copy", value="", children="Copy Theme", copiedChildren="Copied!", color="blue", copiedColor="teal", variant="light", size="xs", ), dmc.Select( id="theme-builder-format", data=["rgba", "rgb", "hex", "hexa", "hsl", "hsla"], value="rgba", w=80, size="xs", styles={"root": {"height": 38}}, ), ], gap="xs", align="center", ), dmc.Button( "Search", id="theme-builder-search", variant="light", color="yellow", size="xs", leftSection=DashIconify(icon="mdi:magnify", width=14), ), ], justify="space-between", align="center", ), # Color input sections in tabs dmc.Tabs( [ dmc.TabsList( tabs_list, grow=True, bd="1px solid var(--mantine-color-default-border)", p=10, ), *tabs_panels, ], value="grid", variant="pills", radius="sm", ), ], gap="md", ) # Get all theme property names for the callback ALL_PROPS = [prop for section in THEME_SECTIONS for prop, _ in section["props"]] @callback( Output({"type": "theme-builder-color", "prop": ALL}, "value", allow_duplicate=True), Output("theme-builder-mode", "data"), Output( {"type": "glide-grid", "index": "theme-builder"}, "theme", allow_duplicate=True ), Input("color-scheme-storage", "data"), prevent_initial_call="initial_duplicate", ) def initialize_theme(color_scheme): """Initialize colors based on app color scheme.""" is_dark = color_scheme == "dark" base_theme = GRID_DARK_THEME if is_dark else GRID_LIGHT_THEME mode = "dark" if is_dark else "light" return [base_theme[prop] for prop in ALL_PROPS], mode, base_theme @callback( Output( {"type": "glide-grid", "index": "theme-builder"}, "theme", allow_duplicate=True ), Output("theme-builder-copy", "value"), Input({"type": "theme-builder-color", "prop": ALL}, "value"), State("theme-builder-mode", "data"), prevent_initial_call=True, ) def update_theme(color_values, mode): """Update grid theme and copy button value when any color changes.""" base_theme = GRID_DARK_THEME if mode == "dark" else GRID_LIGHT_THEME # Build theme dict from current values theme = {} for i, prop in enumerate(ALL_PROPS): if color_values[i]: theme[prop] = color_values[i] else: theme[prop] = base_theme[prop] # Generate Python code for the theme code_lines = ["theme = {"] for prop in ALL_PROPS: code_lines.append(f' "{prop}": "{theme[prop]}",') code_lines.append("}") code = "\n".join(code_lines) return theme, code @callback( Output({"type": "theme-builder-color", "prop": ALL}, "value"), Input("theme-builder-reset", "n_clicks"), State("theme-builder-mode", "data"), prevent_initial_call=True, ) def reset_theme(_, mode): """Reset all colors to current mode's defaults.""" base_theme = GRID_DARK_THEME if mode == "dark" else GRID_LIGHT_THEME return [base_theme[prop] for prop in ALL_PROPS] @callback( Output({"type": "glide-grid", "index": "theme-builder"}, "showSearch"), Input("theme-builder-search", "n_clicks"), prevent_initial_call=True, ) def toggle_search(n_clicks): """Toggle the search box visibility.""" return (n_clicks or 0) % 2 == 1 @callback( Output({"type": "theme-builder-color", "prop": ALL}, "format"), Input("theme-builder-format", "value"), ) def update_color_format(fmt): """Update all color inputs to use the selected format.""" return [fmt] * len(ALL_PROPS) ``` :defaultExpanded: false :withExpandedButton: true ### Theme Overrides Apply conditional styling at row, column, or cell level. Use the selector to see each override type. .. exec::examples.reference.theming.overrides :code: false :defaultExpanded: false :withExpandedButton: true ### Dark Mode Integration Sync grid theme with Dash Mantine Components color scheme. .. exec::examples.reference.theming.dmc_integration :code: false ```python # File: examples/reference/theming/dmc_integration.py import dash_glide_grid as dgg import dash_mantine_components as dmc from dash import callback, Input, Output from lib.constants import GRID_LIGHT_THEME, GRID_DARK_THEME columns = [ {"title": "Name", "id": "name", "width": 150}, {"title": "Email", "id": "email", "width": 200}, {"title": "Role", "id": "role", "width": 120}, {"title": "Status", "id": "status", "width": 100}, ] data = [ { "name": "Alice Johnson", "email": "alice@example.com", "role": "Engineer", "status": "Active", }, { "name": "Bob Smith", "email": "bob@example.com", "role": "Designer", "status": "Active", }, { "name": "Carol White", "email": "carol@example.com", "role": "Manager", "status": "Away", }, { "name": "David Brown", "email": "david@example.com", "role": "Developer", "status": "Active", }, ] component = dmc.Stack( [ dgg.GlideGrid( id={"type": "glide-grid", "index": "dmc-integration"}, columns=columns, data=data, height=200, ), dmc.Text( "Toggle dark mode using the theme switch in the header to see the grid update.", size="sm", c="dimmed", ), ], gap="md", ) # The "color-scheme-storage" is a dcc.Store in the app layout that holds # the current theme ("light" or "dark"). It's updated when the user toggles # the theme switch in the header. @callback( Output( {"type": "glide-grid", "index": "dmc-integration"}, "theme", allow_duplicate=True, ), Input("color-scheme-storage", "data"), # dcc.Store with "light" or "dark" prevent_initial_call=True, ) def update_grid_theme(color_scheme): """Update grid theme based on app color scheme.""" return GRID_DARK_THEME if color_scheme == "dark" else GRID_LIGHT_THEME ``` :defaultExpanded: false :withExpandedButton: true ### CSS Theming As an alternative to the `theme` prop, you can style grids using CSS variables. Use the `className` prop to target specific grids: ```python dgg.GlideGrid( className="my-grid", columns=columns, data=data, # ... ) ``` Then in your CSS file: ```css /* Global grid styling */ .my-grid { border: 1px solid var(--mantine-color-default-border); border-radius: 8px; overflow: hidden; } /* Theme-aware colors */ html[data-mantine-color-scheme='light'] .my-grid { --gdg-accent-color: #e64980; --gdg-bg-cell: #ffffff; --gdg-bg-header: #f8f9fa; --gdg-border-color: #dee2e6; --gdg-text-dark: #212529; } html[data-mantine-color-scheme='dark'] .my-grid { --gdg-accent-color: #e64980; --gdg-bg-cell: #1a1b1e; --gdg-bg-header: #25262b; --gdg-border-color: #373a40; --gdg-text-dark: #c1c2c5; } ``` #### Available CSS Variables | Variable | Description | |----------|-------------| | `--gdg-accent-color` | Primary accent color | | `--gdg-accent-fg` | Foreground on accent | | `--gdg-accent-light` | Light accent highlight | | `--gdg-text-dark` | Primary text | | `--gdg-text-medium` | Secondary text | | `--gdg-text-light` | Tertiary text | | `--gdg-text-header` | Header text | | `--gdg-bg-cell` | Cell background | | `--gdg-bg-cell-medium` | Alternate cell background | | `--gdg-bg-header` | Header background | | `--gdg-bg-header-hovered` | Header hover background | | `--gdg-border-color` | Border color | | `--gdg-horizontal-border-color` | Horizontal border | | `--gdg-link-color` | URI link color | > **Note:** The `theme` prop takes precedence over CSS variables. Use one approach or the other for consistent results. ### Props Reference #### Theme Prop | Property | Type | Default | Description | |----------|------|---------|-------------| | `theme` | dict | - | Custom theme object with color properties | | `scaleToRem` | boolean | False | Scale theme elements to match rem sizing | #### Accent Colors | Property | Type | Description | |----------|------|-------------| | `accentColor` | string | Primary accent (selection, focus rings) | | `accentLight` | string | Light accent for highlights | | `accentFg` | string | Foreground color on accent backgrounds | #### Text Colors | Property | Type | Description | |----------|------|-------------| | `textDark` | string | Primary text color | | `textMedium` | string | Secondary text color | | `textLight` | string | Tertiary text color | | `textBubble` | string | Text color in bubble cells | | `linkColor` | string | Color for URI cell links | | `textHeader` | string | Header text color | | `textHeaderSelected` | string | Selected header text color | | `textGroupHeader` | string | Group header text color | #### Background Colors | Property | Type | Description | |----------|------|-------------| | `bgCell` | string | Primary cell background | | `bgCellMedium` | string | Alternate/disabled cell background | | `bgHeader` | string | Header background | | `bgHeaderHasFocus` | string | Header background when column has focus | | `bgHeaderHovered` | string | Header background on hover | | `bgBubble` | string | Bubble cell background | | `bgBubbleSelected` | string | Selected bubble background | | `bgSearchResult` | string | Search result highlight | | `bgIconHeader` | string | Icon header background | | `fgIconHeader` | string | Header icon foreground color | #### Border Colors | Property | Type | Description | |----------|------|-------------| | `borderColor` | string | Primary border color | | `horizontalBorderColor` | string | Horizontal border override | | `drilldownBorder` | string | Drilldown cell border | #### Override Props | Property | Type | Description | |----------|------|-------------| | `getRowThemeOverride` | dict | JS function for row-level styling: `{"function": "name(row, rowData)"}` | | `rowMarkerTheme` | dict | Theme overrides for row marker column | | Column `themeOverride` | dict | Per-column theme in column definition | | Cell `themeOverride` | dict | Per-cell theme in cell data object | --- *Source: /reference/theming* *Generated with dash-improve-my-llms*