Claude-skill-registry dmc-py
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dmc-py" ~/.claude/skills/majiayu000-claude-skill-registry-dmc-py && rm -rf "$T"
skills/data/dmc-py/SKILL.mdDash Mantine Components (DMC) v2.4.0
Build modern Dash applications with 90+ 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.
Workflow Decision Tree
Select components by use case:
Form Inputs
| Need | Component | Key Props |
|---|---|---|
| Text input | | , , , |
| Dropdown | | , , , |
| Multi-select | | , , |
| Checkbox | | , |
| Toggle | | , , , |
| Number | | , , , |
| Date | | , , , |
| Rich text | | , , , |
| File upload | | , , |
Layout
| Need | Component | Key Props |
|---|---|---|
| Content wrapper | | , , |
| Vertical stack | | , , |
| Horizontal row | | , , |
| CSS Grid | , | , , |
| Full app shell | | , , , |
| Card container | | , , , |
| Flex layout | | , , , |
Navigation
| Need | Component | Key Props |
|---|---|---|
| Nav item | | , , , |
| Tabs | , , | , |
| Breadcrumb | | |
| Stepper | , | , |
| Pagination | | , , |
Feedback & Overlays
| Need | Component | Key Props |
|---|---|---|
| Modal dialog | | , , , |
| Side panel | | , , , |
| Toast | | , , , |
| Alert banner | | , , , |
| Loading | , | , , |
| Progress | , | , , |
| Tooltip | | , , |
Data Display
| Need | Component | Key Props |
|---|---|---|
| Data table | | , , |
| Accordion | , | , , |
| Timeline | , | , |
| Badge | | , , |
Charts
| Need | Component | Key Props |
|---|---|---|
| Line | | , , |
| Bar | | , , , |
| Area | | , , |
| Pie/Donut | , | , |
| Scatter | | , , |
→ 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 |
|---|---|---|
, , , , , , | margin | , , , , or number (px) |
, , , , , , | padding | same as margin |
| color | , , , |
| background | same as color |
, | width, height | , , number (px) |
, , , | max/min width/height | same as w, h |
| font-weight | , , |
| font-size | , , , , or number |
| text-align | , , |
| text-decoration | , |
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:
- Delay callback trigger (ms) for TextInput, Textareadebounce=300
- Persist value across page reloadspersistence=True
- Storage type: memory, local, sessionpersistence_type="local"
→ 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 |
|---|---|
| scaffold_app.py | |
| generate_theme.py | |
| component_search.py | |
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 |
|---|---|---|
| Component outside provider | Wrap entire layout in |
| Color not in theme | Use built-in colors (, ) or add to |
| Component not in layout | Ensure component with ID exists in layout |
| Output also used as Input | Use instead of for non-triggering values |
| Dict keys don't match | Ensure and keys match exactly |
| Same output in multiple callbacks | Add to additional callbacks |
Debug Tips
- Check browser console for JavaScript errors
- Use
indebug=True
for detailed Python errorsapp.run() - Print
to see which input firedctx.triggered_id - Validate JSON-serializable callback returns (no Python objects)
- Test with
to avoid startup errorsprevent_initial_call=True
DMC v2.x Gotchas
: UseDateTimePicker
nottimePickerPropstimeInputProps
: Embla options needCarousel
wrapper{"containScroll": "trimSnaps"}- Default
may cause Portal issues - set toreuseTargetNode=True
if overlays misbehaveFalse - Use
notMantineProvider
(deprecated)MantineProviderV2
→ Full migration guide: references/migration-v2.md