如何在Next.js 14中为Shadcn组件添加RTL支持?
Next.js 14 + Shadcn RTL 不生效及 Radix Direction 错误解决指南
一、修复 Shadcn 组件 RTL 样式不生效问题
Shadcn UI 基于 Tailwind CSS 实现,要让 RTL 样式生效,需配合 Tailwind 的 RTL 支持配置:
- 安装 Tailwind RTL 插件
npm install @tailwindcss/rtl
- 更新 tailwind.config.ts 配置
添加插件以启用 RTL 样式支持:
import type { Config } from 'tailwindcss'; import tailwindcssRTL from '@tailwindcss/rtl'; const config: Config = { content: [ './src/**/*.{js,ts,jsx,tsx,mdx}', ], theme: { extend: {}, }, plugins: [ tailwindcssRTL(), // 保留你原有的其他插件(如 shadcn/ui 插件) ], }; export default config;
保留现有 HTML dir 属性设置
你当前在<html>标签中设置的dir={locale === "fa" ? "rtl" : "ltr"}是正确的,无需修改,Tailwind 和 Shadcn 组件会自动响应这个属性切换布局方向。优化组件样式写法
对于自定义样式,尽量使用 Tailwind 的start/end替代固定的left/right,比如用text-start代替text-left,这样在 RTL 模式下会自动切换为文本右对齐。
二、修复 @radix-ui/react-direction 报错问题
你遇到的 TypeError: createContext is not a function 错误,是因为在 React Server Components(RSC)中使用了仅支持客户端的组件——DirectionProvider 依赖 React Context,而 Context 只能在客户端组件中运行。
解决步骤:
- 封装客户端版 DirectionProvider
创建单独的客户端组件文件,比如src/app/components/DirectionProviderClient.tsx:
'use client'; import { DirectionProvider } from '@radix-ui/react-direction'; type Props = { children: React.ReactNode; dir: 'ltr' | 'rtl'; }; export default function DirectionProviderClient({ children, dir }: Props) { return <DirectionProvider dir={dir}>{children}</DirectionProvider>; }
- 在 Layout 中使用封装后的组件
替换原直接导入的DirectionProvider,改为使用上述客户端组件:
import type { Metadata } from "next"; import "../globals.css"; import localFont from "next/font/local"; import { Provider } from "../../providers"; import { NextIntlClientProvider, useMessages } from "next-intl"; import DirectionProviderClient from "../components/DirectionProviderClient"; const iranSansFont = localFont({ src: "../../fonts/iranSans.woff2", display: "swap", variable: "--font-iranSans", }); export const metadata: Metadata = { title: "Create Next App", description: "Generated by create next app", }; export default function RootLayout({ children, params: { locale }, }: Readonly<{ children: React.ReactElement; params: { locale: string }; }>) { const messages = useMessages(); const dir = locale === "fa" ? "rtl" : "ltr"; return ( <html lang={locale} dir={dir}> <body className={`${iranSansFont.className} bg-background text-foreground px-4 py-4 font-bold`} > <DirectionProviderClient dir={dir}> <NextIntlClientProvider locale={locale} messages={messages}> <Provider>{children}</Provider> </NextIntlClientProvider> </DirectionProviderClient> </body> </html> ); }
- 可选:移除不必要的依赖
如果你不需要在组件内部主动获取当前方向状态,仅靠 HTML 的dir属性就足够让 Tailwind 和 Shadcn 组件适配 RTL,此时可以直接移除@radix-ui/react-direction依赖,简化代码。
额外检查项
- 确认
globals.css中没有覆盖 RTL 相关的默认样式 - 验证波斯字体
iranSans已正确加载,RTL 文本需要适配的字体才能正常排版 - 检查 next-intl 配置,确保 locale 切换时 HTML 的
dir属性同步更新
内容的提问来源于stack exchange,提问作者EhsanKey_
相关产品推荐
相关产品推荐

