Summit
Setup

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.

layout.tsx
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.

PartLeft-to-RightRight-to-Left
The thumb of a Switch when it is onAt the right end of the trackAt the left end
The fill of a Progress barGrows from the leftGrows from the right
A caret or a separator that points along the reading directionAs drawnRotated 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.

ComponentLeft-to-RightRight-to-Left
SliderArrowRight raises the valueArrowLeft raises the value
Tabs, Menubar, and Radio GroupArrowLeft moves to the previous itemArrowLeft moves to the next item
A submenu of a Dropdown MenuArrowRight opens it, to the right of its parentArrowLeft opens it, to the left
A Dropdown Menu aligned to the start of its triggerLines up with the trigger’s left edgeLines up with the trigger’s right edge

What Does Not Mirror

These parts keep a physical side or need a prop.

PartBehaviorChange
Sidebarside is physical and defaults to leftPass side="right"
Sheetside is physical and defaults to rightPass side="left" for a Sheet at the end edge
DrawerswipeDirection is physical and sets both the edge and the swipePass swipeDirection="right" for a side Drawer at the start edge
SonnerToaster keeps its toasts at the bottom rightPass position="bottom-left"
An icon passed to a componentIt is drawn as it is in left-to-rightAdd rtl:rotate-180 to an arrow or a caret

To set a physical prop, read the direction with useDirection.

Sidebar Side
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.

PhysicalLogical
pl-, pr-ps-, pe-
ml-, mr-ms-, me-
left-, right-start-, end-
border-l, border-rborder-s, border-e
rounded-l-, rounded-r-rounded-s-, rounded-e-
text-left, text-righttext-start, text-end
DoUse ms-auto to push the count to the end of the row.
Don’tWhen 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.

On this page