Skip to content

add DirectionProvider#650

Merged
AnnMarieW merged 7 commits intosnehilvj:masterfrom
AnnMarieW:add-RTL-direction
Sep 11, 2025
Merged

add DirectionProvider#650
AnnMarieW merged 7 commits intosnehilvj:masterfrom
AnnMarieW:add-RTL-direction

Conversation

@AnnMarieW
Copy link
Copy Markdown
Collaborator

@AnnMarieW AnnMarieW commented Sep 8, 2025

Closes #648

  • adds the DirectionProvider component to handle RTL (right-to-left) direction
  1. Wrap the app layout in DirectionProvider
app.layout = dmc.DirectionProivider(
    dmc.MantineProvider([
     # your app layout
     ]),
    direction="rtl"
)
  1. Change the text direction dynamically (like with a toggle switch) by updating the direction prop in a callback

Note - needed to update to the latest Mantine 8.3.0 to get this working with multi-page apps and a theme switch consistently.
New in 8.3.0: DirectionProvider now automatically subscribes to the dir attribute mutations of the root element (usually <html />) and updates internal state automatically.

docs PR: snehilvj/dmc-docs#245

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Sep 8, 2025

Test Environment for snehilvj/dash-mantine-components-650
Updated on: 2025-09-09 00:42:31 UTC

@AnnMarieW
Copy link
Copy Markdown
Collaborator Author

AnnMarieW commented Sep 8, 2025

Here's the code for the sample app hosted on PyCafe
This shows an app with a RTL toggle in header, plus a few components to see how they work in RTL mode.

import dash
import dash_mantine_components as dmc
from dash import Dash, Input, Output, State, callback
from dash_iconify import DashIconify

app = Dash()

logo = "https://github.com/user-attachments/assets/c1ff143b-4365-4fd1-880f-3e97aab5c302"

main = dmc.Box([
    dmc.Select(data=["A", "B", "C"], value="B", label="select"),
    dmc.Slider(
        id="slider-callback",
        value=26,
        marks=[
            {"value": 20, "label": "20%"},
            {"value": 50, "label": "50%"},
            {"value": 80, "label": "80%"},
        ],
        mt=35,
    ),
], p="xl")


layout = dmc.AppShell(
    [
        dmc.AppShellHeader(
            dmc.Group(
                [
                    dmc.Burger(id="burger", size="sm", hiddenFrom="sm", opened=False),
                    dmc.Image(src=logo, h=40, flex=0),
                    dmc.Title("Demo App", c="blue"),
                    dmc.ActionIcon(DashIconify(icon="tabler:text-direction-ltr", width=18),id="rtl-toggle", variant="outline", color="gray")
                ],
                h="100%",
                px="md",
            )
        ),
        dmc.AppShellNavbar(
            id="navbar",
            children=[
                "Navbar",
                *[dmc.Skeleton(height=28, mt="sm", animate=False) for _ in range(15)],
            ],
            p="md",
        ),
        dmc.AppShellMain(main),
    ],
    header={"height": 60},
    padding="md",
    navbar={
        "width": 300,
        "breakpoint": "sm",
        "collapsed": {"mobile": True},
    },
    id="appshell",
)

#
app.layout = dmc.DirectionProvider(dmc.MantineProvider(layout), id="direction", persistence=True, direction="ltr")



@callback(
    Output("appshell", "navbar"),
    Input("burger", "opened"),
    State("appshell", "navbar"),
    prevent_initial_call=True
)
def navbar_is_open(opened, navbar):
    navbar["collapsed"] = {"mobile": not opened}
    return navbar


@callback(
    Output("rtl-toggle", "children"),
    Output("direction", "direction"),
    Input("rtl-toggle", "n_clicks"),
    State("direction", "direction")
)
def toggle_direction(n, d):
    if n is None:
        return dash.no_update

    new_dir = "ltr" if d == "rtl" else "rtl"
    return DashIconify(icon=f"tabler:text-direction-{d}", width=18), new_dir


if __name__ == "__main__":
    app.run(debug=True)

Comment on lines +26 to +30
useEffect(() => {
if (direction && typeof document !== 'undefined') {
document.documentElement.dir = direction;
}
}, [direction]);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to use Mantine's useDirection hook here rather than directly manipulating the DOM?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I started with that but had some issues with setting it initially and the timing with the theme switch. But that might have been solved by upgrading to 8.3.0, so I'll give it another try.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah OK - not a big deal, particularly if this code is essentially what happens inside useDirection anyway. I was concerned they might have covered more edge cases so using their hook would be more robust, but it sounds like the opposite may be true!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like they are setting the direction in the same way: https://github.com/mantinedev/mantine/blob/ece602c7d023513add4c6ce56af45332f059c1f6/packages/%40mantine/core/src/core/DirectionProvider/DirectionProvider.tsx#L43

There are some other features like toggle, but in Dash I think that's easier to do in a callback.

So, do you think this is OK as-is?

Copy link
Copy Markdown
Collaborator

@alexcjohnson alexcjohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks for investigating the hook, I agree it's better as you have it.

@AnnMarieW AnnMarieW merged commit 8f8d578 into snehilvj:master Sep 11, 2025
1 check passed
@AnnMarieW AnnMarieW deleted the add-RTL-direction branch September 11, 2025 00:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Expose DirectionProvider or allow RTL support in DMC

2 participants