## Version 2.0.0 Release announcement for Dash Mantine Components v2.0.0 Category: Releases ### Dash Mantine Components v2 (Powered by Mantine v8) Released Jun 3, 2025 ### Migration Guide This version is built on [Mantine 8](https://v8.mantine.dev/changelog/8-0-0/), so there are some breaking changes, but as promised, far fewer than in previous major releases. See our [Migration Guide](/migration) for step-by-step instructions for updating your apps. ### What's New * **Functions as Props** – Use JavaScript functions from Python to customize charts, sliders, filters, dropdowns, and more * **Simplified Notifications** – Use `NotificationContainer` and the Mantine API directly in clientside callbacks * **New DatePicker** – A calendar-only component with full support for multi-date, ranges, and custom disabled logic * **New TimePicker & TimeGrid** – Better time selection with dropdowns, 12/24h formats, and predefined slots * **Submenus in Menu** – New nested menu support * **Carousel API updates** – Now uses `emblaOptions` for full alignment with Mantine * **Component improvements** – Updated `Switch`, better dropdown behavior, and more! ### New Functions as Props You can now pass JavaScript functions to DMC components using: ```python {"function": "yourFunctionName"} ``` This enables advanced use cases like: - Custom chart tooltips and axis value formatting - Smart search filters for Select and MultiSelect - Custom option renderers with full React components - Custom Slider scales and labels - Dynamically disabled calendar dates You can even pass options from Python: ```python {"function": "formatTemp", "options": {"unit": "F"}} ``` Functions live in `/assets/*.js` under the global `window.dashMantineFunctions` object. 🤔 Don’t know JavaScript? No problem! The docs include examples of how to use AI to convert Python functions to JavaScript, with prompt templates to help you get reliable results every time: See the new [Functions As Props docs](/functions-as-props) #### Example: Custom Slider Label + Scale ```python import dash_mantine_components as dmc component = dmc.Stack([ dmc.Slider( min=2, max=30, step=1, value=10, scale={"function": "getScale"}, labelAlwaysOn=True, label={"function": "valueLabelFormat"} ), dmc.RangeSlider( mt=50, min=2, max=30, step=1, value=[10, 20], scale={"function": "getScale"}, labelAlwaysOn=True, label={"function": "valueLabelFormat"} ) ]) ``` ```javascript var dmcfuncs = window.dashMantineFunctions = window.dashMantineFunctions || {}; dmcfuncs.getScale = (v) => Math.pow(2, v); dmcfuncs.valueLabelFormat = (value) => { const units = ['KB', 'MB', 'GB', 'TB']; let unitIndex = 0; let scaledValue = value; while (scaledValue >= 1024 && unitIndex < units.length - 1) { unitIndex += 1; scaledValue /= 1024; } return `${scaledValue} ${units[unitIndex]}`; }; ``` #### Example: DatePicker: Disable All Except Fridays ```python import dash_mantine_components as dmc # makes dayjs available #app = Dash(exteral_scripts=["https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.10.8/dayjs.min.js"]) component = dmc.Center( dmc.DatePicker( value="2024-11-08", defaultDate="2024-11-01", disabledDates={"function": "excludeDate"}, m="lg" ) ) ``` ```javascript var dmcfuncs = window.dashMantineFunctions = window.dashMantineFunctions || {}; dmcfuncs.excludeDate = function(dateStr) { const date = dayjs(dateStr, "YYYY-MM-DD"); return date.isValid() && date.day() !== 5; } ``` #### Example: MultiSelect: Components in the Dropdown ```python import dash_mantine_components as dmc users_data = { "Emily Johnson": { "image": "https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-7.png", "email": "emily92@gmail.com", }, "Ava Rodriguez": { "image": "https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-8.png", "email": "ava_rose@gmail.com", }, "Olivia Chen": { "image": "https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-4.png", "email": "livvy_globe@gmail.com", }, "Ethan Barnes": { "image": "https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-1.png", "email": "ethan_explorer@gmail.com", }, "Mason Taylor": { "image": "https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-2.png", "email": "mason_musician@gmail.com", }, } component = dmc.MultiSelect( data=list(users_data.keys()), label="Employees of the month", placeholder="Search for employee", maxDropdownHeight=300, searchable=True, hidePickedOptions=True, renderOption={ "function": "renderUserOption", "options": {"users": users_data}, }, ) ``` ```javascript var dmcfuncs = window.dashMantineFunctions = window.dashMantineFunctions || {}; var dmc = window.dash_mantine_components; dmcfuncs.renderUserOption = function ({ option }, { users }) { const user = users[option.value]; return React.createElement( dmc.Group, { gap: "sm" }, React.createElement(dmc.Avatar, { key: "avatar", src: user.image, size: 36, radius: "xl", }), React.createElement( "div", { key: "text-block" }, React.createElement(dmc.Text, { size: "sm", key: "name" }, option.value), React.createElement(dmc.Text, { size: "xs", opacity: 0.5, key: "email", children: user.email, }) ) ); }; ``` ### New NotificationContainer component Notifications are now handled by a single component: `NotificationContainer`. This new approach replaces the previous `NotificationProvider` + `Notification` pattern with one that’s simpler, more consistent with Mantine, and resolves a number of issues from earlier versions. Also, there is now direct access to Mantine's Notification API in clientside callbacks. Thanks to @BSd3v for contributing this new component. Please see the new [Notification docs](/components/notification) for more details. ### New Menu with Sub Menus ```python import dash_mantine_components as dmc menu = dmc.Menu( width=200, position="bottom-start", keepMounted=True, # required when using SubMenu children=[ dmc.MenuTarget( dmc.Button("Toggle Menu") ), dmc.MenuDropdown([ dmc.MenuItem("Dashboard"), dmc.SubMenu([ dmc.SubMenuTarget( dmc.SubMenuItem("Products") ), dmc.SubMenuDropdown([ dmc.MenuItem("All products"), dmc.MenuItem("Categories"), dmc.MenuItem("Tags"), dmc.MenuItem("Attributes"), dmc.MenuItem("Shipping classes"), ]) ]), dmc.SubMenu([ dmc.SubMenuTarget( dmc.SubMenuItem("Orders") ), dmc.SubMenuDropdown([ dmc.MenuItem("Open"), dmc.MenuItem("Completed"), dmc.MenuItem("Cancelled"), ]) ]), dmc.SubMenu([ dmc.SubMenuTarget( dmc.SubMenuItem("Settings") ), dmc.SubMenuDropdown([ dmc.MenuItem("Profile"), dmc.MenuItem("Security"), dmc.MenuItem("Notifications"), ]) ]), ]) ] ) component=dmc.Center(menu) ``` ### New TimePicker Component New `TimePicker` component is an alternative to `TimeInput` that offers more features. It supports 24-hour and 12-hour formats, dropdown with hours, minutes and seconds, and more. With Dropdown: ```python import dash_mantine_components as dmc component = dmc.Group( gap=50, mb=60, children=[ dmc.TimePicker( label="Enter time (24h format)", withSeconds=True, withDropdown=True ), dmc.TimePicker( label="Enter time (12h format)", withSeconds=True, withDropdown=True, format="12h" ), ], ) ``` With presets: ```python import dash_mantine_components as dmc from dash import callback, Input, Output component = dmc.TimePicker( label="Enter a time", withDropdown=True, maxDropdownContentHeight=300, presets = [ {"label": 'Morning', "values": ['06:00:00', '08:00:00', '10:00:00']}, {"label": 'Afternoon', "values": ['12:00:00', '14:00:00', '16:00:00']}, {"label": 'Evening', "values": ['18:00:00', '20:00:00', '22:00:00']}, ], mb=120, ) ``` ### DateTimePicker component changes `DateTimePicker` component now uses `TimePicker` under the hood instead of `TimeInput`. You can now use all `TimePicker` features with `DateTimePicker` component. The `timeInputProps` is no longer available. To pass props down to the underlying `TimePicker` you need to use `timePickerProps` prop. Example of enabling dropdown and setting 12h format for time picker: ```python from datetime import datetime import dash_mantine_components as dmc component = dmc.DateTimePicker( label="Pick date and time", placeholder="Pick Date and time", timePickerProps={ "withDropdown": True, "popoverProps": { "withinPortal": False }, "format": '12h', } ) ``` ### New TimeGrid component New `TimeGrid` component allows to capture time value from the user with a predefined set of time slots: ```python import dash_mantine_components as dmc from dash import callback, Input, Output component = dmc.Stack([ dmc.TimeGrid( timeRangeData={"startTime": "10:00", "endTime": "21:00", "interval": "01:00"}, withSeconds=False, simpleGridProps={ "type": "container", "cols": {"base": 1, "180px": 2, "320px": 3}, "spacing": "xs", }, value="10:00:00", id="time-grid" ), dmc.Text(id="time-grid-out") ]) @callback( Output("time-grid-out", "children"), Input("time-grid", "value") ) def update(value): return f"You selected: {value}" ``` ### New DatePicker component We've added a new `DatePicker` — a calendar-only component with no input field. It's the base calendar used in components like `DateInput`, `DatePickerInput`, and `DateTimePicker`. Any configuration you can apply to `DatePicker` — such as multiple selection, min/max dates, week numbers, or disabled dates — can also be used in those components. [Read the full DatePicker docs →](/components/datepicker) ```python import dash_mantine_components as dmc from dash import Input, Output, html, callback component = dmc.Stack([ dmc.DatePicker(id="date-picker"), dmc.Text(id="selected-date-picker", mt=10), ], align="center") @callback( Output("selected-date-picker", "children"), Input("date-picker", "value") ) def update_output(d): return f"You selected {d}" ``` ### Popover Hide detached Use `hideDetached` prop to configure how the dropdown behaves when the target element is hidden with styles (`display: none, visibility: hidden,` etc.), removed from the DOM, or when the target element is scrolled out of the viewport. By default, `hideDetached` is enabled – the dropdown is hidden with the target element. You can change this behavior with `hideDetached=False`. To see the difference, try to scroll the container that holds the Popover components: ```python import dash_mantine_components as dmc component = dmc.Box( style={"border": "1px solid var(--mantine-color-dimmed)", "overflow": "auto"}, p="xl", w=400, h=200, children=[ dmc.Box( w=1000, h=400, children=dmc.Group( [ dmc.Popover( opened=True, width="target", position="bottom", closeOnClickOutside=False, children=[ dmc.PopoverTarget( dmc.Button("Toggle popover") ), dmc.PopoverDropdown("This popover dropdown is hidden when detached"), ], ), dmc.Popover( opened=True, width="target", position="bottom", closeOnClickOutside=False, hideDetached=False, children=[ dmc.PopoverTarget( dmc.Button("Toggle popover") ), dmc.PopoverDropdown("This popover dropdown is visible when detached"), ], ), ] ), ) ] ) ``` ### Carousel changes The following props are removed. They now need to be passed to embla using the `emblaOptions` prop - `loop` - `align` - `slidesToScroll` - `dragFree` - `inViewThreshold` - `skipSnaps` - `containScroll` ```python # ❌ 1.x – embla options passed as props no longer works in 2.x dmc.Carousel(loop=True, dragFree=True, align="start") # ✅ 2.x – use emblaOptions to pass options to embla dmc.Carousel({ "loop": True, "dragFree": True, "align": 'start' }) ``` Also, the `speed` and `draggable` props were removed – they are no longer supported by embla ### Switch withThumbIndicator Switch component styles were updated to include indicator inside the thumb. You can change it by setting `withThumbIndicator` prop: ### Other changes - [CodeHighlight](/components/code-highlight) - To reduce the bundle size only the top 10 languages are supported. If you would like to include other, please open an issue on our GitHub - DatesProvider timezone -DatesProvider component no longer supports timezone option – all Mantine dates components now use strings in YYYY-MM-DD HH:mm:ss format as values and do not contain timezone information. - See the [Mantine Changelog](https://v8.mantine.dev/changelog/8-0-0/#other-changes) for other changes. --- ### Quick Start Just a reminder... * If you're using Dash ≥ 3.0.0, you no longer need to set the React version manually. * If you're using DMC ≥ 1.2.0, there's no need to include additional stylesheets like `dmc.styles.ALL`. Here’s a minimal app to get started: ```python import dash_mantine_components as dmc from dash import Dash app = Dash() app.layout = dmc.MantineProvider( dmc.Alert( "Welcome to Dash Mantine Components", title="Hello!", color="violet", ) ) if __name__ == "__main__": app.run(debug=True) ```