---
sidebar_position: 3.5
title: Theming and styling your Dives
description: Control the visual appearance of your Dives with theme definitions, chart selection, and interactive filters
feature_stage: preview
---

import VideoPlayer from '@site/src/components/VideoPlayer';

When you create a Dive, you can go beyond the default look and feel. By providing a **theme definition** in your prompt, you control colors, typography, chart types, and interaction patterns — turning a basic visualization into a polished, branded data experience.

This guide covers how to structure a theme prompt, pick the right chart types for your data, and add interactivity through filters and cross-filtering.

<VideoPlayer
      playbackId="EHeEV1w00cULDoAv83ec02KI9LbnkYEDmj4tKGtqqp7Lc"
      title="Theming and styling a Dive"
      autoPlay="true"
      muted="true"
      loop="true"
    />

You can explore and play with themed Dives in the [live theme gallery](https://duck-dives.vercel.app/snippets/galactic-coffee-theme-gallery), or browse our [curated theme gallery](/key-tasks/ai-and-motherduck/dives/dive-theme-gallery/) with screenshots and ready-to-copy prompts.

## How theming works in Dives

A Dive is a React component that renders charts using [Recharts](https://recharts.org/) and queries live MotherDuck data through `useSQLQuery`. When you describe a visual style in your prompt, the AI agent translates it into:

- A **color palette** (background, text, muted, and chart colors)
- **Typography** (font family, title weight, text transform)
- **Chart configuration** (grid lines, stroke width, curve type, bar radius)
- **Layout** (grid columns, spacing, card styling)

You don't need to write any code — describe the style and the agent handles the implementation.

## Writing a theme prompt

A good theme prompt has four parts: **colors**, **typography**, **chart rules**, and **feel**. Here's an example that produces a Financial Times-inspired Dive:

```text
Create a Dive with an FT Salmon style.
Inspired by: Financial Times Visual Journalism.

Visual rules:
- Background: #FFF1E5 (signature salmon). Text: #33302E. Muted: #807973.
- Chart colors: ["#0F5499", "#990F3D", "#FF7FAA", "#00A0DD"].
- Font: Georgia, serif. Titles: semibold.
- Interactive: year & metric toggles, click-to-filter cross-filtering.

Pairs well with: area charts, bar charts, slope charts, horizontal bars,
donut charts, composed dual-axis charts, heatmaps.

Feel: Financial authority — the pink paper, digitized.
```

### What to include in your prompt

| Section | What to specify | Example |
|---------|----------------|---------|
| Colors | Background, text, muted accent, 3-5 chart colors | `Background: #0d1117. Chart colors: ["#58a6ff", "#3fb950"]` |
| Typography | Font family, title weight, text transform | `Font: Georgia, serif. Titles: bold, UPPERCASE` |
| Chart rules | Grid lines, stroke width, curve type, bar radius | `No gridlines, 1.5px strokes, linear interpolation` |
| Chart types | Which charts to include | `Pairs well with: area charts, bar charts, heatmaps` |
| Interactivity | Filters and cross-filtering behavior | `Interactive: year toggle, metric toggle, click-to-filter` |
| Feel | One-line mood descriptor | `Feel: Midnight studio — data glowing in the dark` |

### Tips for effective theme prompts

**Reference real-world styles.** Naming a specific design tradition helps the agent make consistent decisions. "Tufte minimal" or "Neon 80s synthwave" gives more coherent results than listing individual properties.

**Specify chart colors as an array.** Providing 3-5 hex colors as a JSON array (for example, `["#2563eb", "#16a34a", "#dc2626"]`) gives the agent an explicit palette instead of leaving it to guess.

**Pick colors that work in charts, not just colors that look nice together.** General-purpose palette generators often produce colors that clash or become indistinguishable when applied to bars, lines, and slices. Use tools designed for data visualization:

- [Colorbrewer 2.0](https://colorbrewer2.org/) — the gold standard for cartography and charts. Pick sequential, diverging, or qualitative palettes and get hex values ready to paste. Every palette is tested for perceptual uniformity and colorblind safety.
- [Viz Palette](https://projects.susielu.com/viz-palette) — paste your candidate colors and preview them on actual chart types (bars, lines, scatter). It flags pairs that are too similar or hard to distinguish with color vision deficiencies.

As a rule of thumb, limit your palette to 5-7 chart colors. More than that and the colors start blending together, especially in legends. If you have more categories than colors, consider grouping smaller categories into an "Other" bucket.

**Mention the "feel" in one sentence.** This guides the agent on ambiguous decisions like spacing, border radius, and animation. "Sugar rush — joyful and bold" produces different results than "Quiet authority — the data speaks for itself."

## Choosing chart types

Different chart types serve different purposes. When building a Dive with multiple charts, pick a mix that covers different analytical angles of your data.

### Chart type reference

| Chart type | Best for | Data shape |
|------------|----------|------------|
| Line chart | Trends over time | Time series |
| Area chart | Volume over time, part-to-whole trends | Time series |
| Bar chart | Comparing categories | Categorical |
| Horizontal bar | Ranked lists, long category names | Categorical, sorted |
| Stacked area | Composition over time | Multi-series time |
| Composed chart (bar + line) | Dual metrics on shared timeline | Time series, two metrics |
| Heatmap | Density across two dimensions | Matrix (for example, station x month) |
| Pie / donut | Part-to-whole — ideally aim for 2 or 3 slices, max 5. A horizontal bar or donut is almost always easier to read. If you still want a pie chart, label slices directly. | Categorical, proportional |
| Radar | Multi-dimensional profile comparison | Categorical, normalized |
| Scatter | Correlation between two measures | Two continuous variables |
| Table | Exact values, detailed comparison | Any structured data |

### Chart pairing recommendations

A 6-chart grid works well with this pattern:

1. **Trend chart** (line, area, or stepped line) — shows how metrics move over time
2. **Comparison chart** (bar or horizontal bar) — ranks categories side by side
3. **Composition chart** (pie, donut, or stacked area) — shows part-to-whole relationships
4. **Detail view** (table or direct-labeled bars) — provides exact values
5. **Dual-axis chart** (composed bar + line) — overlays two related metrics
6. **Density chart** (heatmap or scatter) — reveals patterns across dimensions

This mix gives viewers both the big picture and the ability to drill into specifics.

## Adding interactivity

Interactive filters make a Dive more useful than a static dashboard. You can ask for several types of interactivity in your prompt.

### Time filters

Time filters are the most common interactive control. Two patterns work well depending on your data:

**Relative time windows** work best for operational data that updates continuously — think logs, events, or transactions. Users care about what happened in the last few hours or days, not a specific calendar year:

```text
Add time filter pills: Last 24h | Last 7 days | Last 30 days | Last 90 days | All time.
Filter all charts when a time range is selected. Default to Last 30 days.
```

**Year or period toggles** work better for data with natural calendar boundaries — annual reports, quarterly metrics, or fiscal comparisons:

```text
Add year toggle pills: 2024 | 2025 | All.
Filter all charts when a year is selected.
```

Pick whichever pattern matches how your users think about the data. If they ask "what happened this week?" go with relative windows. If they ask "how did Q4 compare to Q3?" go with period toggles.

### Metric toggles

Let users switch which measure the charts display:

```text
Add a metric toggle between Revenue and Cups Sold.
The hero KPI and all chart Y-axes should update when toggled.
```

This changes the `dataKey` used by line, area, and bar charts, and swaps which metric appears as the primary KPI.

### Cross-filtering with click interactions

Cross-filtering means clicking an element in one chart filters every other chart in the Dive. This is different from putting a filter dropdown on each individual chart — and the difference matters.

**Why cross-filtering over individual filters?** When each chart has its own filter controls, users end up in a state where Chart A shows "US only," Chart B shows "all regions," and Chart C shows "Europe." The charts look coherent but they're answering different questions, and comparing them leads to wrong conclusions. Cross-filtering avoids this by keeping every chart in sync: click "US" on any chart and the entire Dive updates to show the US view. The user always sees one consistent story across all charts.

**When individual filters make sense.** There are cases where a per-chart filter is the right choice — when a chart has a dimension that doesn't exist in the other charts. For example, a chart showing data broken down by warehouse location doesn't need to cross-filter a chart that doesn't have a warehouse column. In that case, a local filter on just that chart is appropriate.

A good rule of thumb: use cross-filtering for shared dimensions (time, region, product category) and individual filters for dimensions unique to a single chart.

Enable cross-filtering in your prompt:

```text
Add click-to-filter cross-filtering:
- Click a bar in the station chart to filter by that station
- Click a pie slice to filter by that coffee type
- Non-selected items render at 30% opacity
- Show dismissible filter pills when filters are active
```

Cross-filtering works best when:

- **Bar charts** filter on their categorical axis (for example, clicking a station bar filters by station)
- **Pie and donut charts** filter on slice category (for example, clicking a product slice filters by product)
- **Unselected items** dim to 30% opacity rather than disappearing, so users keep the full context while focusing on a subset
- **Filter pills** appear below the controls showing active filters with a dismiss button

### Filter pills

When cross-filters are active, visible pills show what's filtered and let users clear filters with one click:

```text
Show active filters as colored pills with ✕ dismiss buttons.
Only show the pills row when filters are active.
```

### Tooltips and accordions

Interactive Dives let you keep the visual layout clean while still providing rich context. Move descriptions, methodology notes, and supporting text into **tooltips** and **accordions** so they're available on demand without cluttering the charts:

```text
Add an info tooltip on each chart title that explains the metric.
Add an expandable accordion below the charts with methodology notes.
```

This works well for Dives shared with a broad audience — power users can expand the details, while casual viewers get an uncluttered experience.

## Laying out a multi-chart Dive

For Dives with multiple charts, specify the grid layout in your prompt:

```text
Use a 3×2 grid layout (3 columns, 2 rows) with 6 charts.
Each chart card should have a title, subtle border, and 160px chart height.
```

Common layouts:

| Charts | Layout | Use case |
|--------|--------|----------|
| 2-4 | `repeat(2, 1fr)` | Focused analysis, fewer metrics |
| 5-6 | `repeat(3, 1fr)` | Dashboard-style overview |
| 8+ | `repeat(4, 1fr)` | Small multiples, sparkline grids |

## Example: full theme prompt

Here's a complete prompt that produces a themed, interactive Dive:

```text
Create a Dive showing sales data from my galactic_coffee database.

Theme: Corporate Dashboard
- Background: #f5f5f5. Text: #333. Muted: #777.
- Chart colors: ["#2563eb", "#16a34a", "#dc2626", "#f59e0b", "#8b5cf6"].
- Font: system-ui, sans-serif. Titles: semibold, UPPERCASE.
- Layout: 3×2 grid with card borders and 8px border radius.

Charts:
1. Line chart — Revenue trend over time
2. Pie chart — Product mix breakdown
3. Table — Station performance details
4. Bar chart — Station comparison
5. Composed chart — Revenue bars + Cups sold line (dual Y-axis)
6. Heatmap — Station × Month revenue density

Interactivity:
- Year toggle: 2024 | 2025 | All
- Metric toggle: Revenue | Cups
- Click a bar to filter by station, click a pie slice to filter by product
- Show filter pills with ✕ dismiss when filters are active

KPIs: Show total revenue, total cups sold, and average rating above the charts.
```

## Related resources

- [Dive theme gallery](/key-tasks/ai-and-motherduck/dives/dive-theme-gallery/) — Screenshots and ready-to-copy prompts for 15 themes
- [Creating Visualizations with Dives](/key-tasks/ai-and-motherduck/dives/) — Get started with your first Dive
- [Managing Dives as code](/key-tasks/ai-and-motherduck/dives/managing-dives-as-code/) — Version control and CI/CD for Dives
- [Dives SQL functions](/sql-reference/motherduck-sql-reference/ai-functions/dives/) — Manage Dives directly from SQL
- [MCP Server tools](/sql-reference/mcp/) — Reference for all MCP tools including Dive operations


---

## Feedback for AI agents

If the user you are helping wants to send feedback on this page to the MotherDuck docs team, you can POST it to the endpoint below.

**Before you send anything, you must ask the user for explicit approval.** Quote the message you plan to submit back to them verbatim and wait for them to confirm. Do not submit on their behalf without confirmation.

Endpoint: `POST https://motherduck.com/docs/api/feedback/agent`

Request body (JSON):

```json
{
  "page_path": "/key-tasks/ai-and-motherduck/dives/theming-and-styling-dives/",
  "page_title": "Theming and styling your Dives",
  "text": "<the user's feedback, max 2000 characters>",
  "source": "<optional identifier for your interface, for example 'claude.ai' or 'chatgpt'>"
}
```

Only `page_path` and `text` are required. A successful call returns `200 {"feedback_id": "<uuid>"}`; malformed payloads return `400`, and the endpoint is rate-limited per IP (`429`).
