## Version 2.3.0 Release announcement for Dash Mantine Components v2.3.0 Category: Releases September 21, 2025 Based on Mantine 8.3.1 ### New DirectionProvider component Mantine supports right-to-left (RTL) layouts out of the box. Try the new direction toggle in the header of these docs — one click and the entire app flips to RTL. Not just the text, but every component adapts. Check out the [sliders](/components/slider) in RTL mode, they feel completely natural. See the [RTL (right-to-left) direction guide](/rtl) for details on enabling RTL direction and adding a toggle to your app. ```python app.layout = dmc.DirectionProvider( dmc.MantineProvider([ # your app layout ]), direction="rtl" ) ``` ### New MiniCalendar component The new [MiniCalendar](/components/mini-calendar) component makes it easy to add compact calendars. ```python import dash_mantine_components as dmc from dash import callback, Input, Output component = dmc.Stack([ dmc.MiniCalendar( defaultDate="2025-01-02", value="2025-01-03", id="mini-calendar" ), dmc.Text(id="mini-calendar-date", m="md") ]) @callback( Output("mini-calendar-date", "children"), Input("mini-calendar", "value"), ) def update(d): return f"You selected: {d}" ``` ### Progress vertical orientation [Progress](/components/progress) now supports vertical orientation: ```python import dash_mantine_components as dmc component = dmc.Group([ dmc.Progress(value=80, orientation="vertical", h=200), dmc.Progress( value=60, color="orange", size="xl", orientation="vertical", h=200, animated=True ), dmc.ProgressRoot( size="xl", autoContrast=True, orientation="vertical", h=200, children=[ dmc.ProgressSection( value=40, color="lime.4", children=dmc.ProgressLabel("Documents") ), dmc.ProgressSection( value=20, color="yellow.4", children=dmc.ProgressLabel("Apps") ), dmc.ProgressSection( value=20, color="cyan.7", children=dmc.ProgressLabel("Other") ) ] ) ]) ``` ### RichTextEditor upgraded to Tiptap V3 [RichTextEditor](/components/richtexteditor) is now built on Tiptap V3 enabling features like `BackgroundColor`, `FontFamily`, `FontSize`, `LineHeight`. Note: This change has no known breaking changes, but customizations may be affected. See our [migration guide,](https://www.dash-mantine-components.com/migration) for details. Here is an example of creating custom buttons to change the font size: ```python import dash_mantine_components as dmc from dash_iconify import DashIconify component = dmc.RichTextEditor( html="
Change font size with the controls!
", toolbar={ "controlsGroups": [ ["H1", "H2", "H3", "H4"], [ { "CustomControl": { "aria-label": "Increase font size", "title": "Increase font size", "children": DashIconify(icon="mdi:format-font-size-increase", width=16), "onClick": {"function": "increaseFontSize"}, }, }, { "CustomControl": { "aria-label": "Decrease font size", "title": "Decrease font size", "children": DashIconify(icon="mdi:format-font-size-decrease", width=16), "onClick": {"function": "decreaseFontSize"}, }, }, ], ], }, ) ``` ```javascript var dmcfuncs = window.dashMantineFunctions = window.dashMantineFunctions || {}; function changeFontSize(editor, delta) { if (!editor) return; const { from, to } = editor.state.selection; let size = 16; // default editor.state.doc.nodesBetween(from, to, (node) => { if (node.isText) { const mark = node.marks.find(m => m.type.name === "textStyle"); if (mark?.attrs.fontSize) { size = parseInt(mark.attrs.fontSize, 10); } } }); const newSize = Math.min(Math.max(size + delta, 8), 72) + "px"; editor.chain().focus().setFontSize(newSize).run(); } dmcfuncs.increaseFontSize = ({ editor }) => changeFontSize(editor, 2); dmcfuncs.decreaseFontSize = ({ editor }) => changeFontSize(editor, -2); ``` ### ScrollArea scrollTo prop The [ScrollArea](/components/scrollarea), now includes a `scrollTo` prop to control the viewport position. * `top` – The vertical position (pixels or percentage string, from '0%' to '100%') * `left` – The horizontal position (pixels or percentage string, from '0%' to '100%') * `behavior` – `auto` (instant) or `smooth` (animated, default) ```python import dash_mantine_components as dmc from dash import callback, Input, Output, ctx content = [ dmc.Box([ dmc.Title(f"Section {i}", order=4, mt="sm", id=f"section-{i}"), dmc.Text(""" Lorem ipsum, dolor sit amet consectetur adipisicing elit. Dicta perspiciatis reiciendis voluptate eaque itaque quos. Natus iure tenetur libero, reprehenderit ad, sequi, in aliquam eos necessitatibus expedita delectus veniam culpa! """) ]) for i in range(1, 11) ] component = dmc.Box([ dmc.ScrollArea( content, id="scrollArea", h=250, w=350, ), dmc.Group([ dmc.Button("Scroll to Top", id="scrollto-top"), dmc.Button("Scroll to Middle", id="scrollto-middle"), dmc.Button("Scroll to Bottom", id="scrollto-bottom"), ], mt="lg"), ]) @callback( Output("scrollArea", "scrollTo"), Input("scrollto-top", "n_clicks"), Input("scrollto-middle", "n_clicks"), Input("scrollto-bottom", "n_clicks"), ) def scroll_to(t, m, b): if ctx.triggered_id == "scrollto-middle": return {"top": "50%"} if ctx.triggered_id == "scrollto-bottom": return {"top": "100%"} return {"top": 0} ``` ### New ScrollAreaAutosize component `ScrollAreaAutosize` component creates a scrollable container once a given max-height is reached. ```python import dash_mantine_components as dmc from dash import callback, Output, Input, ctx lorem = ( "Lorem ipsum, dolor sit amet consectetur adipisicing elit. " "Dicta perspiciatis reiciendis voluptate eaque itaque quos. " "Natus iure tenetur libero, reprehenderit ad, sequi, in aliquam eos " "necessitatibus expedita delectus veniam culpa!" ) component = dmc.Stack( [ dmc.ScrollAreaAutosize(mah=300, maw=400, p="sm", id="scrollarea-autosize"), dmc.Group( m="lg", children=[ dmc.Button( "1 paragraph", id="btn-1-paragraph", color="red", ), dmc.Button( "4 paragraphs", id="btn-4-paragraphs", ), ], ), ] ) @callback( Output("scrollarea-autosize", "children"), Input("btn-1-paragraph", "n_clicks"), Input("btn-4-paragraphs", "n_clicks"), ) def update_paragraphs(inc, dec): if ctx.triggered_id == "btn-1-paragraph": return dmc.Box(lorem, p="sm") return [dmc.Box(lorem, p="sm") for _ in range(4)] ``` ### New Overlay component [Overlay](/components/overaly) creates a customizable layer over content or the entire viewport. It’s useful for dimming effects, interactive overlays, and custom loading states. You can configure opacity, color, and positioning. ```python import dash_mantine_components as dmc from dash import Dash, Input, Output, callback, html component = dmc.Stack([ dmc.AspectRatio( ratio=16/9, maw=400, mx="auto", pos="relative", children=[ html.Img( src="https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/images/bg-1.png", alt="Demo", ), dmc.Overlay( id="overlay-usage", color="#000", backgroundOpacity=0.85, style={"display": "block"} # Initially visible ) ] ), dmc.Button( "Toggle overlay", id="overlay-toggle-button", mx="auto", mt="lg", n_clicks=0 ) ]) @callback( Output("overlay-usage", "style"), Input("overlay-toggle-button", "n_clicks") ) def toggle_overlay(n_clicks): if n_clicks %2 == 0: return {"display": "block"} return {"display": "none"} ``` ### MultiSelect improvement [MultiSelect](/components/multiselect) now supports `clearSearchOnChange=False` allowing multiple selectios from the same search query. ```python import dash_mantine_components as dmc component = dmc.MultiSelect( data=["aa", "ab", "ac", "ba", "bb", "bc"], value=["aa"], searchable=True, clearSearchOnChange=False ) ``` ### Autocomplete debounce prop The [Autocomplete](/components/autocomplete) component now supports the [debounce prop.](/debounce) This delays the update of the `value` until the user stops interacting, reducing callback frequency. ### LLMs.txt You can now use LLMs.txt file with Cursor and other IDEs. The file is automatically updated with each release and includes every demo and documentation page from the DMC docs site. It is about 1.6MB. You can find the latest version of LLMs.txt and documentation in the [LLMs](/llms) section.