Right-to-Left
Summit’s components are written with logical properties, so one attribute and one provider mirror a product for a right-to-left script.
Two settings make a product right-to-left. The dir attribute mirrors the layout. Base UI’s DirectionProvider mirrors the behavior: which arrow key moves forward and which side a submenu opens on. You need both because neither sets the other.
Direction
Set dir="rtl" on html, and wrap the app in DirectionProvider with the same direction.
import { DirectionProvider } from '@base-ui/react/direction-provider';
<html lang="ar" dir="rtl">
<body>
<DirectionProvider direction="rtl">{children}</DirectionProvider>
</body>
</html>;DirectionProvider is part of @base-ui/react, which the CLI installs with every component built on Base UI. See the Base UI Direction Provider documentation for direction and useDirection.
The font files in tokens.css have no Arabic or Hebrew glyphs. To set a typeface that has them, see Theming.
The Attribute
Set the attribute on html, not on a wrapper. A Dialog or a menu renders in a portal on body, so its direction comes from html and body alone.
If you set the attribute without the provider, the layout is mirrored, but the behavior isn’t. For example, a Slider fills from the right, and ArrowRight still raises its value.
The rtl Field
In shadcn’s guide to right-to-left, rtl is true in components.json. For Summit, omit the field, or set it to false.
If rtl is true, the CLI rewrites physical classes into logical ones as it writes each file. That rewrite is meant for shadcn’s own sources. Summit’s sources are already written for both directions, and the rewrite breaks the indicator of Tabs and the Segmented Control and the fill of the Progress component.
Layout
The component sources have no physical utilities for padding, margin, border, radius, or text alignment. These are written in their logical form, which the browser resolves against dir.
If no logical form exists, the source uses an rtl: variant.
| Part | Left-to-Right | Right-to-Left |
|---|---|---|
| The thumb of a Switch when it is on | At the right end of the track | At the left end |
| The fill of a Progress bar | Grows from the left | Grows from the right |
| A caret or a separator that points along the reading direction | As drawn | Rotated by 180 degrees |
Behavior
When the app is wrapped in a DirectionProvider, Base UI swaps the horizontal arrow keys and the inline sides of a popup.
| Component | Left-to-Right | Right-to-Left |
|---|---|---|
| Slider | ArrowRight raises the value | ArrowLeft raises the value |
| Tabs, Menubar, and Radio Group | ArrowLeft moves to the previous item | ArrowLeft moves to the next item |
| A submenu of a Dropdown Menu | ArrowRight opens it, to the right of its parent | ArrowLeft opens it, to the left |
| A Dropdown Menu aligned to the start of its trigger | Lines up with the trigger’s left edge | Lines up with the trigger’s right edge |
What Does Not Mirror
These parts keep a physical side or need a prop.
| Part | Behavior | Change |
|---|---|---|
| Sidebar | side is physical and defaults to left | Pass side="right" |
| Sheet | side is physical and defaults to right | Pass side="left" for a Sheet at the end edge |
| Drawer | swipeDirection is physical and sets both the edge and the swipe | Pass swipeDirection="right" for a side Drawer at the start edge |
| Sonner | Toaster keeps its toasts at the bottom right | Pass position="bottom-left" |
| An icon passed to a component | It is drawn as it is in left-to-right | Add rtl:rotate-180 to an arrow or a caret |
To set a physical prop, read the direction with useDirection.
import { Sidebar } from '@/components/ui/sidebar';
import { useDirection } from '@base-ui/react/direction-provider';
const direction = useDirection();
<Sidebar side={direction === 'rtl' ? 'right' : 'left'} />;A Chart isn’t mirrored either. Recharts places the first category at the left in both directions.
See Iconography for which icons to mirror: an icon that shows a direction is mirrored, and a check, a clock, or a logo isn’t.
In Code
Write the product’s own layout with the logical utilities that the components use.
| Physical | Logical |
|---|---|
pl-, pr- | ps-, pe- |
ml-, mr- | ms-, me- |
left-, right- | start-, end- |
border-l, border-r | border-s, border-e |
rounded-l-, rounded-r- | rounded-s-, rounded-e- |
text-left, text-right | text-start, text-end |
ms-auto to push the count to the end of the row.ml-auto is used in a right-to-left layout, the margin stays on the left, so the count is placed next to the label and not at the end of the row.If no logical utility exists, as for a transform, use Tailwind’s rtl: variant.