RTL Support
Right-to-left support for shadcn/ui components.
shadcn/ui components have first-class support for right-to-left (RTL) layouts. Text alignment, positioning, and directional styles automatically adapt for languages like Arabic, Hebrew, and Persian.
When you install components, the CLI automatically transforms physical positioning classes to logical equivalents, so your components work seamlessly in both LTR and RTL contexts.
Get Started
Select your framework to get started with RTL support.
Next.js
Create Project
Create a new project using the --rtl flag and the next template.
npx shadcn@latest create --template next --rtl
This will create a components.json file with the rtl: true flag.
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "base-nova",
"rtl": true
}
Add DirectionProvider
Wrap your application with the DirectionProvider component with the direction="rtl" prop.
Then add the dir="rtl" and lang="ar" attributes to the html tag. Update lang="ar" to your target language.
import { DirectionProvider } from "@/components/ui/direction"
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="ar" dir="rtl">
<body>
<DirectionProvider direction="rtl">{children}</DirectionProvider>
</body>
</html>
)
}
Add Font
For the best RTL experience, we recommend using fonts that have proper support for your target language. Noto is a great font family for this and it pairs well with Inter and Geist.
import { Noto_Sans_Arabic } from "next/font/google"
import { DirectionProvider } from "@/components/ui/direction"
const fontSans = Noto_Sans_Arabic({
subsets: ["arabic"],
variable: "--font-sans",
})
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="ar" dir="rtl" className={fontSans.variable}>
<body>
<DirectionProvider direction="rtl">{children}</DirectionProvider>
</body>
</html>
)
}
For other languages, eg. Hebrew, you can use the Noto_Sans_Hebrew font.
Add Components
You are now ready to add components to your project. The CLI will take care of handling RTL support for you.
npx shadcn@latest add item
Vite
Create Project
Create a new project using the --rtl flag and the vite template.
npx shadcn@latest create --template vite --rtl
This will create a components.json file with the rtl: true flag.
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "base-nova",
"rtl": true
}
Add DirectionProvider
Add the dir="rtl" and lang="ar" attributes to the html tag in your index.html. Update lang="ar" to your target language.
<!doctype html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Then wrap your app with the DirectionProvider component with the direction="rtl" prop in your main.tsx:
import { StrictMode } from "react"
import { createRoot } from "react-dom/client"
import { DirectionProvider } from "@/components/ui/direction"
import App from "./App"
import "./index.css"
createRoot(document.getElementById("root")!).render(
<StrictMode>
<DirectionProvider direction="rtl">
<App />
</DirectionProvider>
</StrictMode>
)
Add Font
For the best RTL experience, we recommend using fonts that have proper support for your target language.
Install the font using Fontsource:
npm install @fontsource-variable/noto-sans-arabic
Import the font in your index.css:
@import "tailwindcss";
@import "tw-animate-css";
@import "shadcn/tailwind.css";
@import "@fontsource-variable/noto-sans-arabic";
@theme inline {
--font-sans: "Noto Sans Arabic Variable", sans-serif;
}
For other languages, eg. Hebrew, you can use @fontsource-variable/noto-sans-hebrew.
Add Components
You are now ready to add components to your project. The CLI will take care of handling RTL support for you.
npx shadcn@latest add item
How It Works
When you add components with rtl: true set in your components.json, the shadcn CLI automatically transforms classes and props to be RTL compatible:
- Physical positioning classes like
left-*andright-*are converted to logical equivalents likestart-*andend-*. - Directional props are updated to use logical values.
- Text alignment and spacing classes are adjusted accordingly.
- Supported icons are automatically flipped using
rtl:rotate-180.
Supported Styles
Automatic RTL transformation via the CLI is only available for projects created using shadcn create with the new styles (base-nova, radix-nova, etc.).
Font Recommendations
For the best RTL experience, we recommend using fonts that have proper support for your target language. Noto is a great font family for this and it pairs well with Inter and Geist.
Animations
The CLI also handles animation classes, automatically transforming physical directional animations to their logical equivalents. For example, slide-in-from-right becomes slide-in-from-end.
This ensures animations like dropdowns, popovers, and tooltips animate in the correct direction based on the document's text direction.
A note on tw-animate-css:
There is a known issue with the tw-animate-css library where the logical slide utilities are not working as expected. For now, make sure you pass in the dir prop to portal elements.
<Popover>
<PopoverTrigger>Open</PopoverTrigger>
<PopoverContent dir="rtl">
<div>Content</div>
</PopoverContent>
</Popover>
<Tooltip>
<TooltipTrigger>Open</TooltipTrigger>
<TooltipContent dir="rtl">
<div>Content</div>
</TooltipContent>
</Tooltip>
Migrating Existing Components
If you have existing components installed before enabling RTL, you can migrate them using the CLI as follows:
npx shadcn@latest migrate rtl [path]
[path] accepts a path or glob pattern to migrate. If you don't provide a path, it will migrate all the files in the ui directory.
Manual Migration (Optional)
The following components are not automatically migrated by the CLI. Follow the RTL support section for each component to manually migrate them.
- Calendar
- Pagination
- Sidebar
Migrate Icons
Some icons like ArrowRightIcon or ChevronLeftIcon might need the rtl:rotate-180 class to be flipped correctly. Add the rtl:rotate-180 class to the icon component to flip it correctly.
<ArrowRightIcon className="rtl:rotate-180" />
Add Direction Component
Add the direction component to your project.
npx shadcn@latest add direction
Add DirectionProvider
Follow your framework's documentation for details on how to add the DirectionProvider component to your project.