## Version 3.0.0 Release announcement for Dash Mantine Components v3.0.0 Category: Releases Oct 30, 2026 Based on Mantine 9.7.4 See the full [Changelog](https://github.com/snehilvj/dash-mantine-components/releases/tag/3.0.0) DMC v3 is based on Mantine v9 and introduces new components, features, and improvements. ### Highlights - New [Marquee](/components/marquee) component for scrolling content. - New [Splitter](/components/splitter) component for resizable split pane layout. - Over 100 new props and enhancements across the component library. - [Notification](/components/notification) now support swipe dismissal, auto-close progress, stacked layout, and priority: - Reorderable pills in [MultiSelect](/components/multiselect) and [TagsInput](/components/tagsinput), with drag-and-drop and keyboard support. - New chart features, including brush selection, streamgraphs, and reference markers. - Expanded date and time inputs, including range selection and durations over 24 hours. - Input loading and success states, [RichTextEditor](/components/richtexteditor) table controls, and improved notifications and dropdown positioning. - Improved responsive style performance. ### Migration Guide DMC v3 is based on Mantine v9 and includes some breaking changes. See the [Migration Guide](/migration) for instructions on updating your apps. See the Mantine v9 changelogs for details of upstream changes: [9.0](https://mantine.dev/changelog/9-0-0/), [9.1](https://mantine.dev/changelog/9-1-0/), [9.2](https://mantine.dev/changelog/9-2-0/), [9.3](https://mantine.dev/changelog/9-3-0/), [9.4](https://mantine.dev/changelog/9-4-0/), [9.5](https://mantine.dev/changelog/9-5-0/), [9.6](https://mantine.dev/changelog/9-6-0/), and [9.7](https://mantine.dev/changelog/9-7-0/). ### Requirements **DMC v3 requires Dash >= 4.5 and React 19.** Set the React version in your app: ```python import dash dash._dash_renderer._set_react_version("19.2.4") app = Dash() ``` Alternatively, set the environment variable: ```bash REACT_VERSION=19.2.4 python app.py ``` ### New Components #### New Marquee component [Marquee](/components/marquee) adds continuous scrolling animation for content. Marquee supports customizable scrolling direction, speed, and spacing between items, with options to pause the animation on hover and control how content repeats. It can display a single row or multiple rows scrolling in alternating directions. Thanks [@budescode](https://github.com/budescode) for adding this component ```python import dash_mantine_components as dmc marquee_content = [ dmc.Badge("Python", color="red", variant="light", w=80), dmc.Badge("Plotly", color="blue", variant="light", w=80), dmc.Badge("Dash", color="violet", variant="light", w=80), dmc.Badge("Mantine", color="yellow", variant="light", w=80), dmc.Badge("React", color="teal", variant="light", w=80), ] component = dmc.Stack([ dmc.Marquee(marquee_content), dmc.Marquee(marquee_content, reverse=True), ]) ``` #### New Splitter component [Splitter](/components/splitter) lets users resize panels by dragging the divider between them. You can create layouts with side-by-side panels or stacked sections, with adjustable sizes and min or max size constraints. It’s useful for dashboards where users need to control how much space is available for different views. Thanks [@datenzauberai](https://github.com/datenzauberai) for adding this component ```python import dash_mantine_components as dmc from dash import Input, Output, State, callback component = dmc.Box([ dmc.Splitter( id="splitter-collapse", h=200, classNames={"pane": "splitter-examples"}, children=[ dmc.SplitterPane( "Collapsible sidebar", collapsible=True, defaultSize=30, min=20, bg="blue", ), dmc.SplitterPane( "Main content", defaultSize=70, min=30, bg="teal", ), ], ), dmc.Button("Toggle Sidebar", id="splitter-collapse-toggle-button", mt="md") ]) @callback( Output("splitter-collapse", "collapsed"), Input("splitter-collapse-toggle-button", "n_clicks"), State("splitter-collapse", "collapsed"), prevent_initial_call=True, ) def toggle_sidebar(n_clicks, collapsed): return [0] if not collapsed or 0 not in collapsed else [] ``` ### New Features ### Layout #### Collapse horizontal orientation [Collapse](/components/collapse) now supports horizontal orientation. ```python from dash import callback, Input, Output import dash_mantine_components as dmc component = dmc.Box([ dmc.Button("Toggle Content", id="collapse-horizontal-btn", n_clicks=0), dmc.Collapse( children=dmc.Text("Hello World!", my="lg", w=200, bg="blue.3", c="white", p="lg"), orientation="horizontal", opened=False, id="collapse-horizontal" ) ], h=120) @callback( Output("collapse-horizontal", "opened"), Input("collapse-horizontal-btn", "n_clicks"), ) def update(n): if n % 2 == 0: return False return True ``` #### Card horizontal orientation [Card](/components/card) now supports horizontal orientation. ```python import dash_mantine_components as dmc completed = 1887 total = 2334 stats = [ {"value": 447, "label": "Remaining"}, {"value": 76, "label": "In progress"}, ] items = [ dmc.Box([ dmc.Text(stat["value"]), dmc.Text(stat["label"], size="xs", c="dimmed"), ]) for stat in stats ] component = dmc.Card( [ dmc.CardSection( dmc.RingProgress( roundCaps=True, thickness=6, size=150, sections=[ { "value": (completed / total) * 100, "color": "blue", } ], label=dmc.Box([ dmc.Text( f"{((completed / total) * 100):.0f}%", ta="center", fz="lg", ), dmc.Text( "Completed", ta="center", fz="xs", c="dimmed", ), ]), ), inheritPadding=True, px="xs", withBorder=True, ), dmc.CardSection( [ dmc.Text("Project tasks", fz="xl"), dmc.Box( [ dmc.Text("1887"), dmc.Text("Completed", fz="xs", c="dimmed"), ], mt="xs", ), dmc.Group(items, mt="sm"), ], inheritPadding=True, px="md", withBorder=True, ml="lg" ), ], padding="sm", withBorder=True, orientation="horizontal", w=400 ) ``` #### Grid improvements [Grid](/components/grid) now uses CSS `gap` instead of negative margins for column spacing. This removes the need for `overflow="hidden"` to prevent overflow caused by negative margins. The `gutter` prop has been renamed to `gap`. New `rowGap` and `columnGap` props control spacing independently, and `GridCol` now supports `align` for vertical alignment. #### SimpleGrid automatic columns [SimpleGrid](/components/simplegrid) now supports `minColWidth` to automatically adjust the number of columns based on available width. When set, `cols` is ignored. Use `autoFlow` to choose between `auto-fill` and `auto-fit`. ```python import dash_mantine_components as dmc from dash import html style = { "border": "1px solid var(--mantine-primary-color-filled)", "textAlign": "center", } component = dmc.SimpleGrid( minColWidth="200px", children=[ html.Div("1", style=style), html.Div("2", style=style), html.Div("3", style=style), html.Div("4", style=style), html.Div("5", style=style), ], ) ``` #### AppShell static mode [AppShell](/components/appshell) now supports `mode="static"`, which places its elements in the normal document flow using CSS Grid instead of fixed positioning. The `layout="alt"` option places the navbar and aside at full height, with the header and footer adjusted between them. #### ScrollArea initial position [ScrollArea](/components/scrollarea) now supports `startScrollPosition` to set the initial scroll position when mounted. ```python import dash_mantine_components as dmc from docs.scrollarea.text import text component = dmc.Center( dmc.ScrollArea( h=200, w=350, startScrollPosition={ "y": 250}, children=dmc.Paper( [dmc.Title("Charizard (Pokémon)", order=3), dmc.Text(text)], w=600 ), ), ) ``` #### ScrollArea scrollbar position [ScrollArea](/components/scrollarea) now supports `verticalScrollbarPosition` to pin the scrollbar to the left or right side regardless of text direction. ### Inputs #### Input loading state All input components based on `Input` now support `loading` and `loadingPosition` props to display a loading indicator on either side of the input. ```python import dash_mantine_components as dmc from dash_iconify import DashIconify component = dmc.TextInput( label="Your Email", w=200, placeholder="Enter Your Email", loading=True ) ``` #### Input success state Inputs based on `Input` and `Input.Wrapper` now support a `success` prop. It changes the input border color and can display a success message below it. When both `error` and `success` are set, `error` takes precedence. A new `--mantine-color-success` CSS variable resolves to `teal-6` in light mode and `teal-8` in dark mode. ```python import dash_mantine_components as dmc component = dmc.Stack( [ dmc.TextInput( label="Success as boolean", placeholder="Success as boolean", success=True, ), dmc.TextInput( label="Success as React node", placeholder="Success as React node", success="Username is available", ), ], ) ``` #### Shared default props Default props set on `Input` and [InputWrapper](/components/inputwrapper) in `theme.components` now cascade to derived components. This lets you configure shared properties such as `size`, `radius`, `variant`, and `withAsterisk` for all inputs, while retaining component-specific overrides. #### CheckboxGroup selection limit `CheckboxGroup` now supports `maxSelectedValues` to limit the number of selected values. Remaining options are disabled when the limit is reached. ```python import dash_mantine_components as dmc from dash import html, Output, Input, callback component = html.Div( [ dmc.CheckboxGroup( id="checkbox-group-max", label="Select your favorite library", description="This is anonymous", withAsterisk=True, mb=10, children=dmc.Group( [ dmc.Checkbox(label="Pandas", value="pandas"), dmc.Checkbox(label="Polars", value="polars"), dmc.Checkbox(label="Vaex", value="vaex"), dmc.Checkbox(label="Dask", value="dask"), ], mt=10, ), value=["pandas", "polars"], maxSelectedValues=2 ), dmc.Text(id="checkbox-group-max-output"), ] ) @callback(Output("checkbox-group--max-output", "children"), Input("checkbox-group-max", "value")) def checkbox(value): return ", ".join(value) if value else None ``` #### Radio and Checkbox light variant [Checkbox](/components/checkbox) and `Radio` now support `variant="light"`. Checked and indeterminate states have a light background and a contrasting icon. ```python import dash_mantine_components as dmc component = dmc.Stack( [ dmc.Checkbox( variant="light", checked=True, label="Light checkbox", ), dmc.Checkbox( variant="light", indeterminate=True, label="Light indeterminate checkbox", ), dmc.Checkbox( variant="light", color="teal", checked=True, label="Teal light checkbox", ), dmc.Checkbox( variant="light", color="grape", checked=True, label="Grape light checkbox", ), dmc.Checkbox( variant="light", color="#e64980", checked=True, label="Light checkbox with CSS color", ), ], gap=7, ) ``` #### Textarea bottomSection [Textarea](/components/textarea) now supports `bottomSection` to display content inside the bottom of the input border, such as a character counter. ```python import dash_mantine_components as dmc from dash import Input, Output, clientside_callback component = dmc.Textarea( id="textarea-bottom-section", autosize=True, minRows=3, label="Message", bottomSection=dmc.Text( id="char-count", size="xs", c="dimmed", ), ) clientside_callback( """ function(value) { const length = (value || "").length; return `${length}/500 characters`; } """, Output("char-count", "children"), Input("textarea-bottom-section", "value"), ) ``` #### RichTextEditor table controls [RichTextEditor](/components/richtexteditor) now includes toolbar controls for inserting and editing tables. You can insert tables of a selected size, add or remove rows and columns, toggle header rows and columns, and merge or split cells. Table controls are disabled when the cursor is outside a table. ```python import dash_mantine_components as dmc table = """

