dmc-py

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.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "dmc-py" with this command: npx skills add bjornmelin/dev-skills/bjornmelin-dev-skills-dmc-py

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

NeedComponentKey Props
Text inputTextInputlabel, placeholder, value, debounce
DropdownSelectdata, value, searchable, clearable
Multi-selectMultiSelectdata, value, searchable
CheckboxCheckboxlabel, checked
ToggleSwitchlabel, checked, onLabel, offLabel
NumberNumberInputvalue, min, max, step
DateDatePickerInputvalue, type, minDate, maxDate
Rich textTextarealabel, value, autosize, minRows
File uploadFileInputvalue, accept, multiple

Layout

NeedComponentKey Props
Content wrapperContainersize, px, py
Vertical stackStackgap, align, justify
Horizontal rowGroupgap, justify, wrap
CSS GridGrid, GridColcolumns, gutter, span
Full app shellAppShellheader, navbar, aside, footer
Card containerCardshadow, padding, radius, withBorder
Flex layoutFlexdirection, wrap, gap, align

Navigation

NeedComponentKey Props
Nav itemNavLinklabel, href, active, leftSection
TabsTabs, TabsList, TabsPanelvalue, orientation
BreadcrumbBreadcrumbsseparator
StepperStepper, StepperStepactive, onStepClick
PaginationPaginationvalue, total, siblings
Table of contentsTableOfContentslinks, variant, active

Feedback & Overlays

NeedComponentKey Props
Modal dialogModalopened, onClose, title, centered
Side panelDraweropened, onClose, position, size
ToastNotificationtitle, message, color, icon
Alert bannerAlerttitle, color, variant, icon
LoadingLoader, LoadingOverlaysize, type, visible
ProgressProgress, RingProgressvalue, size, sections
TooltipTooltiplabel, position, withArrow
Copy buttonCopyButtonvalue, timeout

Data Display

NeedComponentKey Props
Data tableTabledata, striped, highlightOnHover
AccordionAccordion, AccordionItemvalue, multiple, variant
TimelineTimeline, TimelineItemactive, bulletSize
BadgeBadgecolor, variant, size

Charts

NeedComponentKey Props
LineLineChartdata, dataKey, series
BarBarChartdata, dataKey, series, orientation
AreaAreaChartdata, dataKey, series
Pie/DonutDonutChart, PieChartdata, chartLabel
ScatterScatterChartdata, 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:

PropCSS PropertyValues
m, mt, mb, ml, mr, mx, mymarginxs, sm, md, lg, xl or number (px)
p, pt, pb, pl, pr, px, pypaddingsame as margin
ccolor"blue", "red.6", "dimmed", "var(--mantine-color-text)"
bgbackgroundsame as color
w, hwidth, height"100%", "50vw", number (px)
maw, mah, miw, mihmax/min width/heightsame as w, h
fwfont-weight400, 500, 700
fzfont-sizexs, sm, md, lg, xl or number
tatext-align"left", "center", "right"
tdtext-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:

CategoryComponentsReference
All Components90+ components with props/eventscomponents-quick-ref.md
ThemingMantineProvider, theme object, colorstheming-patterns.md
StylingStyle props, Styles API, CSS variablesstyling-guide.md
CallbacksPattern-matching, clientside, backgroundcallbacks-advanced.md
Multi-PageDash Pages, routing, AppShellmulti-page-apps.md
ChartsData formats, series configcharts-data-formats.md
Date PickersDatePicker, DatesProvider, localizationdate-pickers-guide.md
Dash Coredcc.Store, caching, performancedash-fundamentals.md
Migrationv1.x to v2.x breaking changesmigration-v2.md

Asset Templates

Copy and adapt these templates:

TemplateDescription
app_single_page.pyComplete single-page DMC app with theme toggle
app_multi_page.pyMulti-page app with Dash Pages and AppShell
callbacks_patterns.pyAll callback pattern examples
theme_presets.pyPre-built theme configurations

Utility Scripts

ScriptUsage
fetch_docs.pypython fetch_docs.py "Select" - Fetch/search official llms.txt
scaffold_app.pypython scaffold_app.py myapp --type multi --shell
generate_theme.pypython generate_theme.py --primary "#0ea5e9"
component_search.pypython 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

ErrorCauseFix
MantineProvider is requiredComponent outside providerWrap entire layout in dmc.MantineProvider([...])
Invalid theme colorColor not in themeUse built-in colors (blue, red) or add to theme["colors"]
Callback output not foundComponent not in layoutEnsure component with ID exists in layout
Circular callback detectedOutput also used as InputUse State instead of Input for non-triggering values
Pattern-matching ID mismatchDict keys don't matchEnsure type and index keys match exactly
Duplicate callback outputsSame output in multiple callbacksAdd allow_duplicate=True to additional callbacks

Debug Tips

  1. Check browser console for JavaScript errors
  2. Use debug=True in app.run() for detailed Python errors
  3. Print ctx.triggered_id to see which input fired
  4. Validate JSON-serializable callback returns (no Python objects)
  5. 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

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

streamdown

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

zod-v4

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

ai-sdk-core

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

notebook-ml-architect

No summary provided by upstream source.

Repository SourceNeeds Review
dmc-py | V50.AI