diff --git a/.changeset/kind-candies-float.md b/.changeset/kind-candies-float.md
deleted file mode 100644
index 4f7b86391e..0000000000
--- a/.changeset/kind-candies-float.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"shadcn": patch
----
-
-Fix: skip all transforms for universal registry items
diff --git a/.github/changeset-version.js b/.github/changeset-version.js
index e1b4cef66f..ea1fc05e66 100644
--- a/.github/changeset-version.js
+++ b/.github/changeset-version.js
@@ -1,12 +1,12 @@
// ORIGINALLY FROM CLOUDFLARE WRANGLER:
// https://github.com/cloudflare/wrangler2/blob/main/.github/changeset-version.js
-import { exec } from "child_process"
+import { execSync } from "child_process"
// This script is used by the `release.yml` workflow to update the version of the packages being released.
-// The standard step is only to run `changeset version` but this does not update the package-lock.json file.
-// So we also run `npm install`, which does this update.
+// The standard step is only to run `changeset version` but this does not update the pnpm-lock.yaml file.
+// So we also run `pnpm install`, which does this update.
// This is a workaround until this is handled automatically by `changeset version`.
// See https://github.com/changesets/changesets/issues/421.
-exec("npx changeset version")
-exec("npm install")
+execSync("npx changeset version", { stdio: "inherit" })
+execSync("pnpm install --lockfile-only", { stdio: "inherit" })
diff --git a/apps/v4/app/(app)/(root)/components/button-group-demo.tsx b/apps/v4/app/(app)/(root)/components/button-group-demo.tsx
index bdf259d1d5..ccfc877544 100644
--- a/apps/v4/app/(app)/(root)/components/button-group-demo.tsx
+++ b/apps/v4/app/(app)/(root)/components/button-group-demo.tsx
@@ -56,7 +56,7 @@ export function ButtonGroupDemo() {
-
+
diff --git a/apps/v4/app/(app)/(root)/components/field-demo.tsx b/apps/v4/app/(app)/(root)/components/field-demo.tsx
index 795129225d..035bcd5107 100644
--- a/apps/v4/app/(app)/(root)/components/field-demo.tsx
+++ b/apps/v4/app/(app)/(root)/components/field-demo.tsx
@@ -13,6 +13,7 @@ import { Input } from "@/examples/radix/ui/input"
import {
Select,
SelectContent,
+ SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
@@ -69,18 +70,20 @@ export function FieldDemo() {
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
+
+ 01
+ 02
+ 03
+ 04
+ 05
+ 06
+ 07
+ 08
+ 09
+ 10
+ 11
+ 12
+
@@ -93,12 +96,14 @@ export function FieldDemo() {
- 2024
- 2025
- 2026
- 2027
- 2028
- 2029
+
+ 2024
+ 2025
+ 2026
+ 2027
+ 2028
+ 2029
+
diff --git a/apps/v4/app/(app)/(root)/components/field-hear.tsx b/apps/v4/app/(app)/(root)/components/field-hear.tsx
index ad28d31289..704cdc9aee 100644
--- a/apps/v4/app/(app)/(root)/components/field-hear.tsx
+++ b/apps/v4/app/(app)/(root)/components/field-hear.tsx
@@ -50,7 +50,7 @@ export function FieldHear() {
>
Auto
-
+ AutoAgentManual
diff --git a/apps/v4/app/(app)/docs/[[...slug]]/page.tsx b/apps/v4/app/(app)/docs/[[...slug]]/page.tsx
index 49c018249c..d531d3acad 100644
--- a/apps/v4/app/(app)/docs/[[...slug]]/page.tsx
+++ b/apps/v4/app/(app)/docs/[[...slug]]/page.tsx
@@ -95,12 +95,14 @@ export default async function Page(props: {
-
-
+
+
{doc.title}
-
-
+
+
+
+
{neighbours.previous && (
-
+
{doc.toc?.length ? (
diff --git a/apps/v4/app/(app)/docs/changelog/page.tsx b/apps/v4/app/(app)/docs/changelog/page.tsx
index 0893562065..eb32733b67 100644
--- a/apps/v4/app/(app)/docs/changelog/page.tsx
+++ b/apps/v4/app/(app)/docs/changelog/page.tsx
@@ -82,21 +82,25 @@ export default function ChangelogPage() {
More Updates
-
+
{olderPages.map((page) => {
const data = page.data as ChangelogPageData
+ const [date, ...titleParts] = data.title.split(" - ")
+ const title = titleParts.join(" - ")
return (
-
-
- {data.title}
-
-
+
+
+ {date}
+
+ {title}
+
)
})}
-
+
)}
diff --git a/apps/v4/app/(app)/docs/layout.tsx b/apps/v4/app/(app)/docs/layout.tsx
index 339c2ca804..465f5d0665 100644
--- a/apps/v4/app/(app)/docs/layout.tsx
+++ b/apps/v4/app/(app)/docs/layout.tsx
@@ -11,7 +11,11 @@ export default function DocsLayout({
{children}
diff --git a/apps/v4/app/(app)/examples/layout.tsx b/apps/v4/app/(app)/examples/layout.tsx
index 4267903319..b8c5b03105 100644
--- a/apps/v4/app/(app)/examples/layout.tsx
+++ b/apps/v4/app/(app)/examples/layout.tsx
@@ -70,7 +70,7 @@ export default function ExamplesLayout({
-
+
{children}
diff --git a/apps/v4/app/(app)/examples/playground/components/maxlength-selector.tsx b/apps/v4/app/(app)/examples/playground/components/maxlength-selector.tsx
index 3a19f81384..44008c9e2d 100644
--- a/apps/v4/app/(app)/examples/playground/components/maxlength-selector.tsx
+++ b/apps/v4/app/(app)/examples/playground/components/maxlength-selector.tsx
@@ -1,7 +1,7 @@
"use client"
import * as React from "react"
-import { type SliderProps } from "@radix-ui/react-slider"
+import type { Slider as SliderPrimitive } from "radix-ui"
import {
HoverCard,
@@ -12,7 +12,9 @@ import { Label } from "@/registry/new-york-v4/ui/label"
import { Slider } from "@/registry/new-york-v4/ui/slider"
interface MaxLengthSelectorProps {
- defaultValue: SliderProps["defaultValue"]
+ defaultValue: React.ComponentProps<
+ typeof SliderPrimitive.Root
+ >["defaultValue"]
}
export function MaxLengthSelector({ defaultValue }: MaxLengthSelectorProps) {
diff --git a/apps/v4/app/(app)/examples/playground/components/model-selector.tsx b/apps/v4/app/(app)/examples/playground/components/model-selector.tsx
index 5e7dfcb8b4..908dba2dcb 100644
--- a/apps/v4/app/(app)/examples/playground/components/model-selector.tsx
+++ b/apps/v4/app/(app)/examples/playground/components/model-selector.tsx
@@ -1,8 +1,8 @@
"use client"
import * as React from "react"
-import { type PopoverProps } from "@radix-ui/react-popover"
import { Check, ChevronsUpDown } from "lucide-react"
+import type { Popover as PopoverPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
import { useMutationObserver } from "@/hooks/use-mutation-observer"
@@ -29,7 +29,8 @@ import {
import { type Model, type ModelType } from "../data/models"
-interface ModelSelectorProps extends PopoverProps {
+interface ModelSelectorProps
+ extends React.ComponentProps {
types: readonly ModelType[]
models: Model[]
}
diff --git a/apps/v4/app/(app)/examples/playground/components/preset-actions.tsx b/apps/v4/app/(app)/examples/playground/components/preset-actions.tsx
index 3f0e80fc28..a1178653c5 100644
--- a/apps/v4/app/(app)/examples/playground/components/preset-actions.tsx
+++ b/apps/v4/app/(app)/examples/playground/components/preset-actions.tsx
@@ -1,7 +1,6 @@
"use client"
import * as React from "react"
-import { Dialog } from "@radix-ui/react-dialog"
import { MoreHorizontal } from "lucide-react"
import { toast } from "sonner"
@@ -16,6 +15,7 @@ import {
} from "@/registry/new-york-v4/ui/alert-dialog"
import { Button } from "@/registry/new-york-v4/ui/button"
import {
+ Dialog,
DialogClose,
DialogContent,
DialogDescription,
diff --git a/apps/v4/app/(app)/examples/playground/components/preset-selector.tsx b/apps/v4/app/(app)/examples/playground/components/preset-selector.tsx
index f764fcb280..aa9944535b 100644
--- a/apps/v4/app/(app)/examples/playground/components/preset-selector.tsx
+++ b/apps/v4/app/(app)/examples/playground/components/preset-selector.tsx
@@ -1,8 +1,8 @@
"use client"
import * as React from "react"
-import { type PopoverProps } from "@radix-ui/react-popover"
import { Check, ChevronsUpDown } from "lucide-react"
+import type { Popover as PopoverPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/new-york-v4/ui/button"
@@ -23,7 +23,8 @@ import {
import { type Preset } from "../data/presets"
-interface PresetSelectorProps extends PopoverProps {
+interface PresetSelectorProps
+ extends React.ComponentProps {
presets: Preset[]
}
diff --git a/apps/v4/app/(app)/examples/playground/components/temperature-selector.tsx b/apps/v4/app/(app)/examples/playground/components/temperature-selector.tsx
index 7dbbdbb253..cbf308bd64 100644
--- a/apps/v4/app/(app)/examples/playground/components/temperature-selector.tsx
+++ b/apps/v4/app/(app)/examples/playground/components/temperature-selector.tsx
@@ -1,7 +1,7 @@
"use client"
import * as React from "react"
-import { type SliderProps } from "@radix-ui/react-slider"
+import type { Slider as SliderPrimitive } from "radix-ui"
import {
HoverCard,
@@ -12,7 +12,9 @@ import { Label } from "@/registry/new-york-v4/ui/label"
import { Slider } from "@/registry/new-york-v4/ui/slider"
interface TemperatureSelectorProps {
- defaultValue: SliderProps["defaultValue"]
+ defaultValue: React.ComponentProps<
+ typeof SliderPrimitive.Root
+ >["defaultValue"]
}
export function TemperatureSelector({
diff --git a/apps/v4/app/(app)/examples/playground/components/top-p-selector.tsx b/apps/v4/app/(app)/examples/playground/components/top-p-selector.tsx
index a33bd2c2b1..1f02acd323 100644
--- a/apps/v4/app/(app)/examples/playground/components/top-p-selector.tsx
+++ b/apps/v4/app/(app)/examples/playground/components/top-p-selector.tsx
@@ -1,7 +1,7 @@
"use client"
import * as React from "react"
-import { type SliderProps } from "@radix-ui/react-slider"
+import type { Slider as SliderPrimitive } from "radix-ui"
import {
HoverCard,
@@ -12,7 +12,9 @@ import { Label } from "@/registry/new-york-v4/ui/label"
import { Slider } from "@/registry/new-york-v4/ui/slider"
interface TopPSelectorProps {
- defaultValue: SliderProps["defaultValue"]
+ defaultValue: React.ComponentProps<
+ typeof SliderPrimitive.Root
+ >["defaultValue"]
}
export function TopPSelector({ defaultValue }: TopPSelectorProps) {
diff --git a/apps/v4/app/(app)/examples/rtl/components/appearance-settings.tsx b/apps/v4/app/(app)/examples/rtl/components/appearance-settings.tsx
new file mode 100644
index 0000000000..2ec0b008d6
--- /dev/null
+++ b/apps/v4/app/(app)/examples/rtl/components/appearance-settings.tsx
@@ -0,0 +1,170 @@
+"use client"
+
+import * as React from "react"
+import { Button } from "@/examples/base/ui-rtl/button"
+import { ButtonGroup } from "@/examples/base/ui-rtl/button-group"
+import {
+ Field,
+ FieldContent,
+ FieldDescription,
+ FieldGroup,
+ FieldLabel,
+ FieldLegend,
+ FieldSeparator,
+ FieldSet,
+ FieldTitle,
+} from "@/examples/base/ui-rtl/field"
+import { Input } from "@/examples/base/ui-rtl/input"
+import { RadioGroup, RadioGroupItem } from "@/examples/base/ui-rtl/radio-group"
+import { Switch } from "@/examples/base/ui-rtl/switch"
+import { IconMinus, IconPlus } from "@tabler/icons-react"
+
+import { useLanguageContext } from "@/components/language-selector"
+
+const translations = {
+ ar: {
+ dir: "rtl" as const,
+ computeEnvironment: "بيئة الحوسبة",
+ computeDescription: "اختر بيئة الحوسبة لمجموعتك.",
+ kubernetes: "كوبرنيتس",
+ kubernetesDescription:
+ "تشغيل أحمال عمل GPU على مجموعة مُهيأة بـ K8s. هذا هو الافتراضي.",
+ virtualMachine: "جهاز افتراضي",
+ vmDescription: "الوصول إلى مجموعة VM مُهيأة لتشغيل أحمال العمل. (قريبًا)",
+ numberOfGpus: "عدد وحدات GPU",
+ gpuDescription: "يمكنك إضافة المزيد لاحقًا.",
+ decrement: "إنقاص",
+ increment: "زيادة",
+ wallpaperTinting: "تلوين الخلفية",
+ wallpaperDescription: "السماح بتلوين الخلفية.",
+ },
+ he: {
+ dir: "rtl" as const,
+ computeEnvironment: "סביבת מחשוב",
+ computeDescription: "בחר את סביבת המחשוב לאשכול שלך.",
+ kubernetes: "קוברנטיס",
+ kubernetesDescription:
+ "הפעל עומסי עבודה של GPU באשכול מוגדר K8s. זו ברירת המחדל.",
+ virtualMachine: "מכונה וירטואלית",
+ vmDescription: "גש לאשכול VM מוגדר להפעלת עומסי עבודה. (בקרוב)",
+ numberOfGpus: "מספר GPUs",
+ gpuDescription: "תוכל להוסיף עוד מאוחר יותר.",
+ decrement: "הפחת",
+ increment: "הגדל",
+ wallpaperTinting: "צביעת טפט",
+ wallpaperDescription: "אפשר לטפט להיצבע.",
+ },
+}
+
+export function AppearanceSettings() {
+ const context = useLanguageContext()
+ const lang = context?.language === "he" ? "he" : "ar"
+ const t = translations[lang]
+ const [gpuCount, setGpuCount] = React.useState(8)
+
+ const handleGpuAdjustment = React.useCallback((adjustment: number) => {
+ setGpuCount((prevCount) =>
+ Math.max(1, Math.min(99, prevCount + adjustment))
+ )
+ }, [])
+
+ const handleGpuInputChange = React.useCallback(
+ (e: React.ChangeEvent) => {
+ const value = parseInt(e.target.value, 10)
+ if (!isNaN(value) && value >= 1 && value <= 99) {
+ setGpuCount(value)
+ }
+ },
+ []
+ )
+
+ return (
+
{`// You will notice this example uses dir and data-lang attributes.
+// This is because this site is not RTL by default.
+// In your application, you won't need these.`}
+
+ {"// See the "}
+
+ RTL guide
+
+ {" for more information."}
+
+
)
}
diff --git a/apps/v4/content/docs/(root)/cli.mdx b/apps/v4/content/docs/(root)/cli.mdx
index ef7985fa20..c425221541 100644
--- a/apps/v4/content/docs/(root)/cli.mdx
+++ b/apps/v4/content/docs/(root)/cli.mdx
@@ -223,3 +223,113 @@ To customize the output directory, use the `--output` option.
```bash
npx shadcn@latest build --output ./public/registry
```
+
+---
+
+## migrate
+
+Use the `migrate` command to run migrations on your project.
+
+```bash
+npx shadcn@latest migrate [migration]
+```
+
+**Available Migrations**
+
+| Migration | Description |
+| --------- | ------------------------------------------------------- |
+| `icons` | Migrate your UI components to a different icon library. |
+| `radix` | Migrate to radix-ui. |
+| `rtl` | Migrate your components to support RTL (right-to-left). |
+
+**Options**
+
+```bash
+Usage: shadcn migrate [options] [migration] [path]
+
+run a migration.
+
+Arguments:
+ migration the migration to run.
+ path optional path or glob pattern to migrate.
+
+Options:
+ -c, --cwd the working directory. defaults to the current directory.
+ -l, --list list all migrations. (default: false)
+ -y, --yes skip confirmation prompt. (default: false)
+ -h, --help display help for command
+```
+
+---
+
+### migrate rtl
+
+The `rtl` migration transforms your components to support RTL (right-to-left) languages.
+
+```bash
+npx shadcn@latest migrate rtl
+```
+
+This will:
+
+1. Update `components.json` to set `rtl: true`
+2. Transform physical CSS properties to logical equivalents (e.g., `ml-4` → `ms-4`, `text-left` → `text-start`)
+3. Add `rtl:` variants where needed (e.g., `space-x-4` → `space-x-4 rtl:space-x-reverse`)
+
+**Migrate specific files**
+
+You can migrate specific files or use glob patterns:
+
+```bash
+# Migrate a specific file
+npx shadcn@latest migrate rtl src/components/ui/button.tsx
+
+# Migrate files matching a glob pattern
+npx shadcn@latest migrate rtl "src/components/ui/**"
+```
+
+If no path is provided, the migration will transform all files in your `ui` directory (from `components.json`).
+
+---
+
+### migrate radix
+
+The `radix` migration updates your imports from individual `@radix-ui/react-*` packages to the unified `radix-ui` package.
+
+```bash
+npx shadcn@latest migrate radix
+```
+
+This will:
+
+1. Transform imports from `@radix-ui/react-*` to `radix-ui`
+2. Add the `radix-ui` package to your `package.json`
+
+**Before**
+
+```tsx
+import * as DialogPrimitive from "@radix-ui/react-dialog"
+import * as SelectPrimitive from "@radix-ui/react-select"
+```
+
+**After**
+
+```tsx
+import { Dialog as DialogPrimitive, Select as SelectPrimitive } from "radix-ui"
+```
+
+**Migrate specific files**
+
+You can migrate specific files or use glob patterns:
+
+```bash
+# Migrate a specific file.
+npx shadcn@latest migrate radix src/components/ui/dialog.tsx
+
+# Migrate files matching a glob pattern.
+npx shadcn@latest migrate radix "src/components/ui/**"
+```
+
+If no path is provided, the migration will transform all files in your `ui` directory (from `components.json`).
+
+Once complete, you can remove any unused `@radix-ui/react-*` packages from your `package.json`.
diff --git a/apps/v4/content/docs/(root)/meta.json b/apps/v4/content/docs/(root)/meta.json
index 5c2f3e1a78..d5b1f56a05 100644
--- a/apps/v4/content/docs/(root)/meta.json
+++ b/apps/v4/content/docs/(root)/meta.json
@@ -6,6 +6,7 @@
"components-json",
"theming",
"[Dark Mode](/docs/dark-mode)",
+ "[RTL](/docs/rtl)",
"[CLI](/docs/cli)",
"monorepo",
"typography",
diff --git a/apps/v4/content/docs/changelog/2026-01-rtl.mdx b/apps/v4/content/docs/changelog/2026-01-rtl.mdx
new file mode 100644
index 0000000000..5c1b1ea147
--- /dev/null
+++ b/apps/v4/content/docs/changelog/2026-01-rtl.mdx
@@ -0,0 +1,82 @@
+---
+title: January 2026 - RTL Support
+description: The shadcn CLI now supports RTL (right-to-left) layouts by automatically converting physical CSS classes to logical equivalents.
+date: 2026-01-28
+---
+
+shadcn/ui now has first-class support for right-to-left (RTL) layouts. Your components automatically adapt for languages like Arabic, Hebrew, and Persian.
+
+**This works with the [shadcn/ui components](/docs/components) as well as any component distributed on the shadcn registry.**
+
+
+
+### Our approach to RTL
+
+Traditionally, component libraries that support RTL ship with logical classes baked in. This means everyone has to work with classes like `ms-4` and `start-2`, even if they're only building for LTR layouts.
+
+We took a different approach. The shadcn CLI transforms classes at install time, so you only see logical classes when you actually need them. If you're not building for RTL, you work with familiar classes like `ml-4` and `left-2`. When you enable RTL, the CLI handles the conversion for you.
+
+**You don't have to learn RTL until you need it.**
+
+### How it works
+
+When you add components with `rtl: true` set in your `components.json`, the CLI automatically converts physical CSS classes like `ml-4` and `text-left` to their logical equivalents like `ms-4` and `text-start`.
+
+- Physical positioning classes like `left-*` and `right-*` become `start-*` and `end-*`.
+- Margin and padding classes like `ml-*` and `pr-*` become `ms-*` and `pe-*`.
+- Text alignment classes like `text-left` become `text-start`.
+- Directional props are updated to use logical values.
+- Supported icons are automatically flipped using `rtl:rotate-180`.
+- Animations like `slide-in-from-left` become `slide-in-from-start`.
+
+### RTL examples for every component
+
+We've added RTL examples for every component. You'll find live previews and code on each [component page](/docs/components).
+
+
+
+### CLI updates
+
+**New projects**: Use the `--rtl` flag with `init` or `create` to enable RTL from the start.
+
+```bash
+npx shadcn@latest init --rtl
+```
+
+```bash
+npx shadcn@latest create --rtl
+```
+
+**Existing projects**: Migrate your components with the `migrate rtl` command.
+
+```bash
+npx shadcn@latest migrate rtl
+```
+
+This transforms all components in your `ui` directory to use logical classes. You can also pass a specific path or glob pattern.
+
+## Try it out
+
+Click the link below to open a Next.js project with RTL support in v0.
+
+[](https://v0.app/chat/api/open?url=https://github.com/shadcn-ui/next-template-rtl)
+
+### Links
+
+- [RTL Documentation](/docs/rtl)
+- [Font Recommendations](/docs/rtl#font-recommendations)
+- [Animations](/docs/rtl#animations)
+- [Migrating Existing Components](/docs/rtl#migrating-existing-components)
+- [Next.js Setup](/docs/rtl/next)
+- [Vite Setup](/docs/rtl/vite)
+- [TanStack Start Setup](/docs/rtl/start)
diff --git a/apps/v4/content/docs/changelog/2026-02-radix-ui.mdx b/apps/v4/content/docs/changelog/2026-02-radix-ui.mdx
new file mode 100644
index 0000000000..2d5aa38313
--- /dev/null
+++ b/apps/v4/content/docs/changelog/2026-02-radix-ui.mdx
@@ -0,0 +1,38 @@
+---
+title: February 2026 - Unified Radix UI Package
+description: The new-york style now uses the unified radix-ui package.
+date: 2026-02-02
+---
+
+The `new-york` style now uses the unified `radix-ui` package instead of individual `@radix-ui/react-*` packages.
+
+### What's Changed
+
+When you add components using the `new-york` style, they will now import from `radix-ui` instead of separate packages:
+
+```diff title="components/ui/dialog.tsx"
+- import * as DialogPrimitive from "@radix-ui/react-dialog"
++ import { Dialog as DialogPrimitive } from "radix-ui"
+```
+
+This results in a cleaner `package.json` with a single `radix-ui` dependency instead of multiple `@radix-ui/react-*` packages.
+
+### Migrating Existing Projects
+
+If you have an existing project using the `new-york` style, you can migrate to the new `radix-ui` package using the migrate command:
+
+```bash
+npx shadcn@latest migrate radix
+```
+
+This will update all imports in your UI components and add `radix-ui` to your dependencies.
+
+To migrate components outside of your `ui` directory, use the `path` argument:
+
+```bash
+npx shadcn@latest migrate radix src/components/custom
+```
+
+Once complete, you can remove any unused `@radix-ui/react-*` packages from your `package.json`.
+
+See the [migrate radix documentation](/docs/cli#migrate-radix) for more details.
diff --git a/apps/v4/content/docs/components/base/accordion.mdx b/apps/v4/content/docs/components/base/accordion.mdx
index 61f67a072f..900722e273 100644
--- a/apps/v4/content/docs/components/base/accordion.mdx
+++ b/apps/v4/content/docs/components/base/accordion.mdx
@@ -137,6 +137,17 @@ Wrap the `Accordion` in a `Card` component.
previewClassName="*:data-[slot=accordion]:max-w-sm h-[435px]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI](https://base-ui.com/react/components/accordion#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/base/alert-dialog.mdx b/apps/v4/content/docs/components/base/alert-dialog.mdx
index 98f759d182..a8fa565e3b 100644
--- a/apps/v4/content/docs/components/base/alert-dialog.mdx
+++ b/apps/v4/content/docs/components/base/alert-dialog.mdx
@@ -146,6 +146,17 @@ Use the `AlertDialogAction` component to add a destructive action button to the
previewClassName="h-56"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### size
diff --git a/apps/v4/content/docs/components/base/alert.mdx b/apps/v4/content/docs/components/base/alert.mdx
index 4ceac8a1f3..924e6a6ccb 100644
--- a/apps/v4/content/docs/components/base/alert.mdx
+++ b/apps/v4/content/docs/components/base/alert.mdx
@@ -109,6 +109,17 @@ You can customize the alert colors by adding custom classes such as `bg-amber-50
previewClassName="h-auto sm:h-72 p-6"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Alert
diff --git a/apps/v4/content/docs/components/base/aspect-ratio.mdx b/apps/v4/content/docs/components/base/aspect-ratio.mdx
index 10ad08bf7c..e9ba8cb2b7 100644
--- a/apps/v4/content/docs/components/base/aspect-ratio.mdx
+++ b/apps/v4/content/docs/components/base/aspect-ratio.mdx
@@ -79,6 +79,17 @@ A portrait aspect ratio component using the `ratio={9 / 16}` prop. This is usefu
previewClassName="h-96"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### AspectRatio
diff --git a/apps/v4/content/docs/components/base/avatar.mdx b/apps/v4/content/docs/components/base/avatar.mdx
index e778664fb2..7005036e9a 100644
--- a/apps/v4/content/docs/components/base/avatar.mdx
+++ b/apps/v4/content/docs/components/base/avatar.mdx
@@ -129,6 +129,17 @@ You can use the `Avatar` component as a trigger for a dropdown menu.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Avatar
diff --git a/apps/v4/content/docs/components/base/badge.mdx b/apps/v4/content/docs/components/base/badge.mdx
index 97807baa4b..b91a24df94 100644
--- a/apps/v4/content/docs/components/base/badge.mdx
+++ b/apps/v4/content/docs/components/base/badge.mdx
@@ -85,6 +85,12 @@ You can customize the colors of a badge by adding custom classes such as `bg-gre
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Badge
diff --git a/apps/v4/content/docs/components/base/breadcrumb.mdx b/apps/v4/content/docs/components/base/breadcrumb.mdx
index 001bfb39f8..2de58ab85b 100644
--- a/apps/v4/content/docs/components/base/breadcrumb.mdx
+++ b/apps/v4/content/docs/components/base/breadcrumb.mdx
@@ -116,6 +116,17 @@ To use a custom link component from your routing library, you can use the `rende
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Breadcrumb
diff --git a/apps/v4/content/docs/components/base/button-group.mdx b/apps/v4/content/docs/components/base/button-group.mdx
index 8f9a772dce..aa2dfb98e8 100644
--- a/apps/v4/content/docs/components/base/button-group.mdx
+++ b/apps/v4/content/docs/components/base/button-group.mdx
@@ -148,6 +148,16 @@ Use with a `Popover` component.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### ButtonGroup
diff --git a/apps/v4/content/docs/components/base/button.mdx b/apps/v4/content/docs/components/base/button.mdx
index dbc1d8a4cc..4fdf651371 100644
--- a/apps/v4/content/docs/components/base/button.mdx
+++ b/apps/v4/content/docs/components/base/button.mdx
@@ -143,6 +143,12 @@ Remember to set the `nativeButton` prop to `false` if you're returning an elemen
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Button
diff --git a/apps/v4/content/docs/components/base/calendar.mdx b/apps/v4/content/docs/components/base/calendar.mdx
index 08d67f54d5..4a61857fff 100644
--- a/apps/v4/content/docs/components/base/calendar.mdx
+++ b/apps/v4/content/docs/components/base/calendar.mdx
@@ -237,270 +237,174 @@ Use `showWeekNumber` to show week numbers.
previewClassName="h-96"
/>
-## Upgrade Guide
+## RTL
-### Tailwind v4
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
-If you're already using Tailwind v4, you can upgrade to the latest version of the `Calendar` component by running the following command:
+See also the [Hijri Guide](#persian--hijri--jalali-calendar) for enabling the Persian / Hijri / Jalali calendar.
-```bash
-npx shadcn@latest add calendar
+
+
+When using RTL, import the locale from `react-day-picker/locale` and pass both the `locale` and `dir` props to the Calendar component:
+
+```tsx showLineNumbers
+import { arSA } from "react-day-picker/locale"
+
+;
```
-When you're prompted to overwrite the existing `Calendar` component, select `Yes`. **If you have made any changes to the `Calendar` component, you will need to merge your changes with the new version.**
-
-This will update the `Calendar` component and `react-day-picker` to the latest version.
-
-Next, follow the [React DayPicker](https://daypicker.dev/upgrading) upgrade guide to upgrade your existing components to the latest version.
-
-#### Installing Blocks
-
-After upgrading the `Calendar` component, you can install the new blocks by running the `shadcn@latest add` command.
-
-```bash
-npx shadcn@latest add calendar-02
-```
-
-This will install the latest version of the calendar blocks.
-
-### Tailwind v3
-
-If you're using Tailwind v3, you can upgrade to the latest version of the `Calendar` by copying the following code to your `calendar.tsx` file.
-
-
-
-```tsx showLineNumbers title="components/ui/calendar.tsx"
-"use client"
-
-import * as React from "react"
-import {
- ChevronDownIcon,
- ChevronLeftIcon,
- ChevronRightIcon,
-} from "lucide-react"
-import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"
-
-import { cn } from "@/lib/utils"
-import { Button, buttonVariants } from "@/components/ui/button"
-
-function Calendar({
- className,
- classNames,
- showOutsideDays = true,
- captionLayout = "label",
- buttonVariant = "ghost",
- formatters,
- components,
- ...props
-}: React.ComponentProps & {
- buttonVariant?: React.ComponentProps["variant"]
-}) {
- const defaultClassNames = getDefaultClassNames()
-
- return (
- svg]:rotate-180`,
- String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
- className
- )}
- captionLayout={captionLayout}
- formatters={{
- formatMonthDropdown: (date) =>
- date.toLocaleString("default", { month: "short" }),
- ...formatters,
- }}
- classNames={{
- root: cn("w-fit", defaultClassNames.root),
- months: cn(
- "relative flex flex-col gap-4 md:flex-row",
- defaultClassNames.months
- ),
- month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
- nav: cn(
- "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
- defaultClassNames.nav
- ),
- button_previous: cn(
- buttonVariants({ variant: buttonVariant }),
- "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
- defaultClassNames.button_previous
- ),
- button_next: cn(
- buttonVariants({ variant: buttonVariant }),
- "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
- defaultClassNames.button_next
- ),
- month_caption: cn(
- "flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]",
- defaultClassNames.month_caption
- ),
- dropdowns: cn(
- "flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium",
- defaultClassNames.dropdowns
- ),
- dropdown_root: cn(
- "has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border",
- defaultClassNames.dropdown_root
- ),
- dropdown: cn("absolute inset-0 opacity-0", defaultClassNames.dropdown),
- caption_label: cn(
- "select-none font-medium",
- captionLayout === "label"
- ? "text-sm"
- : "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5",
- defaultClassNames.caption_label
- ),
- table: "w-full border-collapse",
- weekdays: cn("flex", defaultClassNames.weekdays),
- weekday: cn(
- "text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal",
- defaultClassNames.weekday
- ),
- week: cn("mt-2 flex w-full", defaultClassNames.week),
- week_number_header: cn(
- "w-[--cell-size] select-none",
- defaultClassNames.week_number_header
- ),
- week_number: cn(
- "text-muted-foreground select-none text-[0.8rem]",
- defaultClassNames.week_number
- ),
- day: cn(
- "relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
- props.showWeekNumber
- ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md"
- : "[&:first-child[data-selected=true]_button]:rounded-l-md",
- defaultClassNames.day
- ),
- range_start: cn(
- "bg-accent rounded-l-md",
- defaultClassNames.range_start
- ),
- range_middle: cn("rounded-none", defaultClassNames.range_middle),
- range_end: cn("bg-accent rounded-r-md", defaultClassNames.range_end),
- today: cn(
- "bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
- defaultClassNames.today
- ),
- outside: cn(
- "text-muted-foreground aria-selected:text-muted-foreground",
- defaultClassNames.outside
- ),
- disabled: cn(
- "text-muted-foreground opacity-50",
- defaultClassNames.disabled
- ),
- hidden: cn("invisible", defaultClassNames.hidden),
- ...classNames,
- }}
- components={{
- Root: ({ className, rootRef, ...props }) => {
- return (
-
- )
- },
- Chevron: ({ className, orientation, ...props }) => {
- if (orientation === "left") {
- return (
-
- )
- }
-
- if (orientation === "right") {
- return (
-
- )
- }
-
- return (
-
- )
- },
- DayButton: CalendarDayButton,
- WeekNumber: ({ children, ...props }) => {
- return (
-
-
- {children}
-
-
- )
- },
- ...components,
- }}
- {...props}
- />
- )
-}
-
-function CalendarDayButton({
- className,
- day,
- modifiers,
- ...props
-}: React.ComponentProps) {
- const defaultClassNames = getDefaultClassNames()
-
- const ref = React.useRef(null)
- React.useEffect(() => {
- if (modifiers.focused) ref.current?.focus()
- }, [modifiers.focused])
-
- return (
-
-
-**If you have made any changes to the `Calendar` component, you will need to merge your changes with the new version.**
-
-Then follow the [React DayPicker](https://daypicker.dev/upgrading) upgrade guide to upgrade your dependencies and existing components to the latest version.
-
-#### Installing Blocks
-
-After upgrading the `Calendar` component, you can install the new blocks by running the `shadcn@latest add` command.
-
-```bash
-npx shadcn@latest add calendar-02
-```
-
-This will install the latest version of the calendar blocks.
-
## API Reference
-See the [React DayPicker](https://react-day-picker.js.org) documentation for more information on the `Calendar` component API.
+See the [React DayPicker](https://react-day-picker.js.org) documentation for more information on the `Calendar` component.
+
+## Changelog
+
+### RTL Support
+
+If you're upgrading from a previous version of the `Calendar` component, you'll need to apply the following updates to add locale support:
+
+
+
+Import the `Locale` type.
+
+Add `Locale` to your imports from `react-day-picker`:
+
+```diff
+ import {
+ DayPicker,
+ getDefaultClassNames,
+ type DayButton,
++ type Locale,
+ } from "react-day-picker"
+```
+
+Add `locale` prop to the Calendar component.
+
+Add the `locale` prop to the component's props:
+
+```diff
+ function Calendar({
+ className,
+ classNames,
+ showOutsideDays = true,
+ captionLayout = "label",
+ buttonVariant = "ghost",
++ locale,
+ formatters,
+ components,
+ ...props
+ }: React.ComponentProps & {
+ buttonVariant?: React.ComponentProps["variant"]
+ }) {
+```
+
+Pass `locale` to DayPicker.
+
+Pass the `locale` prop to the `DayPicker` component:
+
+```diff
+
+- date.toLocaleString("default", { month: "short" }),
++ date.toLocaleString(locale?.code, { month: "short" }),
+ ...formatters,
+ }}
+```
+
+Update CalendarDayButton to accept locale.
+
+Update the `CalendarDayButton` component signature and pass `locale`:
+
+```diff
+ function CalendarDayButton({
+ className,
+ day,
+ modifiers,
++ locale,
+ ...props
+- }: React.ComponentProps) {
++ }: React.ComponentProps & { locale?: Partial }) {
+```
+
+Update date formatting in CalendarDayButton.
+
+Use `locale?.code` in the date formatting:
+
+```diff
+
+```
+
+Pass locale to DayButton component.
+
+Update the `DayButton` component usage to pass the `locale` prop:
+
+```diff
+ components={{
+ ...
+- DayButton: CalendarDayButton,
++ DayButton: ({ ...props }) => (
++
++ ),
+ ...
+ }}
+```
+
+Update RTL-aware CSS classes.
+
+Replace directional classes with logical properties for better RTL support:
+
+```diff
+ // In the day classNames:
+- [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius)
++ [&:last-child[data-selected=true]_button]:rounded-e-(--cell-radius)
+- [&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)
++ [&:nth-child(2)[data-selected=true]_button]:rounded-s-(--cell-radius)
+- [&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)
++ [&:first-child[data-selected=true]_button]:rounded-s-(--cell-radius)
+
+ // In range_start classNames:
+- rounded-l-(--cell-radius) ... after:right-0
++ rounded-s-(--cell-radius) ... after:end-0
+
+ // In range_end classNames:
+- rounded-r-(--cell-radius) ... after:left-0
++ rounded-e-(--cell-radius) ... after:start-0
+
+ // In CalendarDayButton className:
+- data-[range-end=true]:rounded-r-(--cell-radius)
++ data-[range-end=true]:rounded-e-(--cell-radius)
+- data-[range-start=true]:rounded-l-(--cell-radius)
++ data-[range-start=true]:rounded-s-(--cell-radius)
+```
+
+
+
+After applying these changes, you can use the `locale` prop to provide locale-specific formatting:
+
+```tsx
+import { enUS } from "react-day-picker/locale"
+
+;
+```
diff --git a/apps/v4/content/docs/components/base/card.mdx b/apps/v4/content/docs/components/base/card.mdx
index 82faf1ac34..ef582164be 100644
--- a/apps/v4/content/docs/components/base/card.mdx
+++ b/apps/v4/content/docs/components/base/card.mdx
@@ -99,6 +99,17 @@ Add an image before the card header to create a card with an image.
previewClassName="h-[32rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Card
diff --git a/apps/v4/content/docs/components/base/carousel.mdx b/apps/v4/content/docs/components/base/carousel.mdx
index 0e4259d616..1c07e3a4b7 100644
--- a/apps/v4/content/docs/components/base/carousel.mdx
+++ b/apps/v4/content/docs/components/base/carousel.mdx
@@ -285,6 +285,38 @@ export function Example() {
previewClassName="sm:h-[32rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
+When localizing the carousel for RTL languages, you need to set the `direction` option in the `opts` prop to match the text direction. This ensures the carousel scrolls in the correct direction.
+
+```tsx showLineNumbers {2-5}
+
+
+ ...
+ ...
+ ...
+
+
+
+
+```
+
+The `direction` option accepts `"ltr"` or `"rtl"` and should match the `dir` prop value. You may also want to rotate the navigation buttons using the `rtl:rotate-180` class to ensure they point in the correct direction.
+
## API Reference
See the [Embla Carousel docs](https://www.embla-carousel.com/api/plugins/) for more information on props and plugins.
diff --git a/apps/v4/content/docs/components/base/chart.mdx b/apps/v4/content/docs/components/base/chart.mdx
index 4bdb76a602..a0f50f058b 100644
--- a/apps/v4/content/docs/components/base/chart.mdx
+++ b/apps/v4/content/docs/components/base/chart.mdx
@@ -580,3 +580,14 @@ This prop adds keyboard access and screen reader support to your charts.
```tsx title="components/example-chart.tsx"
```
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/base/checkbox.mdx b/apps/v4/content/docs/components/base/checkbox.mdx
index 2166ad6855..526c5d9037 100644
--- a/apps/v4/content/docs/components/base/checkbox.mdx
+++ b/apps/v4/content/docs/components/base/checkbox.mdx
@@ -122,6 +122,17 @@ Use multiple fields to create a checkbox list.
previewClassName="p-4 md:p-8"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI](https://base-ui.com/react/components/checkbox#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/base/collapsible.mdx b/apps/v4/content/docs/components/base/collapsible.mdx
index 1d8513c159..649ff09332 100644
--- a/apps/v4/content/docs/components/base/collapsible.mdx
+++ b/apps/v4/content/docs/components/base/collapsible.mdx
@@ -118,6 +118,17 @@ Use nested collapsibles to build a file tree.
previewClassName="h-[36rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI](https://base-ui.com/react/components/collapsible#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/base/combobox.mdx b/apps/v4/content/docs/components/base/combobox.mdx
index 1219d4b6d1..2222db2331 100644
--- a/apps/v4/content/docs/components/base/combobox.mdx
+++ b/apps/v4/content/docs/components/base/combobox.mdx
@@ -256,6 +256,17 @@ You can add an addon to the combobox by using the `InputGroupAddon` component in
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI](https://base-ui.com/react/components/combobox#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/base/command.mdx b/apps/v4/content/docs/components/base/command.mdx
index 91d243c4a5..17c7a06ece 100644
--- a/apps/v4/content/docs/components/base/command.mdx
+++ b/apps/v4/content/docs/components/base/command.mdx
@@ -120,6 +120,18 @@ Scrollable command menu with multiple items.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [cmdk](https://github.com/dip/cmdk) documentation for more information.
diff --git a/apps/v4/content/docs/components/base/context-menu.mdx b/apps/v4/content/docs/components/base/context-menu.mdx
index 05547a0d34..e5176174f3 100644
--- a/apps/v4/content/docs/components/base/context-menu.mdx
+++ b/apps/v4/content/docs/components/base/context-menu.mdx
@@ -135,6 +135,30 @@ Control submenu placement with side and align props.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
+Use `side="inline-end"` to place the menu on the logical right side of the trigger.
+
+```tsx showLineNumbers
+
+ Right click here
+
+ Profile
+ Billing
+ Team
+ Subscription
+
+
+```
+
## API Reference
See the [Base UI](https://base-ui.com/react/components/context-menu#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/base/data-table.mdx b/apps/v4/content/docs/components/base/data-table.mdx
index 8e42fcdc89..4cbc976d34 100644
--- a/apps/v4/content/docs/components/base/data-table.mdx
+++ b/apps/v4/content/docs/components/base/data-table.mdx
@@ -11,7 +11,8 @@ links:
styleName="radix-nova"
name="data-table-demo"
align="start"
- previewClassName="items-start h-[28rem] px-4 md:px-8"
+ previewClassName="items-start h-auto px-4 md:px-8"
+ hideCode
/>
## Introduction
@@ -883,3 +884,15 @@ A component to toggle column visibility.
```tsx
```
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/base/date-picker.mdx b/apps/v4/content/docs/components/base/date-picker.mdx
index ea769c15bf..f12e8f628e 100644
--- a/apps/v4/content/docs/components/base/date-picker.mdx
+++ b/apps/v4/content/docs/components/base/date-picker.mdx
@@ -95,3 +95,13 @@ A date picker component with a time input field for selecting a time.
This component uses the `chrono-node` library to parse natural language dates.
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/base/dialog.mdx b/apps/v4/content/docs/components/base/dialog.mdx
index c1b0e52cc8..427da7fc64 100644
--- a/apps/v4/content/docs/components/base/dialog.mdx
+++ b/apps/v4/content/docs/components/base/dialog.mdx
@@ -111,6 +111,12 @@ Long content can scroll while the header stays in view.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI](https://base-ui.com/react/components/dialog#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/base/direction.mdx b/apps/v4/content/docs/components/base/direction.mdx
new file mode 100644
index 0000000000..895c790e84
--- /dev/null
+++ b/apps/v4/content/docs/components/base/direction.mdx
@@ -0,0 +1,93 @@
+---
+title: Direction
+description: A provider component that sets the text direction for your application.
+base: base
+component: true
+links:
+ doc: https://base-ui.com/react/utils/direction-provider
+ api: https://base-ui.com/react/utils/direction-provider#api-reference
+---
+
+The `DirectionProvider` component is used to set the text direction (`ltr` or `rtl`) for your application. This is essential for supporting right-to-left languages like Arabic, Hebrew, and Persian.
+
+Here's a preview of the component in RTL mode. Use the language selector to switch the language. To see more examples, look for the RTL section on components pages.
+
+
+
+## Installation
+
+
+
+
+ Command
+ Manual
+
+
+
+
+```bash
+npx shadcn@latest add direction
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install @base-ui/react
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import { DirectionProvider } from "@/components/ui/direction"
+```
+
+```tsx showLineNumbers
+
+
+
+ {/* Your app content */}
+
+
+
+```
+
+## useDirection
+
+The `useDirection` hook is used to get the current direction of the application.
+
+```tsx showLineNumbers
+import { useDirection } from "@/components/ui/direction"
+
+function MyComponent() {
+ const direction = useDirection()
+ return
Current direction: {direction}
+}
+```
diff --git a/apps/v4/content/docs/components/base/drawer.mdx b/apps/v4/content/docs/components/base/drawer.mdx
index f8e27d669c..762642e179 100644
--- a/apps/v4/content/docs/components/base/drawer.mdx
+++ b/apps/v4/content/docs/components/base/drawer.mdx
@@ -108,6 +108,12 @@ You can combine the `Dialog` and `Drawer` components to create a responsive dial
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Vaul documentation](https://vaul.emilkowal.ski/getting-started) for the full API reference.
diff --git a/apps/v4/content/docs/components/base/dropdown-menu.mdx b/apps/v4/content/docs/components/base/dropdown-menu.mdx
index 209f01f97e..b63bfc10bd 100644
--- a/apps/v4/content/docs/components/base/dropdown-menu.mdx
+++ b/apps/v4/content/docs/components/base/dropdown-menu.mdx
@@ -160,6 +160,16 @@ A richer example combining groups, icons, and submenus.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI documentation](https://base-ui.com/react/components/menu) for the full API reference.
diff --git a/apps/v4/content/docs/components/base/empty.mdx b/apps/v4/content/docs/components/base/empty.mdx
index c690250644..2ecdfaf391 100644
--- a/apps/v4/content/docs/components/base/empty.mdx
+++ b/apps/v4/content/docs/components/base/empty.mdx
@@ -127,6 +127,12 @@ You can add an `InputGroup` component to the `EmptyContent` component.
previewClassName="h-96 p-0"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Empty
diff --git a/apps/v4/content/docs/components/base/field.mdx b/apps/v4/content/docs/components/base/field.mdx
index 7281cbbb0b..d0116f04d8 100644
--- a/apps/v4/content/docs/components/base/field.mdx
+++ b/apps/v4/content/docs/components/base/field.mdx
@@ -162,6 +162,17 @@ Stack `Field` components with `FieldGroup`. Add `FieldSeparator` to divide them.
previewClassName="h-96"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## Responsive Layout
- **Vertical fields:** Default orientation stacks label, control, and helper text—ideal for mobile-first layouts.
diff --git a/apps/v4/content/docs/components/base/hover-card.mdx b/apps/v4/content/docs/components/base/hover-card.mdx
index 0c1c2e6311..7705af75ea 100644
--- a/apps/v4/content/docs/components/base/hover-card.mdx
+++ b/apps/v4/content/docs/components/base/hover-card.mdx
@@ -120,6 +120,17 @@ Use the `side` and `align` props on `HoverCardContent` to control placement.
previewClassName="h-[22rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI](https://base-ui.com/react/components/hover-card#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/base/input-group.mdx b/apps/v4/content/docs/components/base/input-group.mdx
index 505a91057e..a781b50c4c 100644
--- a/apps/v4/content/docs/components/base/input-group.mdx
+++ b/apps/v4/content/docs/components/base/input-group.mdx
@@ -191,6 +191,17 @@ Here's an example of a custom resizable textarea from a third-party library.
previewClassName="h-56"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### InputGroup
diff --git a/apps/v4/content/docs/components/base/input-otp.mdx b/apps/v4/content/docs/components/base/input-otp.mdx
index 38f8031513..f64f7d6666 100644
--- a/apps/v4/content/docs/components/base/input-otp.mdx
+++ b/apps/v4/content/docs/components/base/input-otp.mdx
@@ -142,6 +142,12 @@ Use `REGEXP_ONLY_DIGITS_AND_CHARS` to accept both letters and numbers.
previewClassName="h-[30rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [input-otp](https://input-otp.rodz.dev) documentation for more information.
diff --git a/apps/v4/content/docs/components/base/input.mdx b/apps/v4/content/docs/components/base/input.mdx
index ba0d3a75e7..d7d2c841c7 100644
--- a/apps/v4/content/docs/components/base/input.mdx
+++ b/apps/v4/content/docs/components/base/input.mdx
@@ -188,3 +188,14 @@ A full form example with multiple inputs, a select, and a button.
name="input-form"
previewClassName="h-[32rem]"
/>
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/base/item.mdx b/apps/v4/content/docs/components/base/item.mdx
index a967cca4fa..a9b17e50c2 100644
--- a/apps/v4/content/docs/components/base/item.mdx
+++ b/apps/v4/content/docs/components/base/item.mdx
@@ -161,6 +161,12 @@ Use the `render` prop to render the item as a link. The hover and focus states w
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Item
diff --git a/apps/v4/content/docs/components/base/kbd.mdx b/apps/v4/content/docs/components/base/kbd.mdx
index 4de803e960..ee52f65116 100644
--- a/apps/v4/content/docs/components/base/kbd.mdx
+++ b/apps/v4/content/docs/components/base/kbd.mdx
@@ -79,6 +79,12 @@ You can use the `Kbd` component inside a `InputGroupAddon` component to display
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Kbd
diff --git a/apps/v4/content/docs/components/base/label.mdx b/apps/v4/content/docs/components/base/label.mdx
index db763dd605..dbedab2f38 100644
--- a/apps/v4/content/docs/components/base/label.mdx
+++ b/apps/v4/content/docs/components/base/label.mdx
@@ -85,6 +85,12 @@ includes built-in `FieldLabel`, `FieldDescription`, and `FieldError` components.
previewClassName="h-[44rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Label](https://base-ui.com/react/components/label#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/base/menubar.mdx b/apps/v4/content/docs/components/base/menubar.mdx
index 8575c5e6db..d81470267d 100644
--- a/apps/v4/content/docs/components/base/menubar.mdx
+++ b/apps/v4/content/docs/components/base/menubar.mdx
@@ -112,6 +112,12 @@ Use `MenubarSub`, `MenubarSubTrigger`, and `MenubarSubContent` for nested menus.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Menubar](https://base-ui.com/react/components/menubar#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/meta.json b/apps/v4/content/docs/components/base/meta.json
index 876c74b3f0..c4fc782e84 100644
--- a/apps/v4/content/docs/components/base/meta.json
+++ b/apps/v4/content/docs/components/base/meta.json
@@ -22,6 +22,7 @@
"data-table",
"date-picker",
"dialog",
+ "direction",
"drawer",
"dropdown-menu",
"empty",
diff --git a/apps/v4/content/docs/components/base/native-select.mdx b/apps/v4/content/docs/components/base/native-select.mdx
index 94fec14ff3..12ba224e12 100644
--- a/apps/v4/content/docs/components/base/native-select.mdx
+++ b/apps/v4/content/docs/components/base/native-select.mdx
@@ -95,6 +95,16 @@ Use `aria-invalid` to show validation errors and the `data-invalid` attribute to
- Use `NativeSelect` for native browser behavior, better performance, or mobile-optimized dropdowns.
- Use `Select` for custom styling, animations, or complex interactions.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### NativeSelect
diff --git a/apps/v4/content/docs/components/base/navigation-menu.mdx b/apps/v4/content/docs/components/base/navigation-menu.mdx
index 6c93120dce..b998b1e29e 100644
--- a/apps/v4/content/docs/components/base/navigation-menu.mdx
+++ b/apps/v4/content/docs/components/base/navigation-menu.mdx
@@ -109,6 +109,17 @@ export function NavigationMenuDemo() {
}
```
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Navigation Menu](https://base-ui.com/react/components/navigation-menu#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/base/pagination.mdx b/apps/v4/content/docs/components/base/pagination.mdx
index 826d9b1979..39a3aea640 100644
--- a/apps/v4/content/docs/components/base/pagination.mdx
+++ b/apps/v4/content/docs/components/base/pagination.mdx
@@ -127,3 +127,69 @@ const PaginationLink = ({...props }: ) => (
**Note:** We are making updates to the cli to automatically do this for you.
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
+## Changelog
+
+### RTL Support
+
+If you're upgrading from a previous version of the `Pagination` component, you'll need to apply the following updates to add the `text` prop:
+
+
+
+Update `PaginationPrevious`.
+
+```diff
+ function PaginationPrevious({
+ className,
++ text = "Previous",
+ ...props
+- }: React.ComponentProps) {
++ }: React.ComponentProps & { text?: string }) {
+ return (
+
+
+
+- Previous
++ {text}
+
+
+ )
+ }
+```
+
+Update `PaginationNext`.
+
+```diff
+ function PaginationNext({
+ className,
++ text = "Next",
+ ...props
+- }: React.ComponentProps) {
++ }: React.ComponentProps & { text?: string }) {
+ return (
+
+- Next
++ {text}
+
+
+ )
+ }
+```
+
+
diff --git a/apps/v4/content/docs/components/base/popover.mdx b/apps/v4/content/docs/components/base/popover.mdx
index 005c89126d..c03e7805f2 100644
--- a/apps/v4/content/docs/components/base/popover.mdx
+++ b/apps/v4/content/docs/components/base/popover.mdx
@@ -99,6 +99,12 @@ A popover with form fields inside.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Popover](https://base-ui.com/react/components/popover#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/progress.mdx b/apps/v4/content/docs/components/base/progress.mdx
index 8684b04b70..4e683af40b 100644
--- a/apps/v4/content/docs/components/base/progress.mdx
+++ b/apps/v4/content/docs/components/base/progress.mdx
@@ -76,6 +76,12 @@ A progress bar that can be controlled by a slider.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Progress](https://base-ui.com/react/components/progress#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/radio-group.mdx b/apps/v4/content/docs/components/base/radio-group.mdx
index 15107a88f0..c45dada58d 100644
--- a/apps/v4/content/docs/components/base/radio-group.mdx
+++ b/apps/v4/content/docs/components/base/radio-group.mdx
@@ -104,6 +104,16 @@ Use `aria-invalid` on `RadioGroupItem` and `data-invalid` on `Field` to show val
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Radio Group](https://base-ui.com/react/components/radio-group#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/resizable.mdx b/apps/v4/content/docs/components/base/resizable.mdx
index 715be84beb..7c90653889 100644
--- a/apps/v4/content/docs/components/base/resizable.mdx
+++ b/apps/v4/content/docs/components/base/resizable.mdx
@@ -71,7 +71,7 @@ import {
```
```tsx showLineNumbers
-
+OneTwo
@@ -82,7 +82,7 @@ import {
### Vertical
-Use `direction="vertical"` for vertical resizing.
+Use `orientation="vertical"` for vertical resizing.
@@ -92,6 +92,36 @@ Use the `withHandle` prop on `ResizableHandle` to show a visible handle.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [react-resizable-panels](https://github.com/bvaughn/react-resizable-panels/tree/main/packages/react-resizable-panels) documentation.
+
+## Changelog
+
+### 2025-02-02 `react-resizable-panels` v4
+
+Updated to `react-resizable-panels` v4. See the [v4.0.0 release notes](https://github.com/bvaughn/react-resizable-panels/releases/tag/4.0.0) for full details.
+
+If you're using `react-resizable-panels` primitives directly, note the following changes:
+
+| v3 | v4 |
+| ---------------------------- | ----------------------- |
+| `PanelGroup` | `Group` |
+| `PanelResizeHandle` | `Separator` |
+| `direction` prop | `orientation` prop |
+| `defaultSize={50}` | `defaultSize="50%"` |
+| `onLayout` | `onLayoutChange` |
+| `ImperativePanelHandle` | `PanelImperativeHandle` |
+| `ref` prop on Panel | `panelRef` prop |
+| `data-panel-group-direction` | `aria-orientation` |
+
+
+ The shadcn/ui wrapper components (`ResizablePanelGroup`, `ResizablePanel`,
+ `ResizableHandle`) remain unchanged.
+
diff --git a/apps/v4/content/docs/components/base/scroll-area.mdx b/apps/v4/content/docs/components/base/scroll-area.mdx
index c0926757d9..580fcdb46c 100644
--- a/apps/v4/content/docs/components/base/scroll-area.mdx
+++ b/apps/v4/content/docs/components/base/scroll-area.mdx
@@ -76,6 +76,17 @@ Use `ScrollBar` with `orientation="horizontal"` for horizontal scrolling.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Scroll Area](https://base-ui.com/react/components/scroll-area#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/select.mdx b/apps/v4/content/docs/components/base/select.mdx
index e0e0124b1e..5282d7d547 100644
--- a/apps/v4/content/docs/components/base/select.mdx
+++ b/apps/v4/content/docs/components/base/select.mdx
@@ -59,6 +59,7 @@ npm install @base-ui/react
import {
Select,
SelectContent,
+ SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
@@ -71,9 +72,11 @@ import {
- Light
- Dark
- System
+
+ Light
+ Dark
+ System
+
```
@@ -117,6 +120,12 @@ Add the `data-invalid` attribute to the `Field` component and the `aria-invalid`
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Select](https://base-ui.com/react/components/select#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/separator.mdx b/apps/v4/content/docs/components/base/separator.mdx
index 3e694ef27d..4b3ce305ab 100644
--- a/apps/v4/content/docs/components/base/separator.mdx
+++ b/apps/v4/content/docs/components/base/separator.mdx
@@ -82,6 +82,12 @@ Horizontal separators between list items.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Separator](https://base-ui.com/react/components/separator#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/sheet.mdx b/apps/v4/content/docs/components/base/sheet.mdx
index 3706c86ebd..426063a588 100644
--- a/apps/v4/content/docs/components/base/sheet.mdx
+++ b/apps/v4/content/docs/components/base/sheet.mdx
@@ -93,6 +93,12 @@ Use `showCloseButton={false}` on `SheetContent` to hide the close button.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Dialog](https://base-ui.com/react/components/dialog#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/sidebar.mdx b/apps/v4/content/docs/components/base/sidebar.mdx
index ebf0768f5a..31545a50f6 100644
--- a/apps/v4/content/docs/components/base/sidebar.mdx
+++ b/apps/v4/content/docs/components/base/sidebar.mdx
@@ -5,8 +5,15 @@ base: base
component: true
---
+import { ExternalLinkIcon } from "lucide-react"
+
-
+
A sidebar that collapses to icons.
@@ -15,9 +22,6 @@ component: true
Sidebars are one of the most complex components to build. They are central
to any application and often contain a lot of moving parts.
-I don't like building sidebars. So I built 30+ of them. All kinds of
-configurations. Then I extracted the core components into `sidebar.tsx`.
-
We now have a solid foundation to build on top of. Composable. Themeable.
Customizable.
@@ -33,96 +37,20 @@ Customizable.
-
-
-Run the following command to install `sidebar.tsx`
-
```bash
npx shadcn@latest add sidebar
```
-Add the following colors to your CSS file
-
-The command above should install the colors for you. If not, copy and paste the following in your CSS file.
-
-We'll go over the colors later in the [theming section](/docs/components/sidebar#theming).
-
-```css showLineNumbers title="app/globals.css"
-@layer base {
- :root {
- --sidebar: oklch(0.985 0 0);
- --sidebar-foreground: oklch(0.145 0 0);
- --sidebar-primary: oklch(0.205 0 0);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.97 0 0);
- --sidebar-accent-foreground: oklch(0.205 0 0);
- --sidebar-border: oklch(0.922 0 0);
- --sidebar-ring: oklch(0.708 0 0);
- }
-
- .dark {
- --sidebar: oklch(0.205 0 0);
- --sidebar-foreground: oklch(0.985 0 0);
- --sidebar-primary: oklch(0.488 0.243 264.376);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.269 0 0);
- --sidebar-accent-foreground: oklch(0.985 0 0);
- --sidebar-border: oklch(1 0 0 / 10%);
- --sidebar-ring: oklch(0.439 0 0);
- }
-}
-```
-
-
-
-
-
-Copy and paste the following code into your project.
-
-Update the import paths to match your project setup.
-
-Add the following colors to your CSS file
-
-We'll go over the colors later in the [theming section](/docs/components/sidebar#theming).
-
-```css showLineNumbers title="app/globals.css"
-@layer base {
- :root {
- --sidebar: oklch(0.985 0 0);
- --sidebar-foreground: oklch(0.145 0 0);
- --sidebar-primary: oklch(0.205 0 0);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.97 0 0);
- --sidebar-accent-foreground: oklch(0.205 0 0);
- --sidebar-border: oklch(0.922 0 0);
- --sidebar-ring: oklch(0.708 0 0);
- }
-
- .dark {
- --sidebar: oklch(0.205 0 0);
- --sidebar-foreground: oklch(0.985 0 0);
- --sidebar-primary: oklch(0.488 0.243 264.376);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.269 0 0);
- --sidebar-accent-foreground: oklch(0.985 0 0);
- --sidebar-border: oklch(1 0 0 / 10%);
- --sidebar-ring: oklch(0.439 0 0);
- }
-}
-```
-
-
-
@@ -195,142 +123,6 @@ export function AppSidebar() {
}
```
-## Your First Sidebar
-
-Let's start with the most basic sidebar. A collapsible sidebar with a menu.
-
-
-
-
- Add a `SidebarProvider` and `SidebarTrigger` at the root of your application.
-
-
-```tsx showLineNumbers title="app/layout.tsx"
-import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
-import { AppSidebar } from "@/components/app-sidebar"
-
-export default function Layout({ children }: { children: React.ReactNode }) {
- return (
-
-
-
-
- {children}
-
-
- )
-}
-```
-
-Create a new sidebar component at `components/app-sidebar.tsx`.
-
-```tsx showLineNumbers title="components/app-sidebar.tsx"
-import { Sidebar, SidebarContent } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return (
-
-
-
- )
-}
-```
-
-Now, let's add a `SidebarMenu` to the sidebar.
-
-We'll use the `SidebarMenu` component in a `SidebarGroup`.
-
-```tsx showLineNumbers title="components/app-sidebar.tsx"
-import { Calendar, Home, Inbox, Search, Settings } from "lucide-react"
-
-import {
- Sidebar,
- SidebarContent,
- SidebarGroup,
- SidebarGroupContent,
- SidebarGroupLabel,
- SidebarMenu,
- SidebarMenuButton,
- SidebarMenuItem,
-} from "@/components/ui/sidebar"
-
-// Menu items.
-const items = [
- {
- title: "Home",
- url: "#",
- icon: Home,
- },
- {
- title: "Inbox",
- url: "#",
- icon: Inbox,
- },
- {
- title: "Calendar",
- url: "#",
- icon: Calendar,
- },
- {
- title: "Search",
- url: "#",
- icon: Search,
- },
- {
- title: "Settings",
- url: "#",
- icon: Settings,
- },
-]
-
-export function AppSidebar() {
- return (
-
-
-
- Application
-
-
- {items.map((item) => (
-
-
-
-
- {item.title}
-
-
-
- ))}
-
-
-
-
-
- )
-}
-```
-
-You've created your first sidebar.
-
-You should see something like this:
-
-
-
-
- Your first sidebar.
-
-
-
-
-
-## Components
-
-The components in `sidebar.tsx` are built to be composable i.e you build your sidebar by putting the provided components together. They also compose well with other shadcn/ui components such as `DropdownMenu`, `Collapsible` or `Dialog` etc.
-
-**If you need to change the code in `sidebar.tsx`, you are encouraged to do so. The code is yours. Use `sidebar.tsx` as a starting point and build your own.**
-
-In the next sections, we'll go over each component and how to use them.
-
## SidebarProvider
The `SidebarProvider` component is used to provide the sidebar context to the `Sidebar` component. You should always wrap your application in a `SidebarProvider` component.
@@ -352,11 +144,9 @@ const SIDEBAR_WIDTH = "16rem"
const SIDEBAR_WIDTH_MOBILE = "18rem"
```
-For multiple sidebars in your application, you can use the `style` prop to set the width of the sidebar.
+For multiple sidebars in your application, you can use the `--sidebar-width` and `--sidebar-width-mobile` CSS variables in the `style` prop.
-To set the width of the sidebar, you can use the `--sidebar-width` and `--sidebar-width-mobile` CSS variables in the `style` prop.
-
-```tsx showLineNumbers title="components/ui/sidebar.tsx"
+```tsx showLineNumbers
```
-This will handle the width of the sidebar but also the layout spacing.
-
### Keyboard Shortcut
-The `SIDEBAR_KEYBOARD_SHORTCUT` variable is used to set the keyboard shortcut used to open and close the sidebar.
-
To trigger the sidebar, you use the `cmd+b` keyboard shortcut on Mac and `ctrl+b` on Windows.
-You can change the keyboard shortcut by updating the `SIDEBAR_KEYBOARD_SHORTCUT` variable.
-
```tsx showLineNumbers title="components/ui/sidebar.tsx"
const SIDEBAR_KEYBOARD_SHORTCUT = "b"
```
-### Persisted State
-
-The `SidebarProvider` supports persisting the sidebar state across page reloads and server-side rendering. It uses cookies to store the current state of the sidebar. When the sidebar state changes, a default cookie named `sidebar_state` is set with the current open/closed state. This cookie is then read on subsequent page loads to restore the sidebar state.
-
-To persist sidebar state in Next.js, set up your `SidebarProvider` in `app/layout.tsx` like this:
-
-```tsx showLineNumbers title="app/layout.tsx"
-import { cookies } from "next/headers"
-
-import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
-import { AppSidebar } from "@/components/app-sidebar"
-
-export async function Layout({ children }: { children: React.ReactNode }) {
- const cookieStore = await cookies()
- const defaultOpen = cookieStore.get("sidebar_state")?.value === "true"
-
- return (
-
-
-
-
- {children}
-
-
- )
-}
-```
-
-You can change the name of the cookie by updating the `SIDEBAR_COOKIE_NAME` variable in `sidebar.tsx`.
-
-```tsx showLineNumbers title="components/ui/sidebar.tsx"
-const SIDEBAR_COOKIE_NAME = "sidebar_state"
-```
-
## Sidebar
The main `Sidebar` component used to render a collapsible sidebar.
-```tsx showLineNumbers
-import { Sidebar } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return
-}
-```
-
### Props
| Property | Type | Description |
@@ -435,33 +177,11 @@ export function AppSidebar() {
| `variant` | `sidebar`, `floating`, or `inset` | The variant of the sidebar. |
| `collapsible` | `offcanvas`, `icon`, or `none` | Collapsible state of the sidebar. |
-### side
-
-Use the `side` prop to change the side of the sidebar.
-
-Available options are `left` and `right`.
-
-```tsx showLineNumbers
-import { Sidebar } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return
-}
-```
-
-### variant
-
-Use the `variant` prop to change the variant of the sidebar.
-
-Available options are `sidebar`, `floating` and `inset`.
-
-```tsx showLineNumbers
-import { Sidebar } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return
-}
-```
+| Prop | Description |
+| ----------- | ------------------------------------------------------------ |
+| `offcanvas` | A collapsible sidebar that slides in from the left or right. |
+| `icon` | A sidebar that collapses to icons. |
+| `none` | A non-collapsible sidebar. |
**Note:** If you use the `inset` variant, remember to wrap your main content
@@ -477,26 +197,6 @@ export function AppSidebar() {
```
-### collapsible
-
-Use the `collapsible` prop to make the sidebar collapsible.
-
-Available options are `offcanvas`, `icon` and `none`.
-
-```tsx showLineNumbers
-import { Sidebar } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return
-}
-```
-
-| Prop | Description |
-| ----------- | ------------------------------------------------------------ |
-| `offcanvas` | A collapsible sidebar that slides in from the left or right. |
-| `icon` | A sidebar that collapses to icons. |
-| `none` | A non-collapsible sidebar. |
-
## useSidebar
The `useSidebar` hook is used to control the sidebar.
@@ -531,15 +231,6 @@ export function AppSidebar() {
Use the `SidebarHeader` component to add a sticky header to the sidebar.
-The following example adds a `` to the `SidebarHeader`.
-
-
-
-
- A sidebar header with a dropdown menu.
-
-
-
```tsx showLineNumbers title="components/app-sidebar.tsx"
@@ -556,9 +247,6 @@ The following example adds a `` to the `SidebarHeader`.
Acme Inc
-
- Acme Corp.
-
@@ -571,54 +259,18 @@ The following example adds a `` to the `SidebarHeader`.
Use the `SidebarFooter` component to add a sticky footer to the sidebar.
-The following example adds a `` to the `SidebarFooter`.
-
-
-
-
- A sidebar footer with a dropdown menu.
-
-
-
-```tsx showLineNumbers title="components/app-sidebar.tsx"
-export function AppSidebar() {
- return (
-
-
-
-
-
-
-
-
-
-
- Username
-
-
-
-
-
- Account
-
-
- Billing
-
-
- Sign out
-
-
-
-
-
-
-
-
- )
-}
+```tsx showLineNumbers
+
+
+
+
+
+ Username
+
+
+
+
+
```
## SidebarContent
@@ -626,18 +278,12 @@ export function AppSidebar() {
The `SidebarContent` component is used to wrap the content of the sidebar. This is where you add your `SidebarGroup` components. It is scrollable.
```tsx showLineNumbers
-import { Sidebar, SidebarContent } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return (
-
-
-
-
-
-
- )
-}
+
+
+
+
+
+
```
## SidebarGroup
@@ -646,108 +292,38 @@ Use the `SidebarGroup` component to create a section within the sidebar.
A `SidebarGroup` has a `SidebarGroupLabel`, a `SidebarGroupContent` and an optional `SidebarGroupAction`.
-
-
-
- A sidebar group.
-
-
-
```tsx showLineNumbers
-import { Sidebar, SidebarContent, SidebarGroup } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return (
-
-
-
- Application
-
- Add Project
-
-
-
-
-
- )
-}
+
+ Application
+
+ Add Project
+
+
+
```
-## Collapsible SidebarGroup
-
To make a `SidebarGroup` collapsible, wrap it in a `Collapsible`.
-
-
-
- A collapsible sidebar group.
-
-
-
```tsx showLineNumbers
-export function AppSidebar() {
- return (
-
-
-
-
- Help
-
-
-
-
-
-
-
-
- )
-}
-```
-
-
- **Note:** We wrap the `CollapsibleTrigger` in a `SidebarGroupLabel` to render
- a button.
-
-
-## SidebarGroupAction
-
-Use the `SidebarGroupAction` component to add an action button to the `SidebarGroup`.
-
-
-
-
- A sidebar group with an action button.
-
-
-
-```tsx showLineNumbers {5-7}
-export function AppSidebar() {
- return (
-
- Projects
-
- Add Project
-
+
+
+
+
+ Help
+
+
+
+
-
- )
-}
+
+
+
```
## SidebarMenu
The `SidebarMenu` component is used for building a menu within a `SidebarGroup`.
-A `SidebarMenu` component is composed of `SidebarMenuItem`, `SidebarMenuButton`, `` and `` components.
-
-Here's an example of a `SidebarMenu` component rendering a list of projects.
-
-
-
-
- A sidebar menu with a list of projects.
-
-
-
```tsx showLineNumbers
-
-
-
- Projects
-
-
- {projects.map((project) => (
-
-
-
-
- {project.name}
-
-
-
- ))}
-
-
-
-
-
+
+ {projects.map((project) => (
+
+
+
+
+ {project.name}
+
+
+
+ ))}
+
```
## SidebarMenuButton
The `SidebarMenuButton` component is used to render a menu button within a `SidebarMenuItem`.
-### Link or Anchor
-
By default, the `SidebarMenuButton` renders a button but you can use the `asChild` prop to render a different component such as a `Link` or an `a` tag.
-```tsx showLineNumbers
-
- Home
-
-```
-
-### Icon and Label
-
-You can render an icon and a truncated label inside the button. Remember to wrap the label in a ``.
-
-```tsx showLineNumbers
-
-
-
- Home
-
-
-```
-
-### isActive
-
Use the `isActive` prop to mark a menu item as active.
```tsx showLineNumbers
@@ -837,8 +372,6 @@ Use the `isActive` prop to mark a menu item as active.
The `SidebarMenuAction` component is used to render a menu action within a `SidebarMenuItem`.
-This button works independently of the `SidebarMenuButton` i.e you can have the `` as a clickable link and the `` as a button.
-
```tsx showLineNumbers
@@ -853,64 +386,10 @@ This button works independently of the `SidebarMenuButton` i.e you can have the
```
-### DropdownMenu
-
-Here's an example of a `SidebarMenuAction` component rendering a `DropdownMenu`.
-
-
-
-
- A sidebar menu action with a dropdown menu.
-
-
-
-```tsx showLineNumbers
-
-
-
-
- Home
-
-
-
-
-
-
-
-
-
-
- Edit Project
-
-
- Delete Project
-
-
-
-
-```
-
## SidebarMenuSub
The `SidebarMenuSub` component is used to render a submenu within a `SidebarMenu`.
-Use `` and `` to render a submenu item.
-
-
-
-
- A sidebar menu with a submenu.
-
-
-
```tsx showLineNumbers
@@ -918,60 +397,14 @@ Use `` and `` to render a submenu
-
-
-
```
-## Collapsible SidebarMenu
-
-To make a `SidebarMenu` component collapsible, wrap it and the `SidebarMenuSub` components in a `Collapsible`.
-
-
-
-
- A collapsible sidebar menu.
-
-
-
-```tsx showLineNumbers
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
## SidebarMenuBadge
The `SidebarMenuBadge` component is used to render a badge within a `SidebarMenuItem`.
-
-
-
- A sidebar menu with a badge.
-
-
-
```tsx showLineNumbers
@@ -981,57 +414,22 @@ The `SidebarMenuBadge` component is used to render a badge within a `SidebarMenu
## SidebarMenuSkeleton
-The `SidebarMenuSkeleton` component is used to render a skeleton for a `SidebarMenu`. You can use this to show a loading state when using React Server Components, SWR or react-query.
+The `SidebarMenuSkeleton` component is used to render a skeleton for a `SidebarMenu`.
```tsx showLineNumbers
-function NavProjectsSkeleton() {
- return (
-
- {Array.from({ length: 5 }).map((_, index) => (
-
-
-
- ))}
-
- )
-}
-```
-
-## SidebarSeparator
-
-The `SidebarSeparator` component is used to render a separator within a `Sidebar`.
-
-```tsx showLineNumbers
-
-
-
-
-
-
-
-
-
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+
+ ))}
+
```
## SidebarTrigger
Use the `SidebarTrigger` component to render a button that toggles the sidebar.
-The `SidebarTrigger` component must be used within a `SidebarProvider`.
-
-```tsx showLineNumbers
-
-
-
-
-
-
-```
-
-### Custom Trigger
-
-To create a custom trigger, you can use the `useSidebar` hook.
-
```tsx showLineNumbers
import { useSidebar } from "@/components/ui/sidebar"
@@ -1057,166 +455,10 @@ The `SidebarRail` component is used to render a rail within a `Sidebar`. This ra
```
-## Data Fetching
-
-### React Server Components
-
-Here's an example of a `SidebarMenu` component rendering a list of projects using React Server Components.
-
-
-
-
- A sidebar menu using React Server Components.
-
-
-
-```tsx showLineNumbers {6} title="Skeleton to show loading state."
-function NavProjectsSkeleton() {
- return (
-
- {Array.from({ length: 5 }).map((_, index) => (
-
-
-
- ))}
-
- )
-}
-```
-
-```tsx showLineNumbers {2} title="Server component fetching data."
-async function NavProjects() {
- const projects = await fetchProjects()
-
- return (
-
- {projects.map((project) => (
-
-
-
-
- {project.name}
-
-
-
- ))}
-
- )
-}
-```
-
-```tsx showLineNumbers {8-10} title="Usage with React Suspense."
-function AppSidebar() {
- return (
-
-
-
- Projects
-
- }>
-
-
-
-
-
-
- )
-}
-```
-
-### SWR and React Query
-
-You can use the same approach with [SWR](https://swr.vercel.app/) or [react-query](https://tanstack.com/query/latest/docs/framework/react/overview).
-
-```tsx showLineNumbers title="SWR"
-function NavProjects() {
- const { data, isLoading } = useSWR("/api/projects", fetcher)
-
- if (isLoading) {
- return (
-
- {Array.from({ length: 5 }).map((_, index) => (
-
-
-
- ))}
-
- )
- }
-
- if (!data) {
- return ...
- }
-
- return (
-
- {data.map((project) => (
-
-
-
-
- {project.name}
-
-
-
- ))}
-
- )
-}
-```
-
-```tsx showLineNumbers title="React Query"
-function NavProjects() {
- const { data, isLoading } = useQuery()
-
- if (isLoading) {
- return (
-
- {Array.from({ length: 5 }).map((_, index) => (
-
-
-
- ))}
-
- )
- }
-
- if (!data) {
- return ...
- }
-
- return (
-
- {data.map((project) => (
-
-
-
-
- {project.name}
-
-
-
- ))}
-
- )
-}
-```
-
## Controlled Sidebar
Use the `open` and `onOpenChange` props to control the sidebar.
-
-
-
- A controlled sidebar.
-
-
-
```tsx showLineNumbers
export function AppSidebar() {
const [open, setOpen] = React.useState(false)
@@ -1259,14 +501,10 @@ We use the following CSS variables to theme the sidebar.
}
```
-**We intentionally use different variables for the sidebar and the rest of the application** to make it easy to have a sidebar that is styled differently from the rest of the application. Think a sidebar with a darker shade from the main application.
-
## Styling
Here are some tips for styling the sidebar based on different states.
-- **Styling an element based on the sidebar collapsible state.** The following will hide the `SidebarGroup` when the sidebar is in `icon` mode.
-
```tsx
@@ -1275,8 +513,6 @@ Here are some tips for styling the sidebar based on different states.
```
-- **Styling a menu action based on the menu button active state.** The following will force the menu action to be visible when the menu button is active.
-
```tsx
@@ -1284,42 +520,108 @@ Here are some tips for styling the sidebar based on different states.
```
-You can find more tips on using states for styling in this [Twitter thread](https://x.com/shadcn/status/1842329158879420864).
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+{/* prettier-ignore */}
+
## Changelog
-### 2024-10-30 Cookie handling in setOpen
+### RTL Support
-- [#5593](https://github.com/shadcn-ui/ui/pull/5593) - Improved setOpen callback logic in ``.
+If you're upgrading from a previous version of the `Sidebar` component, you'll need to apply the following updates to add RTL support:
-Update the `setOpen` callback in `` as follows:
+
-```tsx showLineNumbers
-const setOpen = React.useCallback(
- (value: boolean | ((value: boolean) => boolean)) => {
- const openState = typeof value === "function" ? value(open) : value
- if (setOpenProp) {
- setOpenProp(openState)
- } else {
- _setOpen(openState)
- }
+Add `dir` prop to Sidebar component.
- // This sets the cookie to keep the sidebar state.
- document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
- },
- [setOpenProp, open]
-)
+Add `dir` to the destructured props and pass it to `SheetContent` for mobile:
+
+```diff
+ function Sidebar({
+ side = "left",
+ variant = "sidebar",
+ collapsible = "offcanvas",
+ className,
+ children,
++ dir,
+ ...props
+ }: React.ComponentProps<"div"> & {
+ side?: "left" | "right"
+ variant?: "sidebar" | "floating" | "inset"
+ collapsible?: "offcanvas" | "icon" | "none"
+ }) {
```
-### 2024-10-21 Fixed `text-sidebar-foreground`
+Then pass it to `SheetContent` in the mobile view:
-- [#5491](https://github.com/shadcn-ui/ui/pull/5491) - Moved `text-sidebar-foreground` from `` to `` component.
-
-### 2024-10-20 Typo in `useSidebar` hook.
-
-Fixed typo in `useSidebar` hook.
-
-```diff showLineNumbers title="sidebar.tsx"
-- throw new Error("useSidebar must be used within a Sidebar.")
-+ throw new Error("useSidebar must be used within a SidebarProvider.")
+```diff
+
+ Add `data-side` attribute to sidebar container.
+
+Add `data-side={side}` to the sidebar container element:
+
+```diff
+
Update sidebar container positioning classes.
+
+Replace JavaScript ternary conditional classes with CSS data attribute selectors:
+
+```diff
+ className={cn(
+- "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
+- side === "left"
+- ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
+- : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
++ "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex data-[side=left]:left-0 data-[side=right]:right-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
+```
+
+Update SidebarRail positioning classes.
+
+Update the `SidebarRail` component to use physical positioning for the rail:
+
+```diff
+ className={cn(
+- "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-end-4 group-data-[side=right]:start-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] sm:flex",
++ "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 ltr:-translate-x-1/2 rtl:-translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] sm:flex",
+```
+
+Add RTL flip to SidebarTrigger icon.
+
+Add `className="rtl:rotate-180"` to the icon in `SidebarTrigger` to flip it in RTL mode:
+
+```diff
+
+```
+
+
+
+After applying these changes, you can use the `dir` prop to set the direction:
+
+```tsx
+
+ {/* ... */}
+
+```
+
+The sidebar will correctly position itself and handle interactions in both LTR and RTL layouts.
diff --git a/apps/v4/content/docs/components/base/skeleton.mdx b/apps/v4/content/docs/components/base/skeleton.mdx
index 5b76c21c34..1877d8bf74 100644
--- a/apps/v4/content/docs/components/base/skeleton.mdx
+++ b/apps/v4/content/docs/components/base/skeleton.mdx
@@ -78,3 +78,9 @@ import { Skeleton } from "@/components/ui/skeleton"
### Table
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/base/slider.mdx b/apps/v4/content/docs/components/base/slider.mdx
index 6b7f9d1691..3cf7331b23 100644
--- a/apps/v4/content/docs/components/base/slider.mdx
+++ b/apps/v4/content/docs/components/base/slider.mdx
@@ -92,6 +92,12 @@ Use the `disabled` prop to disable the slider.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Slider](https://base-ui.com/react/components/slider#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/spinner.mdx b/apps/v4/content/docs/components/base/spinner.mdx
index 63f1644add..d209690563 100644
--- a/apps/v4/content/docs/components/base/spinner.mdx
+++ b/apps/v4/content/docs/components/base/spinner.mdx
@@ -105,3 +105,9 @@ Add a spinner to a badge to indicate a loading state. Remember to use the `data-
### Empty
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/base/switch.mdx b/apps/v4/content/docs/components/base/switch.mdx
index c0e7ffe7a8..8dad18fe18 100644
--- a/apps/v4/content/docs/components/base/switch.mdx
+++ b/apps/v4/content/docs/components/base/switch.mdx
@@ -92,6 +92,12 @@ Use the `size` prop to change the size of the switch.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Switch](https://base-ui.com/react/components/switch#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/table.mdx b/apps/v4/content/docs/components/base/table.mdx
index 7d376692fc..dea24857e2 100644
--- a/apps/v4/content/docs/components/base/table.mdx
+++ b/apps/v4/content/docs/components/base/table.mdx
@@ -104,3 +104,14 @@ You can use the `
` component to build more complex data tables. Combine
See the [Data Table](/docs/components/data-table) documentation for more information.
You can also see an example of a data table in the [Tasks](/examples/tasks) demo.
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/base/tabs.mdx b/apps/v4/content/docs/components/base/tabs.mdx
index 7ed16873fe..b3c42a4eca 100644
--- a/apps/v4/content/docs/components/base/tabs.mdx
+++ b/apps/v4/content/docs/components/base/tabs.mdx
@@ -95,6 +95,12 @@ Use `orientation="vertical"` for vertical tabs.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Tabs](https://base-ui.com/react/components/tabs#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/textarea.mdx b/apps/v4/content/docs/components/base/textarea.mdx
index 7c075ffac3..ea3c4f565b 100644
--- a/apps/v4/content/docs/components/base/textarea.mdx
+++ b/apps/v4/content/docs/components/base/textarea.mdx
@@ -98,3 +98,9 @@ Pair with `Button` to create a textarea with a submit button.
name="textarea-button"
previewClassName="*:max-w-xs"
/>
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/base/toggle-group.mdx b/apps/v4/content/docs/components/base/toggle-group.mdx
index 2a7ba570f5..cde192e6e6 100644
--- a/apps/v4/content/docs/components/base/toggle-group.mdx
+++ b/apps/v4/content/docs/components/base/toggle-group.mdx
@@ -96,6 +96,16 @@ Use `orientation="vertical"` for vertical toggle groups.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Toggle Group](https://base-ui.com/react/components/toggle-group#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/toggle.mdx b/apps/v4/content/docs/components/base/toggle.mdx
index 715ea4cac9..40c661a396 100644
--- a/apps/v4/content/docs/components/base/toggle.mdx
+++ b/apps/v4/content/docs/components/base/toggle.mdx
@@ -33,7 +33,7 @@ npx shadcn@latest add toggle
Install the following dependencies:
```bash
-npm install @base-ui-components/react
+npm install @base-ui/react
```
Copy and paste the following code into your project.
@@ -84,6 +84,12 @@ Use the `size` prop to change the size of the toggle.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Toggle](https://base-ui.com/react/components/toggle#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/tooltip.mdx b/apps/v4/content/docs/components/base/tooltip.mdx
index f003809f3f..3bddb8a40c 100644
--- a/apps/v4/content/docs/components/base/tooltip.mdx
+++ b/apps/v4/content/docs/components/base/tooltip.mdx
@@ -33,7 +33,7 @@ npx shadcn@latest add tooltip
Install the following dependencies:
```bash
-npm install @base-ui-components/react
+npm install @base-ui/react
```
Copy and paste the following code into your project.
@@ -89,6 +89,12 @@ Show a tooltip on a disabled button by wrapping it with a span.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Base UI Tooltip](https://base-ui.com/react/components/tooltip#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/base/typography.mdx b/apps/v4/content/docs/components/base/typography.mdx
index 8fb0f25a01..af8a044337 100644
--- a/apps/v4/content/docs/components/base/typography.mdx
+++ b/apps/v4/content/docs/components/base/typography.mdx
@@ -65,3 +65,14 @@ We do not ship any typography styles by default. This page is an example of how
## Muted
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/radix/accordion.mdx b/apps/v4/content/docs/components/radix/accordion.mdx
index 1fd0638dda..72d0b6fc36 100644
--- a/apps/v4/content/docs/components/radix/accordion.mdx
+++ b/apps/v4/content/docs/components/radix/accordion.mdx
@@ -137,6 +137,17 @@ Wrap the `Accordion` in a `Card` component.
previewClassName="*:data-[slot=accordion]:max-w-sm h-[32rem] md:h-[28rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI](https://www.radix-ui.com/primitives/docs/components/accordion#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/radix/alert-dialog.mdx b/apps/v4/content/docs/components/radix/alert-dialog.mdx
index e69f4e8366..b36577099b 100644
--- a/apps/v4/content/docs/components/radix/alert-dialog.mdx
+++ b/apps/v4/content/docs/components/radix/alert-dialog.mdx
@@ -146,6 +146,17 @@ Use the `AlertDialogAction` component to add a destructive action button to the
previewClassName="h-56"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### size
diff --git a/apps/v4/content/docs/components/radix/alert.mdx b/apps/v4/content/docs/components/radix/alert.mdx
index 709ab5e458..3c65fdbd9f 100644
--- a/apps/v4/content/docs/components/radix/alert.mdx
+++ b/apps/v4/content/docs/components/radix/alert.mdx
@@ -113,6 +113,17 @@ You can customize the alert colors by adding custom classes such as `bg-amber-50
previewClassName="h-auto sm:h-72 p-6"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Alert
diff --git a/apps/v4/content/docs/components/radix/aspect-ratio.mdx b/apps/v4/content/docs/components/radix/aspect-ratio.mdx
index fb426193b9..f08ad1ed81 100644
--- a/apps/v4/content/docs/components/radix/aspect-ratio.mdx
+++ b/apps/v4/content/docs/components/radix/aspect-ratio.mdx
@@ -82,6 +82,17 @@ A portrait aspect ratio component using the `ratio={9 / 16}` prop. This is usefu
previewClassName="h-96"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### AspectRatio
diff --git a/apps/v4/content/docs/components/radix/avatar.mdx b/apps/v4/content/docs/components/radix/avatar.mdx
index c8e96f84cc..ef8652b191 100644
--- a/apps/v4/content/docs/components/radix/avatar.mdx
+++ b/apps/v4/content/docs/components/radix/avatar.mdx
@@ -145,6 +145,17 @@ You can use the `Avatar` component as a trigger for a dropdown menu.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Avatar
diff --git a/apps/v4/content/docs/components/radix/badge.mdx b/apps/v4/content/docs/components/radix/badge.mdx
index a6cd129ba9..87ad710a6d 100644
--- a/apps/v4/content/docs/components/radix/badge.mdx
+++ b/apps/v4/content/docs/components/radix/badge.mdx
@@ -81,6 +81,12 @@ You can customize the colors of a badge by adding custom classes such as `bg-gre
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Badge
diff --git a/apps/v4/content/docs/components/radix/breadcrumb.mdx b/apps/v4/content/docs/components/radix/breadcrumb.mdx
index 9215d66274..114c2aaf4a 100644
--- a/apps/v4/content/docs/components/radix/breadcrumb.mdx
+++ b/apps/v4/content/docs/components/radix/breadcrumb.mdx
@@ -110,6 +110,17 @@ To use a custom link component from your routing library, you can use the `asChi
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Breadcrumb
diff --git a/apps/v4/content/docs/components/radix/button-group.mdx b/apps/v4/content/docs/components/radix/button-group.mdx
index 9b2b0613f7..a6d0091372 100644
--- a/apps/v4/content/docs/components/radix/button-group.mdx
+++ b/apps/v4/content/docs/components/radix/button-group.mdx
@@ -148,6 +148,16 @@ Use with a `Popover` component.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### ButtonGroup
diff --git a/apps/v4/content/docs/components/radix/button.mdx b/apps/v4/content/docs/components/radix/button.mdx
index a958c5f750..10d6fecdd2 100644
--- a/apps/v4/content/docs/components/radix/button.mdx
+++ b/apps/v4/content/docs/components/radix/button.mdx
@@ -141,6 +141,12 @@ You can use the `asChild` prop on `` to make another component look li
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Button
diff --git a/apps/v4/content/docs/components/radix/calendar.mdx b/apps/v4/content/docs/components/radix/calendar.mdx
index d4ab11f899..b208100489 100644
--- a/apps/v4/content/docs/components/radix/calendar.mdx
+++ b/apps/v4/content/docs/components/radix/calendar.mdx
@@ -237,270 +237,174 @@ Use `showWeekNumber` to show week numbers.
previewClassName="h-96"
/>
-## Upgrade Guide
+## RTL
-### Tailwind v4
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
-If you're already using Tailwind v4, you can upgrade to the latest version of the `Calendar` component by running the following command:
+See also the [Hijri Guide](#persian--hijri--jalali-calendar) for enabling the Persian / Hijri / Jalali calendar.
-```bash
-npx shadcn@latest add calendar
+
+
+When using RTL, import the locale from `react-day-picker/locale` and pass both the `locale` and `dir` props to the Calendar component:
+
+```tsx showLineNumbers
+import { arSA } from "react-day-picker/locale"
+
+;
```
-When you're prompted to overwrite the existing `Calendar` component, select `Yes`. **If you have made any changes to the `Calendar` component, you will need to merge your changes with the new version.**
-
-This will update the `Calendar` component and `react-day-picker` to the latest version.
-
-Next, follow the [React DayPicker](https://daypicker.dev/upgrading) upgrade guide to upgrade your existing components to the latest version.
-
-#### Installing Blocks
-
-After upgrading the `Calendar` component, you can install the new blocks by running the `shadcn@latest add` command.
-
-```bash
-npx shadcn@latest add calendar-02
-```
-
-This will install the latest version of the calendar blocks.
-
-### Tailwind v3
-
-If you're using Tailwind v3, you can upgrade to the latest version of the `Calendar` by copying the following code to your `calendar.tsx` file.
-
-
-
-```tsx showLineNumbers title="components/ui/calendar.tsx"
-"use client"
-
-import * as React from "react"
-import {
- ChevronDownIcon,
- ChevronLeftIcon,
- ChevronRightIcon,
-} from "lucide-react"
-import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"
-
-import { cn } from "@/lib/utils"
-import { Button, buttonVariants } from "@/components/ui/button"
-
-function Calendar({
- className,
- classNames,
- showOutsideDays = true,
- captionLayout = "label",
- buttonVariant = "ghost",
- formatters,
- components,
- ...props
-}: React.ComponentProps & {
- buttonVariant?: React.ComponentProps["variant"]
-}) {
- const defaultClassNames = getDefaultClassNames()
-
- return (
- svg]:rotate-180`,
- String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
- className
- )}
- captionLayout={captionLayout}
- formatters={{
- formatMonthDropdown: (date) =>
- date.toLocaleString("default", { month: "short" }),
- ...formatters,
- }}
- classNames={{
- root: cn("w-fit", defaultClassNames.root),
- months: cn(
- "relative flex flex-col gap-4 md:flex-row",
- defaultClassNames.months
- ),
- month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
- nav: cn(
- "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
- defaultClassNames.nav
- ),
- button_previous: cn(
- buttonVariants({ variant: buttonVariant }),
- "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
- defaultClassNames.button_previous
- ),
- button_next: cn(
- buttonVariants({ variant: buttonVariant }),
- "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
- defaultClassNames.button_next
- ),
- month_caption: cn(
- "flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]",
- defaultClassNames.month_caption
- ),
- dropdowns: cn(
- "flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium",
- defaultClassNames.dropdowns
- ),
- dropdown_root: cn(
- "has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border",
- defaultClassNames.dropdown_root
- ),
- dropdown: cn("absolute inset-0 opacity-0", defaultClassNames.dropdown),
- caption_label: cn(
- "select-none font-medium",
- captionLayout === "label"
- ? "text-sm"
- : "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5",
- defaultClassNames.caption_label
- ),
- table: "w-full border-collapse",
- weekdays: cn("flex", defaultClassNames.weekdays),
- weekday: cn(
- "text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal",
- defaultClassNames.weekday
- ),
- week: cn("mt-2 flex w-full", defaultClassNames.week),
- week_number_header: cn(
- "w-[--cell-size] select-none",
- defaultClassNames.week_number_header
- ),
- week_number: cn(
- "text-muted-foreground select-none text-[0.8rem]",
- defaultClassNames.week_number
- ),
- day: cn(
- "relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
- props.showWeekNumber
- ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md"
- : "[&:first-child[data-selected=true]_button]:rounded-l-md",
- defaultClassNames.day
- ),
- range_start: cn(
- "bg-accent rounded-l-md",
- defaultClassNames.range_start
- ),
- range_middle: cn("rounded-none", defaultClassNames.range_middle),
- range_end: cn("bg-accent rounded-r-md", defaultClassNames.range_end),
- today: cn(
- "bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
- defaultClassNames.today
- ),
- outside: cn(
- "text-muted-foreground aria-selected:text-muted-foreground",
- defaultClassNames.outside
- ),
- disabled: cn(
- "text-muted-foreground opacity-50",
- defaultClassNames.disabled
- ),
- hidden: cn("invisible", defaultClassNames.hidden),
- ...classNames,
- }}
- components={{
- Root: ({ className, rootRef, ...props }) => {
- return (
-
- )
- },
- Chevron: ({ className, orientation, ...props }) => {
- if (orientation === "left") {
- return (
-
- )
- }
-
- if (orientation === "right") {
- return (
-
- )
- }
-
- return (
-
- )
- },
- DayButton: CalendarDayButton,
- WeekNumber: ({ children, ...props }) => {
- return (
-
-
- {children}
-
-
- )
- },
- ...components,
- }}
- {...props}
- />
- )
-}
-
-function CalendarDayButton({
- className,
- day,
- modifiers,
- ...props
-}: React.ComponentProps) {
- const defaultClassNames = getDefaultClassNames()
-
- const ref = React.useRef(null)
- React.useEffect(() => {
- if (modifiers.focused) ref.current?.focus()
- }, [modifiers.focused])
-
- return (
-
-
-**If you have made any changes to the `Calendar` component, you will need to merge your changes with the new version.**
-
-Then follow the [React DayPicker](https://daypicker.dev/upgrading) upgrade guide to upgrade your dependencies and existing components to the latest version.
-
-#### Installing Blocks
-
-After upgrading the `Calendar` component, you can install the new blocks by running the `shadcn@latest add` command.
-
-```bash
-npx shadcn@latest add calendar-02
-```
-
-This will install the latest version of the calendar blocks.
-
## API Reference
-See the [React DayPicker](https://react-day-picker.js.org) documentation for more information on the `Calendar` component API.
+See the [React DayPicker](https://react-day-picker.js.org) documentation for more information on the `Calendar` component.
+
+## Changelog
+
+### RTL Support
+
+If you're upgrading from a previous version of the `Calendar` component, you'll need to apply the following updates to add locale support:
+
+
+
+Import the `Locale` type.
+
+Add `Locale` to your imports from `react-day-picker`:
+
+```diff
+ import {
+ DayPicker,
+ getDefaultClassNames,
+ type DayButton,
++ type Locale,
+ } from "react-day-picker"
+```
+
+Add `locale` prop to the Calendar component.
+
+Add the `locale` prop to the component's props:
+
+```diff
+ function Calendar({
+ className,
+ classNames,
+ showOutsideDays = true,
+ captionLayout = "label",
+ buttonVariant = "ghost",
++ locale,
+ formatters,
+ components,
+ ...props
+ }: React.ComponentProps & {
+ buttonVariant?: React.ComponentProps["variant"]
+ }) {
+```
+
+Pass `locale` to DayPicker.
+
+Pass the `locale` prop to the `DayPicker` component:
+
+```diff
+
+- date.toLocaleString("default", { month: "short" }),
++ date.toLocaleString(locale?.code, { month: "short" }),
+ ...formatters,
+ }}
+```
+
+Update CalendarDayButton to accept locale.
+
+Update the `CalendarDayButton` component signature and pass `locale`:
+
+```diff
+ function CalendarDayButton({
+ className,
+ day,
+ modifiers,
++ locale,
+ ...props
+- }: React.ComponentProps) {
++ }: React.ComponentProps & { locale?: Partial }) {
+```
+
+Update date formatting in CalendarDayButton.
+
+Use `locale?.code` in the date formatting:
+
+```diff
+
+```
+
+Pass locale to DayButton component.
+
+Update the `DayButton` component usage to pass the `locale` prop:
+
+```diff
+ components={{
+ ...
+- DayButton: CalendarDayButton,
++ DayButton: ({ ...props }) => (
++
++ ),
+ ...
+ }}
+```
+
+Update RTL-aware CSS classes.
+
+Replace directional classes with logical properties for better RTL support:
+
+```diff
+ // In the day classNames:
+- [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius)
++ [&:last-child[data-selected=true]_button]:rounded-e-(--cell-radius)
+- [&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)
++ [&:nth-child(2)[data-selected=true]_button]:rounded-s-(--cell-radius)
+- [&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)
++ [&:first-child[data-selected=true]_button]:rounded-s-(--cell-radius)
+
+ // In range_start classNames:
+- rounded-l-(--cell-radius) ... after:right-0
++ rounded-s-(--cell-radius) ... after:end-0
+
+ // In range_end classNames:
+- rounded-r-(--cell-radius) ... after:left-0
++ rounded-e-(--cell-radius) ... after:start-0
+
+ // In CalendarDayButton className:
+- data-[range-end=true]:rounded-r-(--cell-radius)
++ data-[range-end=true]:rounded-e-(--cell-radius)
+- data-[range-start=true]:rounded-l-(--cell-radius)
++ data-[range-start=true]:rounded-s-(--cell-radius)
+```
+
+
+
+After applying these changes, you can use the `locale` prop to provide locale-specific formatting:
+
+```tsx
+import { enUS } from "react-day-picker/locale"
+
+;
+```
diff --git a/apps/v4/content/docs/components/radix/card.mdx b/apps/v4/content/docs/components/radix/card.mdx
index c3e0b564b8..865694d6f4 100644
--- a/apps/v4/content/docs/components/radix/card.mdx
+++ b/apps/v4/content/docs/components/radix/card.mdx
@@ -99,6 +99,17 @@ Add an image before the card header to create a card with an image.
previewClassName="h-[32rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Card
diff --git a/apps/v4/content/docs/components/radix/carousel.mdx b/apps/v4/content/docs/components/radix/carousel.mdx
index d3b13c1ae8..52732239ed 100644
--- a/apps/v4/content/docs/components/radix/carousel.mdx
+++ b/apps/v4/content/docs/components/radix/carousel.mdx
@@ -285,6 +285,38 @@ export function Example() {
previewClassName="sm:h-[32rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
+When localizing the carousel for RTL languages, you need to set the `direction` option in the `opts` prop to match the text direction. This ensures the carousel scrolls in the correct direction.
+
+```tsx showLineNumbers {2-5}
+
+
+ ...
+ ...
+ ...
+
+
+
+
+```
+
+The `direction` option accepts `"ltr"` or `"rtl"` and should match the `dir` prop value. You may also want to rotate the navigation buttons using the `rtl:rotate-180` class to ensure they point in the correct direction.
+
## API Reference
See the [Embla Carousel docs](https://www.embla-carousel.com/api/plugins/) for more information on props and plugins.
diff --git a/apps/v4/content/docs/components/radix/chart.mdx b/apps/v4/content/docs/components/radix/chart.mdx
index 1dd1d0edf4..8bfa840a97 100644
--- a/apps/v4/content/docs/components/radix/chart.mdx
+++ b/apps/v4/content/docs/components/radix/chart.mdx
@@ -580,3 +580,14 @@ This prop adds keyboard access and screen reader support to your charts.
```tsx title="components/example-chart.tsx"
```
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/radix/checkbox.mdx b/apps/v4/content/docs/components/radix/checkbox.mdx
index a8af620620..a1fa244217 100644
--- a/apps/v4/content/docs/components/radix/checkbox.mdx
+++ b/apps/v4/content/docs/components/radix/checkbox.mdx
@@ -122,6 +122,17 @@ Use multiple fields to create a checkbox list.
previewClassName="p-4 md:p-8"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI](https://www.radix-ui.com/docs/primitives/components/checkbox#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/radix/collapsible.mdx b/apps/v4/content/docs/components/radix/collapsible.mdx
index c9bb35b4dd..2571e312ca 100644
--- a/apps/v4/content/docs/components/radix/collapsible.mdx
+++ b/apps/v4/content/docs/components/radix/collapsible.mdx
@@ -122,6 +122,17 @@ Use nested collapsibles to build a file tree.
previewClassName="h-[36rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI](https://www.radix-ui.com/docs/primitives/components/collapsible#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/radix/combobox.mdx b/apps/v4/content/docs/components/radix/combobox.mdx
index fca3eaf527..4ccc4eb4e6 100644
--- a/apps/v4/content/docs/components/radix/combobox.mdx
+++ b/apps/v4/content/docs/components/radix/combobox.mdx
@@ -254,7 +254,18 @@ You can trigger the combobox from a button or any other component by using the `
You can add an addon to the combobox by using the `InputGroupAddon` component inside the `ComboboxInput`.
-
+
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
## API Reference
diff --git a/apps/v4/content/docs/components/radix/command.mdx b/apps/v4/content/docs/components/radix/command.mdx
index 7211da3a34..3f1e46eb67 100644
--- a/apps/v4/content/docs/components/radix/command.mdx
+++ b/apps/v4/content/docs/components/radix/command.mdx
@@ -120,6 +120,18 @@ Scrollable command menu with multiple items.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [cmdk](https://github.com/dip/cmdk) documentation for more information.
diff --git a/apps/v4/content/docs/components/radix/context-menu.mdx b/apps/v4/content/docs/components/radix/context-menu.mdx
index 7c4863da40..3022d286f4 100644
--- a/apps/v4/content/docs/components/radix/context-menu.mdx
+++ b/apps/v4/content/docs/components/radix/context-menu.mdx
@@ -129,11 +129,15 @@ Use `variant="destructive"` to style the menu item as destructive.
-### Sides
+## RTL
-Control submenu placement with side and align props.
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
-
+
## API Reference
diff --git a/apps/v4/content/docs/components/radix/data-table.mdx b/apps/v4/content/docs/components/radix/data-table.mdx
index 8e42fcdc89..0a417136d8 100644
--- a/apps/v4/content/docs/components/radix/data-table.mdx
+++ b/apps/v4/content/docs/components/radix/data-table.mdx
@@ -11,7 +11,8 @@ links:
styleName="radix-nova"
name="data-table-demo"
align="start"
- previewClassName="items-start h-[28rem] px-4 md:px-8"
+ previewClassName="items-start h-auto px-4 md:px-8"
+ hideCode
/>
## Introduction
@@ -883,3 +884,15 @@ A component to toggle column visibility.
```tsx
```
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/radix/date-picker.mdx b/apps/v4/content/docs/components/radix/date-picker.mdx
index c535f7d5b6..5be14cd6c2 100644
--- a/apps/v4/content/docs/components/radix/date-picker.mdx
+++ b/apps/v4/content/docs/components/radix/date-picker.mdx
@@ -93,3 +93,13 @@ A date picker component with a time input field for selecting a time.
This component uses the `chrono-node` library to parse natural language dates.
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/radix/dialog.mdx b/apps/v4/content/docs/components/radix/dialog.mdx
index fadc790bfc..032834b76d 100644
--- a/apps/v4/content/docs/components/radix/dialog.mdx
+++ b/apps/v4/content/docs/components/radix/dialog.mdx
@@ -111,6 +111,12 @@ Long content can scroll while the header stays in view.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI](https://www.radix-ui.com/docs/primitives/components/dialog#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/radix/direction.mdx b/apps/v4/content/docs/components/radix/direction.mdx
new file mode 100644
index 0000000000..70103cf2c7
--- /dev/null
+++ b/apps/v4/content/docs/components/radix/direction.mdx
@@ -0,0 +1,93 @@
+---
+title: Direction
+description: A provider component that sets the text direction for your application.
+base: radix
+component: true
+links:
+ doc: https://www.radix-ui.com/primitives/docs/utilities/direction-provider
+ api: https://www.radix-ui.com/primitives/docs/utilities/direction-provider#api-reference
+---
+
+The `DirectionProvider` component is used to set the text direction (`ltr` or `rtl`) for your application. This is essential for supporting right-to-left languages like Arabic, Hebrew, and Persian.
+
+Here's a preview of the component in RTL mode. Use the language selector to switch the language. To see more examples, look for the RTL section on components pages.
+
+
+
+## Installation
+
+
+
+
+ Command
+ Manual
+
+
+
+
+```bash
+npx shadcn@latest add direction
+```
+
+
+
+
+
+
+
+Install the following dependencies:
+
+```bash
+npm install radix-ui
+```
+
+Copy and paste the following code into your project.
+
+
+
+Update the import paths to match your project setup.
+
+
+
+
+
+
+
+## Usage
+
+```tsx showLineNumbers
+import { DirectionProvider } from "@/components/ui/direction"
+```
+
+```tsx showLineNumbers
+
+
+
+ {/* Your app content */}
+
+
+
+```
+
+## useDirection
+
+The `useDirection` hook is used to get the current direction of the application.
+
+```tsx showLineNumbers
+import { useDirection } from "@/components/ui/direction"
+
+function MyComponent() {
+ const direction = useDirection()
+ return
Current direction: {direction}
+}
+```
diff --git a/apps/v4/content/docs/components/radix/drawer.mdx b/apps/v4/content/docs/components/radix/drawer.mdx
index 780852d9ad..3f50d10f1b 100644
--- a/apps/v4/content/docs/components/radix/drawer.mdx
+++ b/apps/v4/content/docs/components/radix/drawer.mdx
@@ -108,6 +108,12 @@ You can combine the `Dialog` and `Drawer` components to create a responsive dial
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Vaul documentation](https://vaul.emilkowal.ski/getting-started) for the full API reference.
diff --git a/apps/v4/content/docs/components/radix/dropdown-menu.mdx b/apps/v4/content/docs/components/radix/dropdown-menu.mdx
index cb495066b3..18212665f2 100644
--- a/apps/v4/content/docs/components/radix/dropdown-menu.mdx
+++ b/apps/v4/content/docs/components/radix/dropdown-menu.mdx
@@ -163,6 +163,16 @@ A richer example combining groups, icons, and submenus.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI documentation](https://www.radix-ui.com/docs/primitives/components/dropdown-menu) for the full API reference.
diff --git a/apps/v4/content/docs/components/radix/empty.mdx b/apps/v4/content/docs/components/radix/empty.mdx
index 9df80aa0ad..89a01bb5fa 100644
--- a/apps/v4/content/docs/components/radix/empty.mdx
+++ b/apps/v4/content/docs/components/radix/empty.mdx
@@ -127,6 +127,12 @@ You can add an `InputGroup` component to the `EmptyContent` component.
previewClassName="h-96 p-0"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Empty
diff --git a/apps/v4/content/docs/components/radix/field.mdx b/apps/v4/content/docs/components/radix/field.mdx
index 0caa3d5c74..856c8eeb61 100644
--- a/apps/v4/content/docs/components/radix/field.mdx
+++ b/apps/v4/content/docs/components/radix/field.mdx
@@ -162,6 +162,17 @@ Stack `Field` components with `FieldGroup`. Add `FieldSeparator` to divide them.
previewClassName="h-96"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## Responsive Layout
- **Vertical fields:** Default orientation stacks label, control, and helper text—ideal for mobile-first layouts.
diff --git a/apps/v4/content/docs/components/radix/hover-card.mdx b/apps/v4/content/docs/components/radix/hover-card.mdx
index f8666501bf..fe8e4f7ba7 100644
--- a/apps/v4/content/docs/components/radix/hover-card.mdx
+++ b/apps/v4/content/docs/components/radix/hover-card.mdx
@@ -118,6 +118,17 @@ Use the `side` and `align` props on `HoverCardContent` to control placement.
previewClassName="h-[22rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI](https://www.radix-ui.com/docs/primitives/components/hover-card#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/radix/input-group.mdx b/apps/v4/content/docs/components/radix/input-group.mdx
index a495baa64c..1b27dffbd8 100644
--- a/apps/v4/content/docs/components/radix/input-group.mdx
+++ b/apps/v4/content/docs/components/radix/input-group.mdx
@@ -191,6 +191,17 @@ Here's an example of a custom resizable textarea from a third-party library.
previewClassName="h-56"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### InputGroup
diff --git a/apps/v4/content/docs/components/radix/input-otp.mdx b/apps/v4/content/docs/components/radix/input-otp.mdx
index 878bcb23ff..f4ec29276b 100644
--- a/apps/v4/content/docs/components/radix/input-otp.mdx
+++ b/apps/v4/content/docs/components/radix/input-otp.mdx
@@ -142,6 +142,12 @@ Use `REGEXP_ONLY_DIGITS_AND_CHARS` to accept both letters and numbers.
previewClassName="h-[30rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [input-otp](https://input-otp.rodz.dev) documentation for more information.
diff --git a/apps/v4/content/docs/components/radix/input.mdx b/apps/v4/content/docs/components/radix/input.mdx
index c84a3d3e6f..a22e0d19ce 100644
--- a/apps/v4/content/docs/components/radix/input.mdx
+++ b/apps/v4/content/docs/components/radix/input.mdx
@@ -188,3 +188,14 @@ A full form example with multiple inputs, a select, and a button.
name="input-form"
previewClassName="h-[32rem]"
/>
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/radix/item.mdx b/apps/v4/content/docs/components/radix/item.mdx
index 1fe21ede5c..f0d8939ab2 100644
--- a/apps/v4/content/docs/components/radix/item.mdx
+++ b/apps/v4/content/docs/components/radix/item.mdx
@@ -163,6 +163,12 @@ Use the `asChild` prop to render the item as a link. The hover and focus states
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Item
diff --git a/apps/v4/content/docs/components/radix/kbd.mdx b/apps/v4/content/docs/components/radix/kbd.mdx
index 2f259b0f5d..a4a408a398 100644
--- a/apps/v4/content/docs/components/radix/kbd.mdx
+++ b/apps/v4/content/docs/components/radix/kbd.mdx
@@ -79,6 +79,12 @@ You can use the `Kbd` component inside a `InputGroupAddon` component to display
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### Kbd
diff --git a/apps/v4/content/docs/components/radix/label.mdx b/apps/v4/content/docs/components/radix/label.mdx
index 460c0cf6af..6a10a3aa53 100644
--- a/apps/v4/content/docs/components/radix/label.mdx
+++ b/apps/v4/content/docs/components/radix/label.mdx
@@ -85,6 +85,12 @@ includes built-in `FieldLabel`, `FieldDescription`, and `FieldError` components.
previewClassName="h-[44rem]"
/>
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI Label](https://www.radix-ui.com/docs/primitives/components/label#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/radix/menubar.mdx b/apps/v4/content/docs/components/radix/menubar.mdx
index 10b38faa97..e6f34b3e98 100644
--- a/apps/v4/content/docs/components/radix/menubar.mdx
+++ b/apps/v4/content/docs/components/radix/menubar.mdx
@@ -112,6 +112,12 @@ Use `MenubarSub`, `MenubarSubTrigger`, and `MenubarSubContent` for nested menus.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI Menubar](https://www.radix-ui.com/docs/primitives/components/menubar#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/meta.json b/apps/v4/content/docs/components/radix/meta.json
index 1e71ba5d95..4ec87e8a04 100644
--- a/apps/v4/content/docs/components/radix/meta.json
+++ b/apps/v4/content/docs/components/radix/meta.json
@@ -22,6 +22,7 @@
"data-table",
"date-picker",
"dialog",
+ "direction",
"drawer",
"dropdown-menu",
"empty",
diff --git a/apps/v4/content/docs/components/radix/native-select.mdx b/apps/v4/content/docs/components/radix/native-select.mdx
index 4d7a7b8a9b..1b8a7a45f0 100644
--- a/apps/v4/content/docs/components/radix/native-select.mdx
+++ b/apps/v4/content/docs/components/radix/native-select.mdx
@@ -95,6 +95,16 @@ Use `aria-invalid` to show validation errors and the `data-invalid` attribute to
- Use `NativeSelect` for native browser behavior, better performance, or mobile-optimized dropdowns.
- Use `Select` for custom styling, animations, or complex interactions.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
### NativeSelect
diff --git a/apps/v4/content/docs/components/radix/navigation-menu.mdx b/apps/v4/content/docs/components/radix/navigation-menu.mdx
index ea89dec3e8..455b21f3ff 100644
--- a/apps/v4/content/docs/components/radix/navigation-menu.mdx
+++ b/apps/v4/content/docs/components/radix/navigation-menu.mdx
@@ -12,6 +12,7 @@ links:
styleName="radix-nova"
name="navigation-menu-demo"
previewClassName="h-96"
+ className="overflow-visible"
/>
## Installation
@@ -105,6 +106,18 @@ export function NavigationMenuDemo() {
}
```
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI Navigation Menu](https://www.radix-ui.com/docs/primitives/components/navigation-menu#api-reference) documentation for more information.
diff --git a/apps/v4/content/docs/components/radix/pagination.mdx b/apps/v4/content/docs/components/radix/pagination.mdx
index 2fb018939c..e109d411eb 100644
--- a/apps/v4/content/docs/components/radix/pagination.mdx
+++ b/apps/v4/content/docs/components/radix/pagination.mdx
@@ -127,3 +127,73 @@ const PaginationLink = ({...props }: ) => (
**Note:** We are making updates to the cli to automatically do this for you.
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
+## Changelog
+
+### RTL Support
+
+If you're upgrading from a previous version of the `Pagination` component, you'll need to apply the following updates to add the `text` prop:
+
+
+
+Update `PaginationPrevious`.
+
+```diff
+ function PaginationPrevious({
+ className,
++ text = "Previous",
+ ...props
+- }: React.ComponentProps) {
++ }: React.ComponentProps & { text?: string }) {
+ return (
+
+
+
+- Previous
++ {text}
+
+
+ )
+ }
+```
+
+Update `PaginationNext`.
+
+```diff
+ function PaginationNext({
+ className,
++ text = "Next",
+ ...props
+- }: React.ComponentProps) {
++ }: React.ComponentProps & { text?: string }) {
+ return (
+
+- Next
++ {text}
+
+
+ )
+ }
+```
+
+
diff --git a/apps/v4/content/docs/components/radix/popover.mdx b/apps/v4/content/docs/components/radix/popover.mdx
index 944d70c61b..7636e1a798 100644
--- a/apps/v4/content/docs/components/radix/popover.mdx
+++ b/apps/v4/content/docs/components/radix/popover.mdx
@@ -99,6 +99,12 @@ A popover with form fields inside.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI Popover](https://www.radix-ui.com/docs/primitives/components/popover#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/progress.mdx b/apps/v4/content/docs/components/radix/progress.mdx
index c8bf8f35b5..0662b4dd9b 100644
--- a/apps/v4/content/docs/components/radix/progress.mdx
+++ b/apps/v4/content/docs/components/radix/progress.mdx
@@ -76,6 +76,12 @@ A progress bar that can be controlled by a slider.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI Progress](https://www.radix-ui.com/docs/primitives/components/progress#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/radio-group.mdx b/apps/v4/content/docs/components/radix/radio-group.mdx
index 0317662bbe..154a1eb4df 100644
--- a/apps/v4/content/docs/components/radix/radio-group.mdx
+++ b/apps/v4/content/docs/components/radix/radio-group.mdx
@@ -104,6 +104,16 @@ Use `aria-invalid` on `RadioGroupItem` and `data-invalid` on `Field` to show val
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI Radio Group](https://www.radix-ui.com/docs/primitives/components/radio-group#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/resizable.mdx b/apps/v4/content/docs/components/radix/resizable.mdx
index 4eb79e4b22..78ffa09780 100644
--- a/apps/v4/content/docs/components/radix/resizable.mdx
+++ b/apps/v4/content/docs/components/radix/resizable.mdx
@@ -71,7 +71,7 @@ import {
```
```tsx showLineNumbers
-
+OneTwo
@@ -82,7 +82,7 @@ import {
### Vertical
-Use `direction="vertical"` for vertical resizing.
+Use `orientation="vertical"` for vertical resizing.
@@ -92,6 +92,36 @@ Use the `withHandle` prop on `ResizableHandle` to show a visible handle.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [react-resizable-panels](https://github.com/bvaughn/react-resizable-panels/tree/main/packages/react-resizable-panels) documentation.
+
+## Changelog
+
+### 2025-02-02 `react-resizable-panels` v4
+
+Updated to `react-resizable-panels` v4. See the [v4.0.0 release notes](https://github.com/bvaughn/react-resizable-panels/releases/tag/4.0.0) for full details.
+
+If you're using `react-resizable-panels` primitives directly, note the following changes:
+
+| v3 | v4 |
+| ---------------------------- | ----------------------- |
+| `PanelGroup` | `Group` |
+| `PanelResizeHandle` | `Separator` |
+| `direction` prop | `orientation` prop |
+| `defaultSize={50}` | `defaultSize="50%"` |
+| `onLayout` | `onLayoutChange` |
+| `ImperativePanelHandle` | `PanelImperativeHandle` |
+| `ref` prop on Panel | `panelRef` prop |
+| `data-panel-group-direction` | `aria-orientation` |
+
+
+ The shadcn/ui wrapper components (`ResizablePanelGroup`, `ResizablePanel`,
+ `ResizableHandle`) remain unchanged.
+
diff --git a/apps/v4/content/docs/components/radix/scroll-area.mdx b/apps/v4/content/docs/components/radix/scroll-area.mdx
index 353908d269..b2b3cb43d8 100644
--- a/apps/v4/content/docs/components/radix/scroll-area.mdx
+++ b/apps/v4/content/docs/components/radix/scroll-area.mdx
@@ -76,6 +76,17 @@ Use `ScrollBar` with `orientation="horizontal"` for horizontal scrolling.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI Scroll Area](https://www.radix-ui.com/docs/primitives/components/scroll-area#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/select.mdx b/apps/v4/content/docs/components/radix/select.mdx
index 97706faa7d..073faf5b35 100644
--- a/apps/v4/content/docs/components/radix/select.mdx
+++ b/apps/v4/content/docs/components/radix/select.mdx
@@ -59,6 +59,7 @@ npm install radix-ui
import {
Select,
SelectContent,
+ SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
@@ -71,9 +72,11 @@ import {
- Light
- Dark
- System
+
+ Light
+ Dark
+ System
+
```
@@ -117,6 +120,12 @@ Add the `data-invalid` attribute to the `Field` component and the `aria-invalid`
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI Select](https://www.radix-ui.com/docs/primitives/components/select#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/separator.mdx b/apps/v4/content/docs/components/radix/separator.mdx
index 344b59e7d7..8c342d2403 100644
--- a/apps/v4/content/docs/components/radix/separator.mdx
+++ b/apps/v4/content/docs/components/radix/separator.mdx
@@ -82,6 +82,12 @@ Horizontal separators between list items.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI Separator](https://www.radix-ui.com/docs/primitives/components/separator#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/sheet.mdx b/apps/v4/content/docs/components/radix/sheet.mdx
index 1be1e249ca..6ae74c6495 100644
--- a/apps/v4/content/docs/components/radix/sheet.mdx
+++ b/apps/v4/content/docs/components/radix/sheet.mdx
@@ -93,6 +93,12 @@ Use `showCloseButton={false}` on `SheetContent` to hide the close button.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI Dialog](https://www.radix-ui.com/docs/primitives/components/dialog#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/sidebar.mdx b/apps/v4/content/docs/components/radix/sidebar.mdx
index 74f6376cc7..14cd915945 100644
--- a/apps/v4/content/docs/components/radix/sidebar.mdx
+++ b/apps/v4/content/docs/components/radix/sidebar.mdx
@@ -5,6 +5,8 @@ base: radix
component: true
---
+import { ExternalLinkIcon } from "lucide-react"
+
-
-
-Run the following command to install `sidebar.tsx`
-
```bash
npx shadcn@latest add sidebar
```
-Add the following colors to your CSS file
-
-The command above should install the colors for you. If not, copy and paste the following in your CSS file.
-
-We'll go over the colors later in the [theming section](/docs/components/sidebar#theming).
-
-```css showLineNumbers title="app/globals.css"
-@layer base {
- :root {
- --sidebar: oklch(0.985 0 0);
- --sidebar-foreground: oklch(0.145 0 0);
- --sidebar-primary: oklch(0.205 0 0);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.97 0 0);
- --sidebar-accent-foreground: oklch(0.205 0 0);
- --sidebar-border: oklch(0.922 0 0);
- --sidebar-ring: oklch(0.708 0 0);
- }
-
- .dark {
- --sidebar: oklch(0.205 0 0);
- --sidebar-foreground: oklch(0.985 0 0);
- --sidebar-primary: oklch(0.488 0.243 264.376);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.269 0 0);
- --sidebar-accent-foreground: oklch(0.985 0 0);
- --sidebar-border: oklch(1 0 0 / 10%);
- --sidebar-ring: oklch(0.439 0 0);
- }
-}
-```
-
-
-
-
-
-Copy and paste the following code into your project.
-
-Update the import paths to match your project setup.
-
-Add the following colors to your CSS file
-
-We'll go over the colors later in the [theming section](/docs/components/sidebar#theming).
-
-```css showLineNumbers title="app/globals.css"
-@layer base {
- :root {
- --sidebar: oklch(0.985 0 0);
- --sidebar-foreground: oklch(0.145 0 0);
- --sidebar-primary: oklch(0.205 0 0);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.97 0 0);
- --sidebar-accent-foreground: oklch(0.205 0 0);
- --sidebar-border: oklch(0.922 0 0);
- --sidebar-ring: oklch(0.708 0 0);
- }
-
- .dark {
- --sidebar: oklch(0.205 0 0);
- --sidebar-foreground: oklch(0.985 0 0);
- --sidebar-primary: oklch(0.488 0.243 264.376);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.269 0 0);
- --sidebar-accent-foreground: oklch(0.985 0 0);
- --sidebar-border: oklch(1 0 0 / 10%);
- --sidebar-ring: oklch(0.439 0 0);
- }
-}
-```
-
-
-
@@ -200,149 +123,6 @@ export function AppSidebar() {
}
```
-## Your First Sidebar
-
-Let's start with the most basic sidebar. A collapsible sidebar with a menu.
-
-
-
-
- Add a `SidebarProvider` and `SidebarTrigger` at the root of your application.
-
-
-```tsx showLineNumbers title="app/layout.tsx"
-import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
-import { AppSidebar } from "@/components/app-sidebar"
-
-export default function Layout({ children }: { children: React.ReactNode }) {
- return (
-
-
-
-
- {children}
-
-
- )
-}
-```
-
-Create a new sidebar component at `components/app-sidebar.tsx`.
-
-```tsx showLineNumbers title="components/app-sidebar.tsx"
-import { Sidebar, SidebarContent } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return (
-
-
-
- )
-}
-```
-
-Now, let's add a `SidebarMenu` to the sidebar.
-
-We'll use the `SidebarMenu` component in a `SidebarGroup`.
-
-```tsx showLineNumbers title="components/app-sidebar.tsx"
-import { Calendar, Home, Inbox, Search, Settings } from "lucide-react"
-
-import {
- Sidebar,
- SidebarContent,
- SidebarGroup,
- SidebarGroupContent,
- SidebarGroupLabel,
- SidebarMenu,
- SidebarMenuButton,
- SidebarMenuItem,
-} from "@/components/ui/sidebar"
-
-// Menu items.
-const items = [
- {
- title: "Home",
- url: "#",
- icon: Home,
- },
- {
- title: "Inbox",
- url: "#",
- icon: Inbox,
- },
- {
- title: "Calendar",
- url: "#",
- icon: Calendar,
- },
- {
- title: "Search",
- url: "#",
- icon: Search,
- },
- {
- title: "Settings",
- url: "#",
- icon: Settings,
- },
-]
-
-export function AppSidebar() {
- return (
-
-
-
- Application
-
-
- {items.map((item) => (
-
-
-
-
- {item.title}
-
-
-
- ))}
-
-
-
-
-
- )
-}
-```
-
-You've created your first sidebar.
-
-You should see something like this:
-
-
-
-
- Your first sidebar.
-
-
-
-
-
-## Components
-
-The components in `sidebar.tsx` are built to be composable i.e you build your sidebar by putting the provided components together. They also compose well with other shadcn/ui components such as `DropdownMenu`, `Collapsible` or `Dialog` etc.
-
-**If you need to change the code in `sidebar.tsx`, you are encouraged to do so. The code is yours. Use `sidebar.tsx` as a starting point and build your own.**
-
-In the next sections, we'll go over each component and how to use them.
-
## SidebarProvider
The `SidebarProvider` component is used to provide the sidebar context to the `Sidebar` component. You should always wrap your application in a `SidebarProvider` component.
@@ -364,11 +144,9 @@ const SIDEBAR_WIDTH = "16rem"
const SIDEBAR_WIDTH_MOBILE = "18rem"
```
-For multiple sidebars in your application, you can use the `style` prop to set the width of the sidebar.
+For multiple sidebars in your application, you can use the `--sidebar-width` and `--sidebar-width-mobile` CSS variables in the `style` prop.
-To set the width of the sidebar, you can use the `--sidebar-width` and `--sidebar-width-mobile` CSS variables in the `style` prop.
-
-```tsx showLineNumbers title="components/ui/sidebar.tsx"
+```tsx showLineNumbers
```
-This will handle the width of the sidebar but also the layout spacing.
-
### Keyboard Shortcut
-The `SIDEBAR_KEYBOARD_SHORTCUT` variable is used to set the keyboard shortcut used to open and close the sidebar.
-
To trigger the sidebar, you use the `cmd+b` keyboard shortcut on Mac and `ctrl+b` on Windows.
-You can change the keyboard shortcut by updating the `SIDEBAR_KEYBOARD_SHORTCUT` variable.
-
```tsx showLineNumbers title="components/ui/sidebar.tsx"
const SIDEBAR_KEYBOARD_SHORTCUT = "b"
```
-### Persisted State
-
-The `SidebarProvider` supports persisting the sidebar state across page reloads and server-side rendering. It uses cookies to store the current state of the sidebar. When the sidebar state changes, a default cookie named `sidebar_state` is set with the current open/closed state. This cookie is then read on subsequent page loads to restore the sidebar state.
-
-To persist sidebar state in Next.js, set up your `SidebarProvider` in `app/layout.tsx` like this:
-
-```tsx showLineNumbers title="app/layout.tsx"
-import { cookies } from "next/headers"
-
-import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
-import { AppSidebar } from "@/components/app-sidebar"
-
-export async function Layout({ children }: { children: React.ReactNode }) {
- const cookieStore = await cookies()
- const defaultOpen = cookieStore.get("sidebar_state")?.value === "true"
-
- return (
-
-
-
-
- {children}
-
-
- )
-}
-```
-
-You can change the name of the cookie by updating the `SIDEBAR_COOKIE_NAME` variable in `sidebar.tsx`.
-
-```tsx showLineNumbers title="components/ui/sidebar.tsx"
-const SIDEBAR_COOKIE_NAME = "sidebar_state"
-```
-
## Sidebar
The main `Sidebar` component used to render a collapsible sidebar.
-```tsx showLineNumbers
-import { Sidebar } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return
-}
-```
-
### Props
| Property | Type | Description |
@@ -447,33 +177,11 @@ export function AppSidebar() {
| `variant` | `sidebar`, `floating`, or `inset` | The variant of the sidebar. |
| `collapsible` | `offcanvas`, `icon`, or `none` | Collapsible state of the sidebar. |
-### side
-
-Use the `side` prop to change the side of the sidebar.
-
-Available options are `left` and `right`.
-
-```tsx showLineNumbers
-import { Sidebar } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return
-}
-```
-
-### variant
-
-Use the `variant` prop to change the variant of the sidebar.
-
-Available options are `sidebar`, `floating` and `inset`.
-
-```tsx showLineNumbers
-import { Sidebar } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return
-}
-```
+| Prop | Description |
+| ----------- | ------------------------------------------------------------ |
+| `offcanvas` | A collapsible sidebar that slides in from the left or right. |
+| `icon` | A sidebar that collapses to icons. |
+| `none` | A non-collapsible sidebar. |
**Note:** If you use the `inset` variant, remember to wrap your main content
@@ -489,26 +197,6 @@ export function AppSidebar() {
```
-### collapsible
-
-Use the `collapsible` prop to make the sidebar collapsible.
-
-Available options are `offcanvas`, `icon` and `none`.
-
-```tsx showLineNumbers
-import { Sidebar } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return
-}
-```
-
-| Prop | Description |
-| ----------- | ------------------------------------------------------------ |
-| `offcanvas` | A collapsible sidebar that slides in from the left or right. |
-| `icon` | A sidebar that collapses to icons. |
-| `none` | A non-collapsible sidebar. |
-
## useSidebar
The `useSidebar` hook is used to control the sidebar.
@@ -543,22 +231,6 @@ export function AppSidebar() {
Use the `SidebarHeader` component to add a sticky header to the sidebar.
-The following example adds a `` to the `SidebarHeader`.
-
-
-
-
- A sidebar header with a dropdown menu.
-
-
-
```tsx showLineNumbers title="components/app-sidebar.tsx"
@@ -575,9 +247,6 @@ The following example adds a `` to the `SidebarHeader`.
Acme Inc
-
- Acme Corp.
-
@@ -590,61 +259,18 @@ The following example adds a `` to the `SidebarHeader`.
Use the `SidebarFooter` component to add a sticky footer to the sidebar.
-The following example adds a `` to the `SidebarFooter`.
-
-
-
-
- A sidebar footer with a dropdown menu.
-
-
-
-```tsx showLineNumbers title="components/app-sidebar.tsx"
-export function AppSidebar() {
- return (
-
-
-
-
-
-
-
-
-
-
- Username
-
-
-
-
-
- Account
-
-
- Billing
-
-
- Sign out
-
-
-
-
-
-
-
-
- )
-}
+```tsx showLineNumbers
+
+
+
+
+
+ Username
+
+
+
+
+
```
## SidebarContent
@@ -652,18 +278,12 @@ export function AppSidebar() {
The `SidebarContent` component is used to wrap the content of the sidebar. This is where you add your `SidebarGroup` components. It is scrollable.
```tsx showLineNumbers
-import { Sidebar, SidebarContent } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return (
-
-
-
-
-
-
- )
-}
+
+
+
+
+
+
```
## SidebarGroup
@@ -672,121 +292,38 @@ Use the `SidebarGroup` component to create a section within the sidebar.
A `SidebarGroup` has a `SidebarGroupLabel`, a `SidebarGroupContent` and an optional `SidebarGroupAction`.
-
-
-
- A sidebar group.
-
-
-
```tsx showLineNumbers
-import { Sidebar, SidebarContent, SidebarGroup } from "@/components/ui/sidebar"
-
-export function AppSidebar() {
- return (
-
-
-
- Application
-
- Add Project
-
-
-
-
-
- )
-}
+
+ Application
+
+ Add Project
+
+
+
```
-## Collapsible SidebarGroup
-
To make a `SidebarGroup` collapsible, wrap it in a `Collapsible`.
-
-
-
- A collapsible sidebar group.
-
-
-
```tsx showLineNumbers
-export function AppSidebar() {
- return (
-
-
-
-
- Help
-
-
-
-
-
-
-
-
- )
-}
-```
-
-
- **Note:** We wrap the `CollapsibleTrigger` in a `SidebarGroupLabel` to render
- a button.
-
-
-## SidebarGroupAction
-
-Use the `SidebarGroupAction` component to add an action button to the `SidebarGroup`.
-
-
-
-
- A sidebar group with an action button.
-
-
-
-```tsx showLineNumbers {5-7}
-export function AppSidebar() {
- return (
-
- Projects
-
- Add Project
-
+
+
+
+
+ Help
+
+
+
+
-
- )
-}
+
+
+
```
## SidebarMenu
The `SidebarMenu` component is used for building a menu within a `SidebarGroup`.
-A `SidebarMenu` component is composed of `SidebarMenuItem`, `SidebarMenuButton`, `` and `` components.
-
-Here's an example of a `SidebarMenu` component rendering a list of projects.
-
-
-
-
- A sidebar menu with a list of projects.
-
-
-
```tsx showLineNumbers
-
-
-
- Projects
-
-
- {projects.map((project) => (
-
-
-
-
- {project.name}
-
-
-
- ))}
-
-
-
-
-
+
+ {projects.map((project) => (
+
+
+
+
+ {project.name}
+
+
+
+ ))}
+
```
## SidebarMenuButton
The `SidebarMenuButton` component is used to render a menu button within a `SidebarMenuItem`.
-### Link or Anchor
-
By default, the `SidebarMenuButton` renders a button but you can use the `asChild` prop to render a different component such as a `Link` or an `a` tag.
-```tsx showLineNumbers
-
- Home
-
-```
-
-### Icon and Label
-
-You can render an icon and a truncated label inside the button. Remember to wrap the label in a ``.
-
-```tsx showLineNumbers
-
-
-
- Home
-
-
-```
-
-### isActive
-
Use the `isActive` prop to mark a menu item as active.
```tsx showLineNumbers
@@ -883,8 +372,6 @@ Use the `isActive` prop to mark a menu item as active.
The `SidebarMenuAction` component is used to render a menu action within a `SidebarMenuItem`.
-This button works independently of the `SidebarMenuButton` i.e you can have the `` as a clickable link and the `` as a button.
-
```tsx showLineNumbers
@@ -899,70 +386,10 @@ This button works independently of the `SidebarMenuButton` i.e you can have the
```
-### DropdownMenu
-
-Here's an example of a `SidebarMenuAction` component rendering a `DropdownMenu`.
-
-
-
-
- A sidebar menu action with a dropdown menu.
-
-
-
-```tsx showLineNumbers
-
-
-
-
- Home
-
-
-
-
-
-
-
-
-
-
- Edit Project
-
-
- Delete Project
-
-
-
-
-```
-
## SidebarMenuSub
The `SidebarMenuSub` component is used to render a submenu within a `SidebarMenu`.
-Use `` and `` to render a submenu item.
-
-
-
-
- A sidebar menu with a submenu.
-
-
-
```tsx showLineNumbers
@@ -970,66 +397,14 @@ Use `` and `` to render a submenu
-
-
-
```
-## Collapsible SidebarMenu
-
-To make a `SidebarMenu` component collapsible, wrap it and the `SidebarMenuSub` components in a `Collapsible`.
-
-
-
-
- A collapsible sidebar menu.
-
-
-
-```tsx showLineNumbers
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
## SidebarMenuBadge
The `SidebarMenuBadge` component is used to render a badge within a `SidebarMenuItem`.
-
-
-
- A sidebar menu with a badge.
-
-
-
```tsx showLineNumbers
@@ -1039,57 +414,22 @@ The `SidebarMenuBadge` component is used to render a badge within a `SidebarMenu
## SidebarMenuSkeleton
-The `SidebarMenuSkeleton` component is used to render a skeleton for a `SidebarMenu`. You can use this to show a loading state when using React Server Components, SWR or react-query.
+The `SidebarMenuSkeleton` component is used to render a skeleton for a `SidebarMenu`.
```tsx showLineNumbers
-function NavProjectsSkeleton() {
- return (
-
- {Array.from({ length: 5 }).map((_, index) => (
-
-
-
- ))}
-
- )
-}
-```
-
-## SidebarSeparator
-
-The `SidebarSeparator` component is used to render a separator within a `Sidebar`.
-
-```tsx showLineNumbers
-
-
-
-
-
-
-
-
-
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+
+ ))}
+
```
## SidebarTrigger
Use the `SidebarTrigger` component to render a button that toggles the sidebar.
-The `SidebarTrigger` component must be used within a `SidebarProvider`.
-
-```tsx showLineNumbers
-
-
-
-
-
-
-```
-
-### Custom Trigger
-
-To create a custom trigger, you can use the `useSidebar` hook.
-
```tsx showLineNumbers
import { useSidebar } from "@/components/ui/sidebar"
@@ -1115,176 +455,10 @@ The `SidebarRail` component is used to render a rail within a `Sidebar`. This ra
```
-## Data Fetching
-
-### React Server Components
-
-Here's an example of a `SidebarMenu` component rendering a list of projects using React Server Components.
-
-
-
-
- A sidebar menu using React Server Components.
-
-
-
-```tsx showLineNumbers {6} title="Skeleton to show loading state."
-function NavProjectsSkeleton() {
- return (
-
- {Array.from({ length: 5 }).map((_, index) => (
-
-
-
- ))}
-
- )
-}
-```
-
-```tsx showLineNumbers {2} title="Server component fetching data."
-async function NavProjects() {
- const projects = await fetchProjects()
-
- return (
-
- {projects.map((project) => (
-
-
-
-
- {project.name}
-
-
-
- ))}
-
- )
-}
-```
-
-```tsx showLineNumbers {8-10} title="Usage with React Suspense."
-function AppSidebar() {
- return (
-
-
-
- Projects
-
- }>
-
-
-
-
-
-
- )
-}
-```
-
-### SWR and React Query
-
-You can use the same approach with [SWR](https://swr.vercel.app/) or [react-query](https://tanstack.com/query/latest/docs/framework/react/overview).
-
-```tsx showLineNumbers title="SWR"
-function NavProjects() {
- const { data, isLoading } = useSWR("/api/projects", fetcher)
-
- if (isLoading) {
- return (
-
- {Array.from({ length: 5 }).map((_, index) => (
-
-
-
- ))}
-
- )
- }
-
- if (!data) {
- return ...
- }
-
- return (
-
- {data.map((project) => (
-
-
-
-
- {project.name}
-
-
-
- ))}
-
- )
-}
-```
-
-```tsx showLineNumbers title="React Query"
-function NavProjects() {
- const { data, isLoading } = useQuery()
-
- if (isLoading) {
- return (
-
- {Array.from({ length: 5 }).map((_, index) => (
-
-
-
- ))}
-
- )
- }
-
- if (!data) {
- return ...
- }
-
- return (
-
- {data.map((project) => (
-
-
-
-
- {project.name}
-
-
-
- ))}
-
- )
-}
-```
-
## Controlled Sidebar
Use the `open` and `onOpenChange` props to control the sidebar.
-
-
-
- A controlled sidebar.
-
-
-
```tsx showLineNumbers
export function AppSidebar() {
const [open, setOpen] = React.useState(false)
@@ -1327,14 +501,10 @@ We use the following CSS variables to theme the sidebar.
}
```
-**We intentionally use different variables for the sidebar and the rest of the application** to make it easy to have a sidebar that is styled differently from the rest of the application. Think a sidebar with a darker shade from the main application.
-
## Styling
Here are some tips for styling the sidebar based on different states.
-- **Styling an element based on the sidebar collapsible state.** The following will hide the `SidebarGroup` when the sidebar is in `icon` mode.
-
```tsx
@@ -1343,8 +513,6 @@ Here are some tips for styling the sidebar based on different states.
```
-- **Styling a menu action based on the menu button active state.** The following will force the menu action to be visible when the menu button is active.
-
```tsx
@@ -1352,42 +520,108 @@ Here are some tips for styling the sidebar based on different states.
```
-You can find more tips on using states for styling in this [Twitter thread](https://x.com/shadcn/status/1842329158879420864).
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+{/* prettier-ignore */}
+
## Changelog
-### 2024-10-30 Cookie handling in setOpen
+### RTL Support
-- [#5593](https://github.com/shadcn-ui/ui/pull/5593) - Improved setOpen callback logic in ``.
+If you're upgrading from a previous version of the `Sidebar` component, you'll need to apply the following updates to add RTL support:
-Update the `setOpen` callback in `` as follows:
+
-```tsx showLineNumbers
-const setOpen = React.useCallback(
- (value: boolean | ((value: boolean) => boolean)) => {
- const openState = typeof value === "function" ? value(open) : value
- if (setOpenProp) {
- setOpenProp(openState)
- } else {
- _setOpen(openState)
- }
+Add `dir` prop to Sidebar component.
- // This sets the cookie to keep the sidebar state.
- document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
- },
- [setOpenProp, open]
-)
+Add `dir` to the destructured props and pass it to `SheetContent` for mobile:
+
+```diff
+ function Sidebar({
+ side = "left",
+ variant = "sidebar",
+ collapsible = "offcanvas",
+ className,
+ children,
++ dir,
+ ...props
+ }: React.ComponentProps<"div"> & {
+ side?: "left" | "right"
+ variant?: "sidebar" | "floating" | "inset"
+ collapsible?: "offcanvas" | "icon" | "none"
+ }) {
```
-### 2024-10-21 Fixed `text-sidebar-foreground`
+Then pass it to `SheetContent` in the mobile view:
-- [#5491](https://github.com/shadcn-ui/ui/pull/5491) - Moved `text-sidebar-foreground` from `` to `` component.
-
-### 2024-10-20 Typo in `useSidebar` hook.
-
-Fixed typo in `useSidebar` hook.
-
-```diff showLineNumbers title="sidebar.tsx"
-- throw new Error("useSidebar must be used within a Sidebar.")
-+ throw new Error("useSidebar must be used within a SidebarProvider.")
+```diff
+
+ Add `data-side` attribute to sidebar container.
+
+Add `data-side={side}` to the sidebar container element:
+
+```diff
+
Update sidebar container positioning classes.
+
+Replace JavaScript ternary conditional classes with CSS data attribute selectors:
+
+```diff
+ className={cn(
+- "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
+- side === "left"
+- ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
+- : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
++ "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex data-[side=left]:left-0 data-[side=right]:right-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
+```
+
+Update SidebarRail positioning classes.
+
+Update the `SidebarRail` component to use physical positioning for the rail:
+
+```diff
+ className={cn(
+- "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-end-4 group-data-[side=right]:start-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] sm:flex",
++ "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 ltr:-translate-x-1/2 rtl:-translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] sm:flex",
+```
+
+Add RTL flip to SidebarTrigger icon.
+
+Add `className="rtl:rotate-180"` to the icon in `SidebarTrigger` to flip it in RTL mode:
+
+```diff
+
+```
+
+
+
+After applying these changes, you can use the `dir` prop to set the direction:
+
+```tsx
+
+ {/* ... */}
+
+```
+
+The sidebar will correctly position itself and handle interactions in both LTR and RTL layouts.
diff --git a/apps/v4/content/docs/components/radix/skeleton.mdx b/apps/v4/content/docs/components/radix/skeleton.mdx
index b35a35286f..4800170062 100644
--- a/apps/v4/content/docs/components/radix/skeleton.mdx
+++ b/apps/v4/content/docs/components/radix/skeleton.mdx
@@ -78,3 +78,9 @@ import { Skeleton } from "@/components/ui/skeleton"
### Table
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/radix/slider.mdx b/apps/v4/content/docs/components/radix/slider.mdx
index 8ee9c6aa32..9aa21ea790 100644
--- a/apps/v4/content/docs/components/radix/slider.mdx
+++ b/apps/v4/content/docs/components/radix/slider.mdx
@@ -92,6 +92,12 @@ Use the `disabled` prop to disable the slider.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix UI Slider](https://www.radix-ui.com/docs/primitives/components/slider#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/spinner.mdx b/apps/v4/content/docs/components/radix/spinner.mdx
index b19ec62ffc..eff7fd6431 100644
--- a/apps/v4/content/docs/components/radix/spinner.mdx
+++ b/apps/v4/content/docs/components/radix/spinner.mdx
@@ -105,3 +105,9 @@ Add a spinner to a badge to indicate a loading state. Remember to use the `data-
### Empty
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/radix/switch.mdx b/apps/v4/content/docs/components/radix/switch.mdx
index 486016d9a5..fb7f75a31f 100644
--- a/apps/v4/content/docs/components/radix/switch.mdx
+++ b/apps/v4/content/docs/components/radix/switch.mdx
@@ -92,6 +92,12 @@ Use the `size` prop to change the size of the switch.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix Switch](https://www.radix-ui.com/docs/primitives/components/switch#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/table.mdx b/apps/v4/content/docs/components/radix/table.mdx
index 3481c0b4a8..e97a619811 100644
--- a/apps/v4/content/docs/components/radix/table.mdx
+++ b/apps/v4/content/docs/components/radix/table.mdx
@@ -104,3 +104,14 @@ You can use the `
` component to build more complex data tables. Combine
See the [Data Table](/docs/components/data-table) documentation for more information.
You can also see an example of a data table in the [Tasks](/examples/tasks) demo.
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/radix/tabs.mdx b/apps/v4/content/docs/components/radix/tabs.mdx
index 02eba3a5c7..6c666dcea2 100644
--- a/apps/v4/content/docs/components/radix/tabs.mdx
+++ b/apps/v4/content/docs/components/radix/tabs.mdx
@@ -95,6 +95,12 @@ Use `orientation="vertical"` for vertical tabs.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix Tabs](https://www.radix-ui.com/docs/primitives/components/tabs#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/textarea.mdx b/apps/v4/content/docs/components/radix/textarea.mdx
index b0a69cb128..1c031e8279 100644
--- a/apps/v4/content/docs/components/radix/textarea.mdx
+++ b/apps/v4/content/docs/components/radix/textarea.mdx
@@ -98,3 +98,9 @@ Pair with `Button` to create a textarea with a submit button.
name="textarea-button"
previewClassName="*:max-w-xs"
/>
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/components/radix/toggle-group.mdx b/apps/v4/content/docs/components/radix/toggle-group.mdx
index b562a5b47d..c87d40c0a3 100644
--- a/apps/v4/content/docs/components/radix/toggle-group.mdx
+++ b/apps/v4/content/docs/components/radix/toggle-group.mdx
@@ -96,6 +96,16 @@ Use `orientation="vertical"` for vertical toggle groups.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix Toggle Group](https://www.radix-ui.com/docs/primitives/components/toggle-group#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/toggle.mdx b/apps/v4/content/docs/components/radix/toggle.mdx
index 1382d7436b..e46a1b7489 100644
--- a/apps/v4/content/docs/components/radix/toggle.mdx
+++ b/apps/v4/content/docs/components/radix/toggle.mdx
@@ -84,6 +84,12 @@ Use the `size` prop to change the size of the toggle.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix Toggle](https://www.radix-ui.com/docs/primitives/components/toggle#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/tooltip.mdx b/apps/v4/content/docs/components/radix/tooltip.mdx
index 5d918178be..526e02a9f2 100644
--- a/apps/v4/content/docs/components/radix/tooltip.mdx
+++ b/apps/v4/content/docs/components/radix/tooltip.mdx
@@ -89,6 +89,12 @@ Show a tooltip on a disabled button by wrapping it with a span.
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
+
## API Reference
See the [Radix Tooltip](https://www.radix-ui.com/docs/primitives/components/tooltip#api-reference) documentation.
diff --git a/apps/v4/content/docs/components/radix/typography.mdx b/apps/v4/content/docs/components/radix/typography.mdx
index a4f00f6f79..d22e43661e 100644
--- a/apps/v4/content/docs/components/radix/typography.mdx
+++ b/apps/v4/content/docs/components/radix/typography.mdx
@@ -65,3 +65,14 @@ We do not ship any typography styles by default. This page is an example of how
## Muted
+
+## RTL
+
+To enable RTL support in shadcn/ui, see the [RTL configuration guide](/docs/rtl).
+
+
diff --git a/apps/v4/content/docs/installation/next.mdx b/apps/v4/content/docs/installation/next.mdx
index c5be9aef28..8679b8078b 100644
--- a/apps/v4/content/docs/installation/next.mdx
+++ b/apps/v4/content/docs/installation/next.mdx
@@ -11,7 +11,7 @@ description: Install and configure shadcn/ui for Next.js.
-### Create project
+### Create Project
Run the `init` command to create a new Next.js project or to setup an existing one:
diff --git a/apps/v4/content/docs/meta.json b/apps/v4/content/docs/meta.json
index 78e7c7b120..cbb5b7683c 100644
--- a/apps/v4/content/docs/meta.json
+++ b/apps/v4/content/docs/meta.json
@@ -7,6 +7,7 @@
"forms",
"installation",
"dark-mode",
+ "rtl",
"registry"
]
}
diff --git a/apps/v4/content/docs/rtl/index.mdx b/apps/v4/content/docs/rtl/index.mdx
new file mode 100644
index 0000000000..0e9a4e1889
--- /dev/null
+++ b/apps/v4/content/docs/rtl/index.mdx
@@ -0,0 +1,163 @@
+---
+title: "RTL"
+description: "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
+
+
+
+
Vite
+
+
+
+
TanStack Start
+
+
+
+## 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-*` and `right-*` are converted to logical equivalents like `start-*` and `end-*`.
+- 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`.
+
+## Try it out
+
+Click the link below to open a Next.js project with RTL support in v0.
+
+[](https://v0.app/chat/api/open?url=https://github.com/shadcn-ui/next-template-rtl)
+
+## 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.).
+
+For other styles, see the [Migration Guide](#migrating-existing-components).
+
+## Font Recommendations
+
+For the best RTL experience, we recommend using fonts that have proper support for your target language. [Noto](https://fonts.google.com/noto) is a great font family for this and it pairs well with Inter and Geist.
+
+See your framework's RTL guide under [Get Started](#get-started) for details on installing and configuring RTL fonts.
+
+## 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](https://github.com/Wombosvideo/tw-animate-css/issues/67) 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.
+
+```tsx showLineNumbers /dir="rtl"/
+
+ Open
+
+