Name

Role

Department

Alex Morgan

Developer

Engineering

Jamie Lee

Designer

Design

""" component = dmc.RichTextEditor( html=table, toolbar={ "controlsGroups": [ ["Bold", "Italic", "Underline"], ["TableInsert", "TableDelete"], ["TableColumnBefore", "TableColumnAfter", "TableColumnDelete"], ["TableRowBefore", "TableRowAfter", "TableRowDelete"], [ "TableToggleHeaderRow", "TableToggleHeaderColumn", "TableMergeCells", "TableSplitCell", ], ], }, ) ``` #### NumberInput selectAllOnFocus [NumberInput](/components/numberinput) now supports `selectAllOnFocus` to select all text when the input receives focus. ```python import dash_mantine_components as dmc component = dmc.NumberInput(value=123456, selectAllOnFocus=True) ``` #### Slider improvements [Slider](/components/slider) and `RangeSlider` now support vertical orientation. ```python import dash_mantine_components as dmc marks = [ {"value": 20, "label": "20%"}, {"value": 50, "label": "50%"}, {"value": 80, "label": "80%"}, ] component = dmc.Group( [ dmc.Slider( orientation="vertical", value=45, marks=marks, ), dmc.RangeSlider( orientation="vertical", value=[25, 65], marks=marks, ), ], gap=60, ) ``` `Slider` also supports hidden marks for snapping to specific values without displaying marks on the track. Use `restrictToMarks` to enable this behavior. ```python from dash import Input, Output, callback import dash_mantine_components as dmc marks = [ {"value": 0, "label": "0%"}, {"value": 25, "hidden": True}, {"value": 50, "label": "50%"}, {"value": 75, "hidden": True}, {"value": 100, "label": "100%"}, ] component = dmc.Stack( [ dmc.Text( id="hidden-marks-slider-value", size="sm", children="Hidden marks allow you to snap to specific values " "without displaying them visually. Current value: 50", ), dmc.Slider( id="hidden-marks-slider", value=50, min=0, max=100, step=1, restrictToMarks=True, marks=marks, ), ], ) @callback( Output("hidden-marks-slider-value", "children"), Input("hidden-marks-slider", "value"), ) def update_value(value): return ( "Hidden marks allow you to snap to specific values without displaying " f"them visually. Current value: {value}" ) ``` The new `startPointValue` prop sets the origin of the filled bar, which extends toward the current value. ```python import dash_mantine_components as dmc component = dmc.Slider( startPointValue=0, updatemode="drag", min=-100, max=100, value=40, marks=[ {"value": -100, "label": "-100"}, {"value": -50, "label": "-50"}, {"value": 0, "label": "0"}, {"value": 50, "label": "50"}, {"value": 100, "label": "100"}, ], ) ``` #### Rating allowClear [Rating](/components/rating) now supports `allowClear` to reset the rating to zero by clicking the selected value again. ```python from dash import Input, Output, callback import dash_mantine_components as dmc component = dmc.Stack( [ dmc.Text("Click the same star to clear the rating", size="sm"), dmc.Rating(id="rating-clear", value=3, allowClear=True), dmc.Group( [ dmc.Text("Current rating:", size="sm", c="dimmed"), dmc.Text(id="rating-clear-value", size="sm", fw=600, children="3"), ], gap="xs", ), ], gap="md", align="center", ) @callback( Output("rating-clear-value", "children"), Input("rating-clear", "value"), ) def update_rating(value): return "Not rated" if value == 0 else value ``` ### Combobox #### Reorder selected pills [MultiSelect](/components/multiselect) and [TagsInput](/components/tagsinput) now support `withPillsReorder` to reorder selected pills using drag-and-drop or the keyboard. Use the arrow keys to move focus between pills. Press `Alt + ArrowLeft` or `Alt + ArrowRight` to reorder the focused pill. Focus follows the moved pill, allowing multiple moves without refocusing. Reordering is disabled when `disabled` or `readOnly` is set. ```python import dash_mantine_components as dmc component = dmc.MultiSelect( label="Select your favorite superpowers", description="Drag pills to put them in order of preference.", data=["Teleport", "Time Travel", "Fly", "Invisibility", "Mind Reading"], value=["Teleport", "Time Travel", "Fly", "Invisibility", "Mind Reading"], withPillsReorder=True, ) ``` #### Custom pills [MultiSelect](/components/multiselect) and [TagsInput](/components/tagsinput) now support `renderPill` to customize how selected pills are rendered. ```python import dash_mantine_components as dmc from dash import Input, Output, callback users = [ { "value": "Emily Johnson", "label": "Emily Johnson", "image": "https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-7.png", }, { "value": "Ava Rodriguez", "label": "Ava Rodriguez", "image": "https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-8.png", }, { "value": "Olivia Chen", "label": "Olivia Chen", "image": "https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-4.png", }, { "value": "Ethan Barnes", "label": "Ethan Barnes", "image": "https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-1.png", }, { "value": "Mason Taylor", "label": "Mason Taylor", "image": "https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-2.png", }, ] component = dmc.Box([ dmc.MultiSelect( id="multi-select-render-pill", data=users, label="Candidates", placeholder="Select candidates", value=["Emily Johnson", "Ava Rodriguez"], renderPill={ "function": "renderUserPill", "options": {"users": users}}, ), dmc.Text(id="multi-select-render-pill-val") ]) @callback( Output("multi-select-render-pill-val", "children"), Input("multi-select-render-pill", "value"), ) def update(value): return f"You selected {value}" ``` ```javascript var dmcfuncs = window.dashMantineFunctions = window.dashMantineFunctions || {}; var dmc = window.dash_mantine_components; dmcfuncs.renderUserPill = function ({ option, onRemove }, { users }) { const usersMap = new Map( users.map((user) => [user.value.toString(), user]) ); const user = usersMap.get(option?.value.toString()); return React.createElement( dmc.Pill, { withRemoveButton: true, onRemove: onRemove, }, React.createElement( "div", { style: { display: "flex", alignItems: "center", gap: 8, }, }, React.createElement(dmc.Avatar, { src: user?.image, size: 16, }), option?.label ) ); }; ``` #### Number and boolean values [Select](/components/select), [MultiSelect](/components/multiselect), [SegmentedControl](/components/segmentedcontrol), `CheckboxGroup`, and other group components now accept primitive values such as numbers and booleans, rather than only strings. ```python dmc.Select( data=[ {"value": 1, "label": "One"}, {"value": 2, "label": "Two"}, {"value": 3, "label": "Three"}, ], value=2, ) ``` #### Clear section mode Clearable inputs now support `clearSectionMode` to control how the clear button and `rightSection` are rendered: - `"both"` (default): show both. - `"rightSection"`: show only the supplied `rightSection`. - `"clear"`: show only the clear button. Supported components include [Select](/components/select), [Autocomplete](/components/autocomplete), [MultiSelect](/components/multiselect), [TagsInput](/components/tagsinput), and the date and time input components. ```python import dash_mantine_components as dmc from dash_iconify import DashIconify data = [f"Option-{i}" for i in range(6)] component = dmc.Stack([ dmc.MultiSelect( label="clearSectionMode='both' (default)", placeholder="Select options", data=data, value=["Option-1", "Option-2"], clearable=True, rightSection=DashIconify(icon="tabler:chevron-down", width=16), clearSectionMode="both", ), dmc.MultiSelect( label="clearSectionMode='rightSection'", placeholder="Select options", data=data, value=["Option-1", "Option-2"], clearable=True, rightSection=DashIconify(icon="tabler:chevron-down", width=16), clearSectionMode="rightSection", ), dmc.MultiSelect( label="clearSectionMode='clear'", placeholder="Select options", data=data, value=["Option-1", "Option-2"], clearable=True, rightSection=DashIconify(icon="tabler:chevron-down", width=16), clearSectionMode="clear", ), ]) ``` #### Dropdown height `Combobox`, [Select](/components/select), [MultiSelect](/components/multiselect), [Autocomplete](/components/autocomplete), and [TagsInput](/components/tagsinput) now support `floatingHeight="viewport"` to let dropdowns fill the available viewport height. This is useful for large option lists. ```python import dash_mantine_components as dmc data = [f"Option {i}" for i in range(100)] component = dmc.MultiSelect( label="Fits viewport height", placeholder="Pick value", data=data, floatingHeight="viewport", ) ``` ### Buttons & Navigation #### Pagination sizing [Pagination](/components/pagination) controls are smaller than inputs and buttons by default. Use the `input-` prefix with the `size` prop to match their size. ```python import dash_mantine_components as dmc component = dmc.Stack([ dmc.Group([ dmc.Pagination(total=45, size="sm"), dmc.Button("sm button", size="sm"), dmc.TextInput(size="sm", placeholder="sm input"), ]), dmc.Group([ dmc.Pagination(total=45, size="input-sm"), dmc.Button("sm button", size="sm"), dmc.TextInput(size="sm", placeholder="sm input"), ], mt="md"), ]) ``` #### Pagination start value [Pagination](/components/pagination) now supports `startValue` to set the first page number. ```python import dash_mantine_components as dmc component = dmc.Stack([ dmc.Text("Pages 5–15 (startValue=5, total=15)", mb="xs"), dmc.Pagination(total=15, startValue=5, value=5), ]) ``` #### Responsive pagination [Pagination](/components/pagination) now supports `layout="responsive"`, which switches between page buttons and a compact "Page X of Y" label based on available width. Use `formatLabel` to customize the label. ```python import dash_mantine_components as dmc component = dmc.Box( dmc.Pagination(total=20, layout="responsive"), style={ "resize": "horizontal", "overflow": "auto", "minWidth": 200, "maxWidth": "100%", "border": "1px solid var(--mantine-color-gray-5)", "padding": "16px", }, ) ``` #### Stepper label position `Stepper` now supports `labelPosition="bottom"` to display step labels and descriptions below their icons. ```python import dash_mantine_components as dmc component = dmc.Stepper( [ dmc.StepperStep(label="Account"), dmc.StepperStep(label="Verification"), dmc.StepperStep(label="Access"), ], id="stepper", active=1, labelPosition="bottom", ) ``` #### Tree connecting lines [Tree](/components/tree) now supports `withLines` to display connecting lines between parent and child nodes. The lines adapt to `levelOffset`. ```python import dash_mantine_components as dmc from dash import callback, Input, Output from .data import data component = dmc.Tree( data=data, withLines=True, levelOffset=40, expanded=[ "node_modules", "node_modules/@mantine", "node_modules/@mantine/form", "node_modules/@mantine/form/index.d.ts", ], ) ``` ### Feedback #### Notifications [Notification](/components/notification) now support swipe dismissal, auto-close progress, stacked layout, and priority: - Swipe dismissal: dismiss notifications by dragging left or right, or by horizontal scrolling while hovering. These behaviors can be disabled on `NotificationContainer`, and individual notifications can opt out with `allowClose=False`. - Auto-close progress: `withAutoCloseProgress` displays a progress line showing the time remaining before a notification closes. The line pauses with the timer and uses the notification color. Set a default on the container or override it for individual notifications. - Stacked layout: `layout="stacked"` displays the latest notification in front, with older notifications peeking out behind it. - Priority: notifications with higher `priority` take visible slots when the active notification limit is reached. Equal priorities retain insertion order. The default priority is `0`. ```python import dash_mantine_components as dmc from dash import Output, Input, html, callback, no_update from dash_iconify import DashIconify component = html.Div([ # Place one NotificationContainer in app.layout) dmc.Button("Show Notification", id="notification-progress-show") ]) @callback( Output("notification-container", "sendNotifications", allow_duplicate=True), Input("notification-progress-show", "n_clicks"), prevent_initial_call=True, ) def show(n_clicks): if n_clicks is None: return no_update return [dict( title="Hey there!", id="show-notify", action="show", message="Notifications in Dash, Awesome!", icon=DashIconify(icon="ic:round-celebration"), withAutoCloseProgress=True )] ``` #### RingProgress improvements [RingProgress](/components/ringprogress) now supports `sectionGap` to separate sections and `startAngle` to control where the progress starts. ```python import dash_mantine_components as dmc sections = [ {"value": 40, "color": "cyan"}, {"value": 25, "color": "orange"}, {"value": 15, "color": "grape"}, ] component = dmc.Stack( [ dmc.Box( [ dmc.Text("No gap (default)", size="sm", ta="center", mb="xs"), dmc.RingProgress(sections=sections), ] ), dmc.Box( [ dmc.Text("5° gap", size="sm", ta="center", mb="xs"), dmc.RingProgress(sections=sections, sectionGap=5), ] ), dmc.Box( [ dmc.Text("10° gap", size="sm", ta="center", mb="xs"), dmc.RingProgress(sections=sections, sectionGap=10), ] ), ], align="center", ) ``` ```python import dash_mantine_components as dmc sections = [{"value": 40, "color": "cyan"}] component = dmc.Group( [ dmc.Stack( [ dmc.RingProgress(sections=sections, startAngle=0), dmc.Text("0° (right)", size="sm"), ], align="center", gap="xs", ), dmc.Stack( [ dmc.RingProgress(sections=sections, startAngle=90), dmc.Text("90° (bottom)", size="sm"), ], align="center", gap="xs", ), dmc.Stack( [ dmc.RingProgress(sections=sections, startAngle=180), dmc.Text("180° (left)", size="sm"), ], align="center", gap="xs", ), dmc.Stack( [ dmc.RingProgress(sections=sections, startAngle=270), dmc.Text("270° (top)", size="sm"), ], align="center", gap="xs", ), ], justify="center", ) ``` ### Overlay #### Tooltip arrow position [Tooltip](/components/tooltip) now supports `arrowPosition="merge"`, which merges the arrow with the corresponding corner of the dropdown. #### Stable dropdown positioning [Popover](/components/popover) and components built on it now default to `preventPositionChangeWhenVisible=True`. A dropdown chooses its position when opened and keeps that position until closed, even when scrolling, resizing, or changes to its content affect the available space. When neither side fits, it falls back to the preferred `position`. To restore the previous behavior, set `preventPositionChangeWhenVisible=False` through `comboboxProps`: ```python dmc.Select( comboboxProps={"preventPositionChangeWhenVisible": False}, data=["React", "Angular", "Svelte"], ) ``` #### Interactive Tooltip [Tooltip](/components/tooltip) now supports `interactive` to keep the tooltip open while the pointer moves from its target to the tooltip content. This allows users to interact with content such as links and supports WCAG 2.1 success criterion 1.4.13. ```python import dash_mantine_components as dmc component = dmc.Tooltip( label="This tooltip stays open while you move the pointer onto it, so you can read or select its full contents without it closing.", interactive=True, withArrow=True, multiline=True, w=220, children=dmc.Button("Hover to read the tooltip"), ) ``` #### Tooltip hideDetached [Tooltip](/components/tooltip) now supports `hideDetached`, matching the behavior of [Popover](/components/popover). It is enabled by default and hides the tooltip when its target is removed from the DOM, hidden with `display: none`, or scrolled out of a clipping container. #### HoverCard accessibility and behavior [HoverCard](/components/hovercard) now opens on keyboard focus, closes with `Escape` or an outside press, and is announced by screen readers. New props include `events`, `interactive`, `role`, and `returnFocus`. On touch devices, `HoverCard` no longer opens on tap by default. Set `events={"focus": False, "touch": True}` and `closeOnEscape=False` to restore the previous behavior. ### Data Display #### Accordion disable collapse [Accordion](/components/accordion) now supports `disableCollapse`. In single mode (`multiple=False`), the open item cannot be collapsed by clicking it again. Use `value` to ensure an item is open initially. ```python import dash_mantine_components as dmc data = [ { "emoji": "🍎", "value": "Apples", "description": "Crisp and refreshing fruit. Apples are known for their versatility and nutritional benefits. They come in a variety of flavors and are great for snacking, baking, or adding to salads.", }, { "emoji": "🍌", "value": "Bananas", "description": "Naturally sweet and potassium-rich fruit. Bananas are a popular choice for their energy-boosting properties and can be enjoyed as a quick snack, added to smoothies, or used in baking.", }, { "emoji": "🥦", "value": "Broccoli", "description": "Nutrient-packed green vegetable. Broccoli is packed with vitamins, minerals, and fiber. It has a distinct flavor and can be enjoyed steamed, roasted, or added to stir-fries.", }, ] component = dmc.Accordion( [ dmc.AccordionItem( [ dmc.AccordionControl(item["value"], icon=item["emoji"]), dmc.AccordionPanel(item["description"]), ], value=item["value"], ) for item in data ], value="Apples", disableCollapse=True, order=3, ) ``` #### Timeline opposite and alternate content `TimelineItem` now supports `opposite` to display content on the opposite side of the timeline. When used, the timeline switches to a centered layout. Use `alternate` on individual items to switch the positions of the main and opposite content. ```python import dash_mantine_components as dmc from dash_iconify import DashIconify component = dmc.Timeline( [ dmc.TimelineItem( title="New branch", bullet=DashIconify(icon="tabler:git-branch", width=12), opposite=dmc.Text("2 hours ago", size="sm", c="dimmed"), children=dmc.Text( [ "You've created new branch ", dmc.Text("fix-notifications", variant="link", span=True, inherit=True), " from master", ], c="dimmed", size="sm", ), ), dmc.TimelineItem( title="Commits", bullet=DashIconify(icon="tabler:git-commit", width=12), opposite=dmc.Text("52 minutes ago", size="sm", c="dimmed"), children=dmc.Text( [ "You've pushed 23 commits to ", dmc.Text("fix-notifications branch", variant="link", span=True, inherit=True), ], c="dimmed", size="sm", ), ), dmc.TimelineItem( title="Pull request", bullet=DashIconify(icon="tabler:git-pull-request", width=12), lineVariant="dashed", opposite=dmc.Text("34 minutes ago", size="sm", c="dimmed"), children=dmc.Text( [ "You've submitted a pull request ", dmc.Text( "Fix incorrect notification message (#187)", variant="link", span=True, inherit=True, ), ], c="dimmed", size="sm", ), ), dmc.TimelineItem( title="Code review", bullet=DashIconify(icon="tabler:message-circle", width=12), children=dmc.Text( [ dmc.Text("Claude", variant="link", span=True, inherit=True), " left a code review on your pull request", ], c="dimmed", size="sm", ), ), ], active=1, bulletSize=24, lineWidth=2, ) ``` ```python import dash_mantine_components as dmc component = dmc.Timeline( [ dmc.TimelineItem( title="Project started", opposite=dmc.Text("Jan 2025", size="sm", c="dimmed"), children="Initial planning and requirements gathering.", ), dmc.TimelineItem( title="Beta release", opposite=dmc.Text("Apr 2025", size="sm", c="dimmed"), alternate=True, children="Released the first version to early adopters.", ), dmc.TimelineItem( title="General availability", opposite=dmc.Text("Aug 2025", size="sm", c="dimmed"), children="Launched publicly with full documentation.", ), dmc.TimelineItem( title="Version 2.0", opposite=dmc.Text("Jan 2026", size="sm", c="dimmed"), alternate=True, children="Introduced a redesigned interface and new features.", ), ], active=3, bulletSize=16, lineWidth=2, ) ``` #### Indicator improvements [Indicator](/components/indicator) now supports: - `maxValue` to display a capped label, such as `99+`. - `showZero` to control whether an indicator with a label of `0` is visible. Defaults to `True`. - `offset` with separate `x` and `y` values. ```python import dash_mantine_components as dmc component = dmc.Group( [ dmc.Indicator( dmc.Avatar( size="lg", radius="xl", src="https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-1.png", ), inline=True, label=50, maxValue=99, ), dmc.Indicator( dmc.Avatar( size="lg", radius="xl", src="https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-2.png", ), inline=True, label=100, maxValue=99, ), dmc.Indicator( dmc.Avatar( size="lg", radius="xl", src="https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-3.png", ), inline=True, label=1000, maxValue=999, ), ] ) ``` ### Typography #### Highlight improvements [Highlight](/components/highlight) now supports custom colors for individual terms using a list of dictionaries containing text and color properties. ```python import dash_mantine_components as dmc component = dmc.Highlight( "Error: Invalid input. Warning: Check this field. Success: All tests passed.", highlight=[ {"text": "error", "color": "red"}, {"text": "warning", "color": "yellow"}, {"text": "success", "color": "green"}, ], ) ``` Use `wholeWord` to match complete words only. ```python import dash_mantine_components as dmc component = dmc.Box([ dmc.Text( "With whole word matching (wholeWord=True)", size="sm", c="dimmed", ), dmc.Highlight( "The theme is there", highlight="the", wholeWord=True, ), dmc.Text( "Without whole word matching (default)", size="sm", c="dimmed", mt="lg", ), dmc.Highlight( "The theme is there", highlight="the", ), ]) ``` Matching is case-insensitive and accent-insensitive by default. Use `caseInsensitive` or `accentInsensitive` to change this behavior. ```python import dash_mantine_components as dmc component = dmc.Box([ dmc.Text( "With case-insensitive matching (default)", size="sm", c="dimmed", ), dmc.Highlight( "Highlight This, definitely THIS and also this!", highlight="this", ), dmc.Text( "With case-sensitive matching (caseInsensitive=False)", size="sm", c="dimmed", mt="lg", ), dmc.Highlight( "Highlight This, definitely THIS and also this!", highlight="this", caseInsensitive=False, ), ]) ``` #### Text wrapping [Text](/components/text) and [Blockquote](/components/blockquote) now support `textWrap` to control the CSS `text-wrap` property. #### List attributes [List](/components/list) now supports the HTML attributes `start`, `reversed`, and `value` for ordered lists. ```python import dash_mantine_components as dmc component = dmc.Box( [ dmc.Text("Start from specific number:", c="dimmed"), dmc.List( [ dmc.ListItem("This is item #5"), dmc.ListItem("This is item #6"), dmc.ListItem("This is item #7"), dmc.ListItem("This is item #8"), ], type="ordered", start=5, ), dmc.Text("Reversed numbering:", mt="lg", c="dimmed"), dmc.List( [ dmc.ListItem("This is item #3"), dmc.ListItem("This is item #2"), dmc.ListItem("This is item #1"), ], type="ordered", reversed=True, ), ] ) ``` #### CodeHighlight line numbers [CodeHighlight](/components/code-highlight) and `CodeHighligtTabs` now supports `withLineNumbers` to display line numbers alongside code. `` dmc.CodeHighlightTabs( # or dmc.CodeHighligh( code=code, withExpandButton=True, expandCodeLabel="Show full code", collapseCodeLabel="Show less", defaultExpanded=False ) ```python import dash_mantine_components as dmc component = dmc.CodeHighlight( withLineNumbers=True, withExpandButton=True, defaultExpanded=False, language="python", code="""# Kadane's Algorithm class Solution: def maxSubArray(self, nums: List[int]) -> int: curr, summ = nums[0], nums[0] for n in nums[1:]: curr = max(n, curr + n) summ = max(summ, curr) return summ""", ) ``` `CodeHighlight` now supports expandable code snippets with `withExpandButton`, `defaultExpanded`, `expandCodeLabel`, and `collapseCodeLabel` props, previously available only in `CodeHighlightTabs`. ### Datepickers #### DateTimePicker range [DateTimePicker](/components/datetimepicker) now supports `type="range"` for selecting a date and time range. Two time inputs are displayed for the start and end times, with a range summary below. ```python import dash_mantine_components as dmc component = dmc.DateTimePicker( label="Pick date and time range", placeholder="Pick date and time range", type="range", ) ``` #### TimePicker duration [TimePicker](/components/timepicker) now supports `type="duration"` for entering durations longer than 24 hours. The hours field has no upper limit, and the input width adjusts to the value. The `format` prop is ignored, the display is always 24-hour, and the dropdown is disabled. ```python import dash_mantine_components as dmc component = dmc.TimePicker( label="Enter a duration", withSeconds=True, type="duration" ) ``` #### Month and year presets [MonthPickerInput](/components/monthpickerinput) and [YearPickerInput](/components/yearpickerinput) now support `presets` for predefined values. ```python from datetime import date from dateutil.relativedelta import relativedelta import dash_mantine_components as dmc today = date.today() start_of_month = lambda months: (today.replace(day=1) + relativedelta(months=months)).isoformat() component = dmc.MonthPickerInput( label="With presets", placeholder="Select month", presets=[ {"value": start_of_month(0), "label": "This month"}, {"value": start_of_month(1), "label": "Next month"}, {"value": start_of_month(-1), "label": "Last month"}, {"value": start_of_month(6), "label": "In 6 months"}, {"value": start_of_month(12), "label": "Next year"}, {"value": start_of_month(-12), "label": "Last year"}, ], ) ``` #### Date formatting functions [DateTimePicker](/components/datetimepicker) and [DateInput](/components/dateinput) now accept functions in `valueFormat`. [DatePickerInput](/components/datepickerinput), [MonthPickerInput](/components/monthpickerinput), and [YearPickerInput](/components/yearpickerinput) accept functions in `valueFormatter` to customize displayed date text. Note: This example uses custom JavaScript defined in the assets folder. Learn more in the "Functions As Props" section of this document. ```python import dash_mantine_components as dmc component = dmc.DatePickerInput( label="Pick multiple dates", type="multiple", placeholder="Pick multiple dates", clearable=True, valueFormatter={"function": "formatDatesSelected"}, ), ``` ```javascript var dmcfuncs = window.dashMantineFunctions = window.dashMantineFunctions || {}; dmcfuncs.formatDatesSelected = ({ type, date, locale, format }) => { if (type === "multiple" && Array.isArray(date)) { if (date.length === 1) { return dayjs(date[0]).locale(locale).format(format); } if (date.length > 1) { return `${date.length} dates selected`; } return ""; } return ""; }; ``` #### TimePicker preset selection [TimePicker](/components/timepicker) now supports `closeDropdownOnPresetSelect` to close the dropdown after a preset is selected. ```python import dash_mantine_components as dmc component = dmc.TimePicker( label="Enter a time", format="12h", withDropdown=True, presets=['11:30', '15:45', '18:00', '20:15', '22:30'], closeDropdownOnPresetSelect=True ) ``` #### Native calendar level selection Date picker components now support `withNativeLevelSelect`, which replaces the calendar header level button with native select elements for navigating to a month or year. ```python import dash_mantine_components as dmc component = dmc.DatePicker(withNativeLevelSelect=True, yearsSelectRange=[2020, 2035]) ``` ### Charts #### Chart brush (range slider) [AreaChart](/components/areachart), [BarChart](/components/barchart), [LineChart](/components/linechart), and [CompositeChart](/components/compositechart) now support `withBrush` to add a range slider below the chart. Use `brushProps` to configure the Recharts Brush component and `brushDragEnd` to receive the selected `startIndex` and `endIndex`. ```python import dash_mantine_components as dmc from dash import callback, Input, Output data = [ {"date": "Mar 1", "Apples": 2200, "Oranges": 1400}, {"date": "Mar 2", "Apples": 2500, "Oranges": 1500}, {"date": "Mar 3", "Apples": 2800, "Oranges": 1700}, {"date": "Mar 4", "Apples": 3100, "Oranges": 1600}, {"date": "Mar 5", "Apples": 3000, "Oranges": 1800}, {"date": "Mar 6", "Apples": 2700, "Oranges": 2000}, {"date": "Mar 7", "Apples": 2400, "Oranges": 2100}, {"date": "Mar 8", "Apples": 2100, "Oranges": 1900}, {"date": "Mar 9", "Apples": 1900, "Oranges": 1700}, {"date": "Mar 10", "Apples": 2200, "Oranges": 1500}, {"date": "Mar 11", "Apples": 2600, "Oranges": 1600}, {"date": "Mar 12", "Apples": 3000, "Oranges": 1800}, {"date": "Mar 13", "Apples": 3300, "Oranges": 2000}, {"date": "Mar 14", "Apples": 3100, "Oranges": 2200}, {"date": "Mar 15", "Apples": 2800, "Oranges": 2100}, {"date": "Mar 16", "Apples": 2500, "Oranges": 1900}, ] component = dmc.Stack([ dmc.AreaChart( h=300, data=data, dataKey="date", withBrush=True, series=[ {"name": "Apples", "color": "indigo.6"}, {"name": "Oranges", "color": "blue.6"}, ], id="areachart-brush" ), dmc.Text(id="areachart-brush-dragend") ]) @callback( Output("areachart-brush-dragend", "children"), Input("areachart-brush", "brushDragEnd"), ) def brushDragEnd(brushDragEnd): return f"Brush range selected: {brushDragEnd}" ``` #### AreaChart streamgraph [AreaChart](/components/areachart) now supports `type="stream"` to render a streamgraph, a stacked area chart with a flowing baseline. The y-axis is hidden by default because the values are not meaningful to read against a fixed baseline. ```python import dash_mantine_components as dmc data = [ {"month": "Jan", "Apples": 220, "Oranges": 140, "Tomatoes": 90, "Grapes": 60}, {"month": "Feb", "Apples": 260, "Oranges": 180, "Tomatoes": 120, "Grapes": 90}, {"month": "Mar", "Apples": 300, "Oranges": 240, "Tomatoes": 180, "Grapes": 140}, {"month": "Apr", "Apples": 340, "Oranges": 320, "Tomatoes": 260, "Grapes": 200}, {"month": "May", "Apples": 380, "Oranges": 420, "Tomatoes": 360, "Grapes": 280}, {"month": "Jun", "Apples": 420, "Oranges": 520, "Tomatoes": 460, "Grapes": 360}, {"month": "Jul", "Apples": 400, "Oranges": 560, "Tomatoes": 520, "Grapes": 420}, {"month": "Aug", "Apples": 360, "Oranges": 520, "Tomatoes": 560, "Grapes": 460}, {"month": "Sep", "Apples": 300, "Oranges": 440, "Tomatoes": 520, "Grapes": 420}, {"month": "Oct", "Apples": 260, "Oranges": 340, "Tomatoes": 440, "Grapes": 360}, {"month": "Nov", "Apples": 220, "Oranges": 260, "Tomatoes": 340, "Grapes": 280}, {"month": "Dec", "Apples": 200, "Oranges": 200, "Tomatoes": 260, "Grapes": 200}, ] component = dmc.AreaChart( h=300, data=data, dataKey="month", type="stream", series=[ {"name": "Apples", "color": "indigo.6"}, {"name": "Oranges", "color": "blue.6"}, {"name": "Tomatoes", "color": "teal.6"}, {"name": "Grapes", "color": "grape.6"}, ], ) ``` #### Reference areas [AreaChart](/components/areachart), [BarChart](/components/barchart), [LineChart](/components/linechart), [CompositeChart](/components/compositechart), and [ScatterChart](/components/scatterchart) now support `referenceAreas` to highlight rectangular regions such as target ranges, thresholds, or weekends. Areas can be defined by x and y data values and support a theme color and label. ```python import dash_mantine_components as dmc from .data import data component = dmc.AreaChart( h=300, data=data, dataKey="date", type="stacked", series=[ {"name": "Apples", "color": "indigo.6"}, {"name": "Oranges", "color": "blue.6"}, {"name": "Tomatoes", "color": "teal.6"}, ], referenceAreas=[ {"x1": "Mar 23", "x2": "Mar 25", "color": "red.6", "label": "Weekend"}, ], ) ``` #### Reference dots [AreaChart](/components/areachart), [BarChart](/components/barchart), [LineChart](/components/linechart), [CompositeChart](/components/compositechart), and [ScatterChart](/components/scatterchart) now support `referenceDots` to mark individual data points. Each dot supports a radius, theme color, and label. ```python import dash_mantine_components as dmc from .data import data component = dmc.AreaChart( h=300, data=data, dataKey="date", series=[ {"name": "Apples", "color": "indigo.6"}, {"name": "Oranges", "color": "blue.6"}, {"name": "Tomatoes", "color": "teal.6"}, ], referenceDots=[ {"x": "Mar 25", "y": 3470, "color": "red.6", "label": "Peak"}, ], ) ``` #### Heatmap legend and month labels [Heatmap](/components/heatmap) now supports `withLegend` to display a color legend below the chart. Use `legendLabels` to customize the labels. The default is `["Less", "More"]`. `monthLabelsPosition` controls whether month labels appear above or below the heatmap. ```python import dash_mantine_components as dmc from .data import data component = dmc.Heatmap( data=data, startDate="2024-02-16", endDate="2025-02-16", withWeekdayLabels=True, withMonthLabels=True, withLegend=True, ) ``` ```python import dash_mantine_components as dmc from .data import data component = dmc.Heatmap( data=data, startDate="2024-02-16", endDate="2025-02-16", withWeekdayLabels=True, withMonthLabels=True, monthLabelsPosition="bottom" ) ``` #### PieChart and DonutChart labels [PieChart](/components/piechart) and [DonutChart](/components/donutchart) now support `labelsType="name"` to display segment names instead of values or percentages. ```python import dash_mantine_components as dmc from .data import data component = dmc.PieChart( data=data, withLabels=True, withLabelsLine=True, labelsType="name", ) ``` #### Chart legends [PieChart](/components/piechart), [DonutChart](/components/donutchart), and [FunnelChart](/components/funnelchart) now support `withLegend` to display segment names and colors. Hovering over a legend item highlights the corresponding segment. Use `legendProps` to configure the underlying Recharts Legend component. ```python import dash_mantine_components as dmc from .data import data component = dmc.FunnelChart(data=data, withLegend=True) ``` #### ScatterChart right Y axis [ScatterChart](/components/scatterchart) now supports `withRightYAxis` to display a second y-axis on the right. Configure it with `rightYAxisProps` and `rightYAxisLabel`. ```python import dash_mantine_components as dmc from .data import data3 component = dmc.ScatterChart( h=350, data=data3, dataKey={"x": "month", "y": "value"}, withLegend=True, withRightYAxis=True, xAxisLabel="Month", yAxisLabel="Revenue", rightYAxisLabel="Conversion rate", rightYAxisProps={"unit": "%"}, ) ``` ### Other new features #### Theming and styling A new `fontWeights` theme property controls font weights across components. The defaults are `regular=400`, `medium=600`, and `bold=700`, mapped to CSS variables. To restore the previous medium weight of 500: ```python dmc.MantineProvider(theme={"fontWeights": {"medium": 500}}) ``` All Mantine components now support logical margin and padding props: - `mis`: margin-inline-start - `mie`: margin-inline-end - `pis`: padding-inline-start - `pie`: padding-inline-end #### Responsive style performance [MantineProvider](/components/mantineprovider) now supports `deduplicateInlineStyles`, enabled by default. With React 19, repeated responsive style values can share a single style tag instead of generating one for each component. This can improve performance when rendering large lists with identical responsive style props. See [Responsive Styles](https://www.dash-mantine-components.com/responsive-styles) for details. #### Additional component enhancements - [ColorPicker](/components/colorpicker) supports `name` and `hiddenInputProps` for uncontrolled form submissions. - [ColorInput](/components/colorinput) supports `fullWidth` to make the dropdown match the input width. - [JsonInput](/components/jsoninput) supports `indentSpaces` to control JSON formatting indentation. - [Collapse](/components/collapse), [NavLink](/components/navlink), and `AccordionPanel` support `keepMounted=False` to unmount collapsed content. - [Stepper](/components/stepper), [Tabs](/components/tabs), and [Tree](/components/tree) support `keepMounted`. - [Tabs](/components/tabs) supports `keepMountedMode` to control how inactive panels are hidden when `keepMounted=True`. Use `"display-none"` to use `display: none` instead of the default `Activity` component. - [Menu](/components/menu) submenus use a safe polygon when moving the pointer diagonally from a parent item to a submenu. - [PasswordInput](/components/passwordinput) supports `visibilityToggleFocusable` to include the visibility toggle in the keyboard tab order. - [Checkbox](/components/checkbox) supports `readOnly` and `withErrorStyles`. - [Spoiler](/components/spoiler) supports `showAriaLabel` and `hideAriaLabel` to customize screen reader labels. ### Breaking and behavior changes - `TypographyStylesProvider` was renamed to `Typography`. - `Grid.gutter` was renamed to `gap`. Use `rowGap` and `columnGap` for separate row and column spacing. - `Spoiler.initialState` was renamed to `defaultExpanded`. - `Text` and `Anchor` no longer accept the `color` prop. Use the `c` style prop instead. - `Popover` and `Tooltip` no longer accept `positionDependencies`; it is no longer required. - `Tree` no longer defines the `data-hovered` attribute for hover state. Apply hover styles with `&:hover` instead. - The `PasswordInput` visibility toggle icon has changed. - Notifications now pause the auto-close timer for all visible notifications when any notification is hovered. Set `pauseResetOnHover="notification"` to restore the previous behavior of pausing only the hovered notification. - The default `theme.defaultRadius` changed from `sm` (4px) to `md` (8px). - The `light` variant now uses opaque colors to improve contrast. - The `mod` prop converts camelCase keys to kebab-case for data attributes. - The default medium font weight changed from 500 to 600. See the `fontWeights` theme property above to customize it.