Dash Mantine Components (DMC) v2.x
Build modern Dash applications with 100+ Mantine UI components.
Quick Start
Minimal DMC app requiring MantineProvider wrapper:
from dash import Dash, callback, Input, Output
import dash_mantine_components as dmc
app = Dash(__name__)
app.layout = dmc.MantineProvider([
dmc.Container([
dmc.Title("My DMC App", order=1),
dmc.TextInput(label="Name", id="name-input", placeholder="Enter name"),
dmc.Button("Submit", id="submit-btn", mt="md"),
dmc.Text(id="output", mt="md"),
], size="sm", py="xl")
])
@callback(Output("output", "children"), Input("submit-btn", "n_clicks"), Input("name-input", "value"))
def update_output(n_clicks, name):
if not n_clicks:
return ""
return f"Hello, {name or 'World'}!"
if __name__ == "__main__":
app.run(debug=True)
Critical: All DMC components MUST be inside dmc.MantineProvider.
Version Note: This skill targets DMC 2.x (Mantine 8.x). Run pip show dash-mantine-components to check your installed version. For the latest features and API changes, use fetch_docs.py to query the official documentation at https://www.dash-mantine-components.com/assets/llms.txt
Workflow Decision Tree
Select components by use case:
Form Inputs
| Need |
Component |
Key Props |
| Text input |
TextInput |
label, placeholder, value, debounce |
| Dropdown |
Select |
data, value, searchable, clearable |
| Multi-select |
MultiSelect |
data, value, searchable |
| Checkbox |
Checkbox |
label, checked |
| Toggle |
Switch |
label, checked, onLabel, offLabel |
| Number |
NumberInput |
value, min, max, step |
| Date |
DatePickerInput |
value, type, minDate, maxDate |
| Rich text |
Textarea |
label, value, autosize, minRows |
| File upload |
FileInput |
value, accept, multiple |
Layout
| Need |
Component |
Key Props |
| Content wrapper |
Container |
size, px, py |
| Vertical stack |
Stack |
gap, align, justify |
| Horizontal row |
Group |
gap, justify, wrap |
| CSS Grid |
Grid, GridCol |
columns, gutter, span |
| Full app shell |
AppShell |
header, navbar, aside, footer |
| Card container |
Card |
shadow, padding, radius, withBorder |
| Flex layout |
Flex |
direction, wrap, gap, align |
Navigation
| Need |
Component |
Key Props |
| Nav item |
NavLink |
label, href, active, leftSection |
| Tabs |
Tabs, TabsList, TabsPanel |
value, orientation |
| Breadcrumb |
Breadcrumbs |
separator |
| Stepper |
Stepper, StepperStep |
active, onStepClick |
| Pagination |
Pagination |
value, total, siblings |
| Table of contents |
TableOfContents |
links, variant, active |
Feedback & Overlays
| Need |
Component |
Key Props |
| Modal dialog |
Modal |
opened, onClose, title, centered |
| Side panel |
Drawer |
opened, onClose, position, size |
| Toast |
Notification |
title, message, color, icon |
| Alert banner |
Alert |
title, color, variant, icon |
| Loading |
Loader, LoadingOverlay |
size, type, visible |
| Progress |
Progress, RingProgress |
value, size, sections |
| Tooltip |
Tooltip |
label, position, withArrow |
| Copy button |
CopyButton |
value, timeout |
Data Display
| Need |
Component |
Key Props |
| Data table |
Table |
data, striped, highlightOnHover |
| Accordion |
Accordion, AccordionItem |
value, multiple, variant |
| Timeline |
Timeline, TimelineItem |
active, bulletSize |
| Badge |
Badge |
color, variant, size |
Charts
| Need |
Component |
Key Props |
| Line |
LineChart |
data, dataKey, series |
| Bar |
BarChart |
data, dataKey, series, orientation |
| Area |
AreaChart |
data, dataKey, series |
| Pie/Donut |
DonutChart, PieChart |
data, chartLabel |
| Scatter |
ScatterChart |
data, dataKey, series |
What's New in Recent Versions
v2.5.x:
TableOfContents - Auto-generated table of contents from headings
selectFirstOptionOnDropdownOpen prop for Select/MultiSelect/Autocomplete
openOnFocus prop for Combobox components
- AppShell
mode="static" for nested shells
window.MantineCore / window.MantineHooks for custom component building
v2.4.x:
CopyButton / CustomCopyButton - Clipboard operations
getEditor(id) - Access RichTextEditor TipTap instance in clientside callbacks
- Function props for chart axis/grid customization
v2.3.x:
MiniCalendar - Compact calendar component
ScrollAreaAutoheight - Auto-sizing scroll area
DirectionProvider - RTL text direction support
→ Full component reference: references/components-quick-ref.md
Core Patterns
Theming
Configure theme via MantineProvider:
theme = {
"primaryColor": "blue",
"fontFamily": "Inter, sans-serif",
"defaultRadius": "md",
"colors": {
"brand": ["#f0f9ff", "#e0f2fe", "#bae6fd", "#7dd3fc", "#38bdf8",
"#0ea5e9", "#0284c7", "#0369a1", "#075985", "#0c4a6e"]
},
"components": {
"Button": {"defaultProps": {"size": "md", "radius": "md"}},
"TextInput": {"defaultProps": {"size": "sm"}},
}
}
app.layout = dmc.MantineProvider(
theme=theme,
forceColorScheme="light", # or "dark", or None for auto
children=[...]
)
Theme Toggle Pattern (clientside callback):
from dash import clientside_callback, ClientsideFunction
app.layout = dmc.MantineProvider(
id="mantine-provider",
children=[
dcc.Store(id="theme-store", storage_type="local", data="light"),
dmc.Switch(id="theme-switch", label="Dark mode", checked=False),
# ... rest of layout
]
)
clientside_callback(
"""(checked) => checked ? "dark" : "light" """,
Output("mantine-provider", "forceColorScheme"),
Input("theme-switch", "checked"),
)
→ Full theming guide: references/theming-patterns.md
Styling
Style Props - Universal props on all DMC components:
| Prop |
CSS Property |
Values |
m, mt, mb, ml, mr, mx, my |
margin |
xs, sm, md, lg, xl or number (px) |
p, pt, pb, pl, pr, px, py |
padding |
same as margin |
c |
color |
"blue", "red.6", "dimmed", "var(--mantine-color-text)" |
bg |
background |
same as color |
w, h |
width, height |
"100%", "50vw", number (px) |
maw, mah, miw, mih |
max/min width/height |
same as w, h |
fw |
font-weight |
400, 500, 700 |
fz |
font-size |
xs, sm, md, lg, xl or number |
ta |
text-align |
"left", "center", "right" |
td |
text-decoration |
"underline", "line-through" |
Responsive Values - Dict with breakpoints:
dmc.Button("Click", w={"base": "100%", "sm": "auto", "lg": 200})
dmc.Stack(gap={"base": "xs", "md": "lg"})
Styles API - Target nested elements:
dmc.Select(
data=["A", "B", "C"],
classNames={"input": "my-input", "dropdown": "my-dropdown"},
styles={"label": {"fontWeight": 700}, "input": {"borderColor": "blue"}},
)
→ Full styling guide: references/styling-guide.md
Callbacks
Basic Pattern:
from dash import callback, Input, Output, State
@callback(
Output("output", "children"),
Input("button", "n_clicks"),
State("input", "value"),
prevent_initial_call=True,
)
def update(n_clicks, value):
return f"Clicked {n_clicks} times with value: {value}"
Pattern-Matching (dynamic components):
from dash import ALL, MATCH, callback_context as ctx
# ALL: Respond to any button with type "dynamic-btn"
@callback(
Output("output", "children"),
Input({"type": "dynamic-btn", "index": ALL}, "n_clicks"),
)
def handle_all(n_clicks_list):
triggered = ctx.triggered_id # {"type": "dynamic-btn", "index": X}
return f"Button {triggered['index']} clicked"
# MATCH: Update the output matching the triggered input
@callback(
Output({"type": "item-output", "index": MATCH}, "children"),
Input({"type": "item-btn", "index": MATCH}, "n_clicks"),
prevent_initial_call=True,
)
def handle_match(n):
return f"Clicked {n} times"
Clientside Callback (browser-side JavaScript):
from dash import clientside_callback
clientside_callback(
"""(n) => n ? `Clicked ${n} times` : "Not clicked" """,
Output("output", "children"),
Input("button", "n_clicks"),
)
DMC-Specific Props:
debounce=300 - Delay callback trigger (ms) for TextInput, Textarea
persistence=True - Persist value across page reloads
persistence_type="local" - Storage type: memory, local, session
→ Full callbacks reference: references/callbacks-advanced.md
Multi-Page Apps
Use Dash Pages with DMC AppShell:
# app.py
import dash
from dash import Dash
import dash_mantine_components as dmc
app = Dash(__name__, use_pages=True, pages_folder="pages")
app.layout = dmc.MantineProvider([
dmc.AppShell(
[
dmc.AppShellHeader(dmc.Group([
dmc.Title("My App", order=3),
dmc.Switch(id="theme-switch"),
], h="100%", px="md")),
dmc.AppShellNavbar([
dmc.NavLink(label=page["name"], href=page["path"], active=page["path"] == "/")
for page in dash.page_registry.values()
], p="md"),
dmc.AppShellMain(dash.page_container),
],
header={"height": 60},
navbar={"width": 250, "breakpoint": "sm", "collapsed": {"mobile": True}},
padding="md",
)
])
if __name__ == "__main__":
app.run(debug=True)
# pages/home.py
import dash
import dash_mantine_components as dmc
dash.register_page(__name__, path="/", name="Home")
layout = dmc.Container([
dmc.Title("Welcome", order=2),
dmc.Text("Home page content"),
], py="xl")
# pages/analytics.py
import dash
import dash_mantine_components as dmc
dash.register_page(__name__, path="/analytics", name="Analytics")
layout = dmc.Container([
dmc.Title("Analytics", order=2),
# Charts, tables, etc.
], py="xl")
Variable Paths:
# pages/user.py
dash.register_page(__name__, path_template="/user/<user_id>")
def layout(user_id=None):
return dmc.Container([
dmc.Title(f"User: {user_id}", order=2),
])
→ Full multi-page guide: references/multi-page-apps.md
Component Categories
Quick links to reference documentation:
| Category |
Components |
Reference |
| All Components |
90+ components with props/events |
components-quick-ref.md |
| Theming |
MantineProvider, theme object, colors |
theming-patterns.md |
| Styling |
Style props, Styles API, CSS variables |
styling-guide.md |
| Callbacks |
Pattern-matching, clientside, background |
callbacks-advanced.md |
| Multi-Page |
Dash Pages, routing, AppShell |
multi-page-apps.md |
| Charts |
Data formats, series config |
charts-data-formats.md |
| Date Pickers |
DatePicker, DatesProvider, localization |
date-pickers-guide.md |
| Dash Core |
dcc.Store, caching, performance |
dash-fundamentals.md |
| Migration |
v1.x to v2.x breaking changes |
migration-v2.md |
Asset Templates
Copy and adapt these templates:
| Template |
Description |
| app_single_page.py |
Complete single-page DMC app with theme toggle |
| app_multi_page.py |
Multi-page app with Dash Pages and AppShell |
| callbacks_patterns.py |
All callback pattern examples |
| theme_presets.py |
Pre-built theme configurations |
Utility Scripts
| Script |
Usage |
| fetch_docs.py |
python fetch_docs.py "Select" - Fetch/search official llms.txt |
| scaffold_app.py |
python scaffold_app.py myapp --type multi --shell |
| generate_theme.py |
python generate_theme.py --primary "#0ea5e9" |
| component_search.py |
python component_search.py "select" |
Common Tasks
Form with Validation
@callback(
Output("submit-btn", "disabled"),
Output("error-text", "children"),
Input("email-input", "value"),
Input("password-input", "value"),
)
def validate_form(email, password):
errors = []
if not email or "@" not in email:
errors.append("Valid email required")
if not password or len(password) < 8:
errors.append("Password must be 8+ characters")
return bool(errors), ", ".join(errors)
Modal Open/Close
app.layout = dmc.MantineProvider([
dmc.Button("Open Modal", id="open-modal-btn"),
dmc.Modal(
id="my-modal",
title="Confirm Action",
children=[
dmc.Text("Are you sure?"),
dmc.Group([
dmc.Button("Cancel", id="cancel-btn", variant="outline"),
dmc.Button("Confirm", id="confirm-btn", color="red"),
], justify="flex-end", mt="md"),
],
),
])
@callback(
Output("my-modal", "opened"),
Input("open-modal-btn", "n_clicks"),
Input("cancel-btn", "n_clicks"),
Input("confirm-btn", "n_clicks"),
prevent_initial_call=True,
)
def toggle_modal(open_clicks, cancel, confirm):
from dash import ctx
if ctx.triggered_id == "open-modal-btn":
return True
return False
Loading State
from dash import dcc
app.layout = dmc.MantineProvider([
dmc.Button("Load Data", id="load-btn"),
dcc.Loading(
id="loading",
type="circle",
children=dmc.Container(id="data-container"),
),
])
@callback(Output("data-container", "children"), Input("load-btn", "n_clicks"))
def load_data(n):
import time
time.sleep(2) # Simulate slow operation
return dmc.Text("Data loaded!")
Chart with Data
data = [
{"month": "Jan", "sales": 100, "profit": 20},
{"month": "Feb", "sales": 150, "profit": 35},
{"month": "Mar", "sales": 120, "profit": 25},
]
dmc.BarChart(
data=data,
dataKey="month",
series=[
{"name": "sales", "color": "blue.6"},
{"name": "profit", "color": "green.6"},
],
h=300,
withLegend=True,
withTooltip=True,
)
Troubleshooting
Common Errors
| Error |
Cause |
Fix |
MantineProvider is required |
Component outside provider |
Wrap entire layout in dmc.MantineProvider([...]) |
Invalid theme color |
Color not in theme |
Use built-in colors (blue, red) or add to theme["colors"] |
Callback output not found |
Component not in layout |
Ensure component with ID exists in layout |
Circular callback detected |
Output also used as Input |
Use State instead of Input for non-triggering values |
Pattern-matching ID mismatch |
Dict keys don't match |
Ensure type and index keys match exactly |
Duplicate callback outputs |
Same output in multiple callbacks |
Add allow_duplicate=True to additional callbacks |
Debug Tips
- Check browser console for JavaScript errors
- Use
debug=True in app.run() for detailed Python errors
- Print
ctx.triggered_id to see which input fired
- Validate JSON-serializable callback returns (no Python objects)
- Test with
prevent_initial_call=True to avoid startup errors
DMC v2.x Gotchas
DateTimePicker: Use timePickerProps not timeInputProps
Carousel: Embla options need {"containScroll": "trimSnaps"} wrapper
- Default
reuseTargetNode=True may cause Portal issues - set to False if overlays misbehave
- Use
MantineProvider not MantineProviderV2 (deprecated)
→ Full migration guide: references/migration-v2.md
1---2name: dmc-py-23description: Expert guidance for building Dash applications with Dash Mantine Components (DMC) v2.x. Use when creating dashboards, forms, data visualization apps with DMC. Covers: MantineProvider theming, style props (m, p, c, bg, w, h), Styles API, callbacks (basic, pattern-matching ALL/MATCH/ALLSMALLER, clientside, background), multi-page apps with Dash Pages, charts (LineChart, BarChart, DonutChart), date pickers, modals, and all 100+ components. Triggers on: dash-mantine-components, DMC, MantineProvider, dmc.Button, dmc.Select, dmc.Modal, dmc.BarChart, Mantine theme, Dash UI components, Dash callbacks, multi-page Dash app, pattern-matching callbacks, clientside callbacks, AppShell.4---56# Dash Mantine Components (DMC) v2.x78Build modern Dash applications with 100+ Mantine UI components.910## Quick Start1112Minimal DMC app requiring MantineProvider wrapper:1314```python15from dash import Dash, callback, Input, Output16import dash_mantine_components as dmc1718app = Dash(__name__)1920app.layout = dmc.MantineProvider([21 dmc.Container([22 dmc.Title("My DMC App", order=1),23 dmc.TextInput(label="Name", id="name-input", placeholder="Enter name"),24 dmc.Button("Submit", id="submit-btn", mt="md"),25 dmc.Text(id="output", mt="md"),26 ], size="sm", py="xl")27])2829@callback(Output("output", "children"), Input("submit-btn", "n_clicks"), Input("name-input", "value"))30def update_output(n_clicks, name):31 if not n_clicks:32 return ""33 return f"Hello, {name or 'World'}!"3435if __name__ == "__main__":36 app.run(debug=True)37```3839**Critical**: All DMC components MUST be inside `dmc.MantineProvider`.4041> **Version Note:** This skill targets DMC 2.x (Mantine 8.x). Run `pip show dash-mantine-components` to check your installed version. For the latest features and API changes, use `fetch_docs.py` to query the official documentation at https://www.dash-mantine-components.com/assets/llms.txt4243---4445## Workflow Decision Tree4647Select components by use case:4849### Form Inputs50| Need | Component | Key Props |51|------|-----------|-----------|52| Text input | `TextInput` | `label`, `placeholder`, `value`, `debounce` |53| Dropdown | `Select` | `data`, `value`, `searchable`, `clearable` |54| Multi-select | `MultiSelect` | `data`, `value`, `searchable` |55| Checkbox | `Checkbox` | `label`, `checked` |56| Toggle | `Switch` | `label`, `checked`, `onLabel`, `offLabel` |57| Number | `NumberInput` | `value`, `min`, `max`, `step` |58| Date | `DatePickerInput` | `value`, `type`, `minDate`, `maxDate` |59| Rich text | `Textarea` | `label`, `value`, `autosize`, `minRows` |60| File upload | `FileInput` | `value`, `accept`, `multiple` |6162### Layout63| Need | Component | Key Props |64|------|-----------|-----------|65| Content wrapper | `Container` | `size`, `px`, `py` |66| Vertical stack | `Stack` | `gap`, `align`, `justify` |67| Horizontal row | `Group` | `gap`, `justify`, `wrap` |68| CSS Grid | `Grid`, `GridCol` | `columns`, `gutter`, `span` |69| Full app shell | `AppShell` | `header`, `navbar`, `aside`, `footer` |70| Card container | `Card` | `shadow`, `padding`, `radius`, `withBorder` |71| Flex layout | `Flex` | `direction`, `wrap`, `gap`, `align` |7273### Navigation74| Need | Component | Key Props |75|------|-----------|-----------|76| Nav item | `NavLink` | `label`, `href`, `active`, `leftSection` |77| Tabs | `Tabs`, `TabsList`, `TabsPanel` | `value`, `orientation` |78| Breadcrumb | `Breadcrumbs` | `separator` |79| Stepper | `Stepper`, `StepperStep` | `active`, `onStepClick` |80| Pagination | `Pagination` | `value`, `total`, `siblings` |81| Table of contents | `TableOfContents` | `links`, `variant`, `active` |8283### Feedback & Overlays84| Need | Component | Key Props |85|------|-----------|-----------|86| Modal dialog | `Modal` | `opened`, `onClose`, `title`, `centered` |87| Side panel | `Drawer` | `opened`, `onClose`, `position`, `size` |88| Toast | `Notification` | `title`, `message`, `color`, `icon` |89| Alert banner | `Alert` | `title`, `color`, `variant`, `icon` |90| Loading | `Loader`, `LoadingOverlay` | `size`, `type`, `visible` |91| Progress | `Progress`, `RingProgress` | `value`, `size`, `sections` |92| Tooltip | `Tooltip` | `label`, `position`, `withArrow` |93| Copy button | `CopyButton` | `value`, `timeout` |9495### Data Display96| Need | Component | Key Props |97|------|-----------|-----------|98| Data table | `Table` | `data`, `striped`, `highlightOnHover` |99| Accordion | `Accordion`, `AccordionItem` | `value`, `multiple`, `variant` |100| Timeline | `Timeline`, `TimelineItem` | `active`, `bulletSize` |101| Badge | `Badge` | `color`, `variant`, `size` |102103### Charts104| Need | Component | Key Props |105|------|-----------|-----------|106| Line | `LineChart` | `data`, `dataKey`, `series` |107| Bar | `BarChart` | `data`, `dataKey`, `series`, `orientation` |108| Area | `AreaChart` | `data`, `dataKey`, `series` |109| Pie/Donut | `DonutChart`, `PieChart` | `data`, `chartLabel` |110| Scatter | `ScatterChart` | `data`, `dataKey`, `series` |111112### What's New in Recent Versions113114**v2.5.x:**115- `TableOfContents` - Auto-generated table of contents from headings116- `selectFirstOptionOnDropdownOpen` prop for Select/MultiSelect/Autocomplete117- `openOnFocus` prop for Combobox components118- AppShell `mode="static"` for nested shells119- `window.MantineCore` / `window.MantineHooks` for custom component building120121**v2.4.x:**122- `CopyButton` / `CustomCopyButton` - Clipboard operations123- `getEditor(id)` - Access RichTextEditor TipTap instance in clientside callbacks124- Function props for chart axis/grid customization125126**v2.3.x:**127- `MiniCalendar` - Compact calendar component128- `ScrollAreaAutoheight` - Auto-sizing scroll area129- `DirectionProvider` - RTL text direction support130131→ Full component reference: [references/components-quick-ref.md](references/components-quick-ref.md)132133---134135## Core Patterns136137### Theming138139Configure theme via MantineProvider:140141```python142theme = {143 "primaryColor": "blue",144 "fontFamily": "Inter, sans-serif",145 "defaultRadius": "md",146 "colors": {147 "brand": ["#f0f9ff", "#e0f2fe", "#bae6fd", "#7dd3fc", "#38bdf8",148 "#0ea5e9", "#0284c7", "#0369a1", "#075985", "#0c4a6e"]149 },150 "components": {151 "Button": {"defaultProps": {"size": "md", "radius": "md"}},152 "TextInput": {"defaultProps": {"size": "sm"}},153 }154}155156app.layout = dmc.MantineProvider(157 theme=theme,158 forceColorScheme="light", # or "dark", or None for auto159 children=[...]160)161```162163**Theme Toggle Pattern** (clientside callback):164165```python166from dash import clientside_callback, ClientsideFunction167168app.layout = dmc.MantineProvider(169 id="mantine-provider",170 children=[171 dcc.Store(id="theme-store", storage_type="local", data="light"),172 dmc.Switch(id="theme-switch", label="Dark mode", checked=False),173 # ... rest of layout174 ]175)176177clientside_callback(178 """(checked) => checked ? "dark" : "light" """,179 Output("mantine-provider", "forceColorScheme"),180 Input("theme-switch", "checked"),181)182```183184→ Full theming guide: [references/theming-patterns.md](references/theming-patterns.md)185186### Styling187188**Style Props** - Universal props on all DMC components:189190| Prop | CSS Property | Values |191|------|--------------|--------|192| `m`, `mt`, `mb`, `ml`, `mr`, `mx`, `my` | margin | `xs`, `sm`, `md`, `lg`, `xl` or number (px) |193| `p`, `pt`, `pb`, `pl`, `pr`, `px`, `py` | padding | same as margin |194| `c` | color | `"blue"`, `"red.6"`, `"dimmed"`, `"var(--mantine-color-text)"` |195| `bg` | background | same as color |196| `w`, `h` | width, height | `"100%"`, `"50vw"`, number (px) |197| `maw`, `mah`, `miw`, `mih` | max/min width/height | same as w, h |198| `fw` | font-weight | `400`, `500`, `700` |199| `fz` | font-size | `xs`, `sm`, `md`, `lg`, `xl` or number |200| `ta` | text-align | `"left"`, `"center"`, `"right"` |201| `td` | text-decoration | `"underline"`, `"line-through"` |202203**Responsive Values** - Dict with breakpoints:204205```python206dmc.Button("Click", w={"base": "100%", "sm": "auto", "lg": 200})207dmc.Stack(gap={"base": "xs", "md": "lg"})208```209210**Styles API** - Target nested elements:211212```python213dmc.Select(214 data=["A", "B", "C"],215 classNames={"input": "my-input", "dropdown": "my-dropdown"},216 styles={"label": {"fontWeight": 700}, "input": {"borderColor": "blue"}},217)218```219220→ Full styling guide: [references/styling-guide.md](references/styling-guide.md)221222### Callbacks223224**Basic Pattern**:225226```python227from dash import callback, Input, Output, State228229@callback(230 Output("output", "children"),231 Input("button", "n_clicks"),232 State("input", "value"),233 prevent_initial_call=True,234)235def update(n_clicks, value):236 return f"Clicked {n_clicks} times with value: {value}"237```238239**Pattern-Matching** (dynamic components):240241```python242from dash import ALL, MATCH, callback_context as ctx243244# ALL: Respond to any button with type "dynamic-btn"245@callback(246 Output("output", "children"),247 Input({"type": "dynamic-btn", "index": ALL}, "n_clicks"),248)249def handle_all(n_clicks_list):250 triggered = ctx.triggered_id # {"type": "dynamic-btn", "index": X}251 return f"Button {triggered['index']} clicked"252253# MATCH: Update the output matching the triggered input254@callback(255 Output({"type": "item-output", "index": MATCH}, "children"),256 Input({"type": "item-btn", "index": MATCH}, "n_clicks"),257 prevent_initial_call=True,258)259def handle_match(n):260 return f"Clicked {n} times"261```262263**Clientside Callback** (browser-side JavaScript):264265```python266from dash import clientside_callback267268clientside_callback(269 """(n) => n ? `Clicked ${n} times` : "Not clicked" """,270 Output("output", "children"),271 Input("button", "n_clicks"),272)273```274275**DMC-Specific Props**:276- `debounce=300` - Delay callback trigger (ms) for TextInput, Textarea277- `persistence=True` - Persist value across page reloads278- `persistence_type="local"` - Storage type: memory, local, session279280→ Full callbacks reference: [references/callbacks-advanced.md](references/callbacks-advanced.md)281282---283284## Multi-Page Apps285286Use Dash Pages with DMC AppShell:287288```python289# app.py290import dash291from dash import Dash292import dash_mantine_components as dmc293294app = Dash(__name__, use_pages=True, pages_folder="pages")295296app.layout = dmc.MantineProvider([297 dmc.AppShell(298 [299 dmc.AppShellHeader(dmc.Group([300 dmc.Title("My App", order=3),301 dmc.Switch(id="theme-switch"),302 ], h="100%", px="md")),303 dmc.AppShellNavbar([304 dmc.NavLink(label=page["name"], href=page["path"], active=page["path"] == "/")305 for page in dash.page_registry.values()306 ], p="md"),307 dmc.AppShellMain(dash.page_container),308 ],309 header={"height": 60},310 navbar={"width": 250, "breakpoint": "sm", "collapsed": {"mobile": True}},311 padding="md",312 )313])314315if __name__ == "__main__":316 app.run(debug=True)317```318319```python320# pages/home.py321import dash322import dash_mantine_components as dmc323324dash.register_page(__name__, path="/", name="Home")325326layout = dmc.Container([327 dmc.Title("Welcome", order=2),328 dmc.Text("Home page content"),329], py="xl")330```331332```python333# pages/analytics.py334import dash335import dash_mantine_components as dmc336337dash.register_page(__name__, path="/analytics", name="Analytics")338339layout = dmc.Container([340 dmc.Title("Analytics", order=2),341 # Charts, tables, etc.342], py="xl")343```344345**Variable Paths**:346347```python348# pages/user.py349dash.register_page(__name__, path_template="/user/<user_id>")350351def layout(user_id=None):352 return dmc.Container([353 dmc.Title(f"User: {user_id}", order=2),354 ])355```356357→ Full multi-page guide: [references/multi-page-apps.md](references/multi-page-apps.md)358359---360361## Component Categories362363Quick links to reference documentation:364365| Category | Components | Reference |366|----------|------------|-----------|367| **All Components** | 90+ components with props/events | [components-quick-ref.md](references/components-quick-ref.md) |368| **Theming** | MantineProvider, theme object, colors | [theming-patterns.md](references/theming-patterns.md) |369| **Styling** | Style props, Styles API, CSS variables | [styling-guide.md](references/styling-guide.md) |370| **Callbacks** | Pattern-matching, clientside, background | [callbacks-advanced.md](references/callbacks-advanced.md) |371| **Multi-Page** | Dash Pages, routing, AppShell | [multi-page-apps.md](references/multi-page-apps.md) |372| **Charts** | Data formats, series config | [charts-data-formats.md](references/charts-data-formats.md) |373| **Date Pickers** | DatePicker, DatesProvider, localization | [date-pickers-guide.md](references/date-pickers-guide.md) |374| **Dash Core** | dcc.Store, caching, performance | [dash-fundamentals.md](references/dash-fundamentals.md) |375| **Migration** | v1.x to v2.x breaking changes | [migration-v2.md](references/migration-v2.md) |376377### Asset Templates378379Copy and adapt these templates:380381| Template | Description |382|----------|-------------|383| [app_single_page.py](assets/app_single_page.py) | Complete single-page DMC app with theme toggle |384| [app_multi_page.py](assets/app_multi_page.py) | Multi-page app with Dash Pages and AppShell |385| [callbacks_patterns.py](assets/callbacks_patterns.py) | All callback pattern examples |386| [theme_presets.py](assets/theme_presets.py) | Pre-built theme configurations |387388### Utility Scripts389390| Script | Usage |391|--------|-------|392| [fetch_docs.py](scripts/fetch_docs.py) | `python fetch_docs.py "Select"` - Fetch/search official llms.txt |393| [scaffold_app.py](scripts/scaffold_app.py) | `python scaffold_app.py myapp --type multi --shell` |394| [generate_theme.py](scripts/generate_theme.py) | `python generate_theme.py --primary "#0ea5e9"` |395| [component_search.py](scripts/component_search.py) | `python component_search.py "select"` |396397---398399## Common Tasks400401### Form with Validation402403```python404@callback(405 Output("submit-btn", "disabled"),406 Output("error-text", "children"),407 Input("email-input", "value"),408 Input("password-input", "value"),409)410def validate_form(email, password):411 errors = []412 if not email or "@" not in email:413 errors.append("Valid email required")414 if not password or len(password) < 8:415 errors.append("Password must be 8+ characters")416 return bool(errors), ", ".join(errors)417```418419### Modal Open/Close420421```python422app.layout = dmc.MantineProvider([423 dmc.Button("Open Modal", id="open-modal-btn"),424 dmc.Modal(425 id="my-modal",426 title="Confirm Action",427 children=[428 dmc.Text("Are you sure?"),429 dmc.Group([430 dmc.Button("Cancel", id="cancel-btn", variant="outline"),431 dmc.Button("Confirm", id="confirm-btn", color="red"),432 ], justify="flex-end", mt="md"),433 ],434 ),435])436437@callback(438 Output("my-modal", "opened"),439 Input("open-modal-btn", "n_clicks"),440 Input("cancel-btn", "n_clicks"),441 Input("confirm-btn", "n_clicks"),442 prevent_initial_call=True,443)444def toggle_modal(open_clicks, cancel, confirm):445 from dash import ctx446 if ctx.triggered_id == "open-modal-btn":447 return True448 return False449```450451### Loading State452453```python454from dash import dcc455456app.layout = dmc.MantineProvider([457 dmc.Button("Load Data", id="load-btn"),458 dcc.Loading(459 id="loading",460 type="circle",461 children=dmc.Container(id="data-container"),462 ),463])464465@callback(Output("data-container", "children"), Input("load-btn", "n_clicks"))466def load_data(n):467 import time468 time.sleep(2) # Simulate slow operation469 return dmc.Text("Data loaded!")470```471472### Chart with Data473474```python475data = [476 {"month": "Jan", "sales": 100, "profit": 20},477 {"month": "Feb", "sales": 150, "profit": 35},478 {"month": "Mar", "sales": 120, "profit": 25},479]480481dmc.BarChart(482 data=data,483 dataKey="month",484 series=[485 {"name": "sales", "color": "blue.6"},486 {"name": "profit", "color": "green.6"},487 ],488 h=300,489 withLegend=True,490 withTooltip=True,491)492```493494---495496## Troubleshooting497498### Common Errors499500| Error | Cause | Fix |501|-------|-------|-----|502| `MantineProvider is required` | Component outside provider | Wrap entire layout in `dmc.MantineProvider([...])` |503| `Invalid theme color` | Color not in theme | Use built-in colors (`blue`, `red`) or add to `theme["colors"]` |504| `Callback output not found` | Component not in layout | Ensure component with ID exists in layout |505| `Circular callback detected` | Output also used as Input | Use `State` instead of `Input` for non-triggering values |506| `Pattern-matching ID mismatch` | Dict keys don't match | Ensure `type` and `index` keys match exactly |507| `Duplicate callback outputs` | Same output in multiple callbacks | Add `allow_duplicate=True` to additional callbacks |508509### Debug Tips5105111. **Check browser console** for JavaScript errors5122. **Use `debug=True`** in `app.run()` for detailed Python errors5133. **Print `ctx.triggered_id`** to see which input fired5144. **Validate JSON-serializable** callback returns (no Python objects)5155. **Test with `prevent_initial_call=True`** to avoid startup errors516517### DMC v2.x Gotchas518519- `DateTimePicker`: Use `timePickerProps` not `timeInputProps`520- `Carousel`: Embla options need `{"containScroll": "trimSnaps"}` wrapper521- Default `reuseTargetNode=True` may cause Portal issues - set to `False` if overlays misbehave522- Use `MantineProvider` not `MantineProviderV2` (deprecated)523524→ Full migration guide: [references/migration-v2.md](references/migration-v2.md)