注意

当你通过 CLI (npx shadcn@latest add …) 添加组件后,使用编辑器的“全局搜索替换”功能,或者在具体组件文件中手动修改这些类名。

设置阿拉伯文的字体

设置 HTML dir 属性

DirectionProvider

是为整个应用提供全局的文本方向上下文(Text Direction Context),特别是指明应用处于 RTL(Right-to-Left,从右向左) 模式。

1
2
3
4
import { DirectionProvider } from "@radix-ui/react-direction";
export default function RootLayout({ children }) {
  return <DirectionProvider dir="rtl">{children}</DirectionProvider>;
}
  1. 为什么 CSS 的 dir=“rtl” 甚至 html dir=“rtl” 都不够? 通常,我们在 HTML 标签上写 就可以让浏览器自动处理大部分排版(比如文字对齐、Flex/Grid 布局翻转)。 但是,Radix UI (Shadcn 的底层) 是通过 JavaScript 来计算位置、管理焦点和处理键盘事件的,而不是单纯依赖 CSS。Radix 组件需要通过 React Context 明确知道当前的方向,才能正确地执行逻辑。 如果不加 DirectionProvider,Radix 组件会默认假设方向是 ltr (Left-to-Right),即使你的 CSS 已经把页面翻转了,交互逻辑可能还是反的。
  2. 它具体影响了哪些交互逻辑? 当你把 dir 设置为 rtl 后,Radix 会自动调整以下行为: A. 键盘导航 (Keyboard Navigation) 这是最关键的一点。Radix 致力于无障碍访问(A11y),键盘操作必须符合直觉。 Slider (滑块): LTR: 按 右箭头 键,滑块向右移动,数值增加。 RTL: 按 右箭头 键,滑块(物理上)向右移动,但逻辑上代表“后退/减小”;或者按 左箭头 才是“前进/增加”。Radix 会自动处理这种按键映射。 Tabs / Menus (标签页/菜单): LTR: 右箭头 聚焦下一个标签,左箭头 聚焦上一个。 RTL: 左箭头 聚焦下一个标签,右箭头 聚焦上一个。逻辑完全反转。 B. 弹出方向与定位 (Positioning & Collision) Radix 的 Popover, Tooltip, DropdownMenu 使用 JavaScript 计算弹出位置。 Tooltip / Popover: 如果你设置 side=“right”(在右侧显示)。 在 LTR 中,它显示在目标的右边。 在 RTL 中,如果不使用 Provider,它可能还是显示在物理右边,但这符合 RTL 用户的直觉吗?有时候我们需要逻辑上的“开始端(Start)”和“结束端(End)”。 更重要的是 Collisions (碰撞检测):当菜单靠近屏幕边缘时,Radix 需要知道哪一边是“阅读方向的起始边”,以便正确地翻转菜单位置。 C. 组件动画与布局 (Sheet / Dialog) Sheet (侧边抽屉): Shadcn 的 Sheet 组件通常有一个 side 属性。 默认 side=“left”。在 LTR 中,它从左侧滑出。 在 RTL 上下文中,通常希望主菜单从右侧滑出(因为右侧是视觉起点)。虽然这通常结合 CSS 变换,但 Radix 的底层逻辑(如焦点陷阱 Focus Trap)需要知道布局方向,以确保 Tab 键循序正确。

物理属性转逻辑属性

这是一个基于 Tailwind CSS 逻辑属性(Logical Properties)的 Shadcn 组件 RTL 适配对照表:

把所有 ml/mr/pl/pr 批量替换为 ms/me/ps/pe

Tailwind CSS 逻辑属性替换对照表

类别 原始物理类 (LTR) 新逻辑类 (RTL 适配) 说明与常见场景
外边距 (Margin) ml-* ms-* Margin Start
原左边距。例如:列表项之间的间距。
mr-* me-* Margin End
原右边距。例如:图标在左、文字在右时,图标的右间距。
内边距 (Padding) pl-* ps-* Padding Start
原左内边距。
pr-* pe-* Padding End
原右内边距。例如:输入框右侧有图标时,预留的 padding。
定位 (Position) left-* start-* Start Position
原靠左定位。例如:头像左上角的在线状态点。
right-* end-* End Position
原靠右定位。例如:关闭按钮、角标、输入框内部右侧的图标。
文本对齐 (Text) text-left text-start Text Start
文本起始对齐(LTR 下居左,RTL 下居右)。
text-right text-end Text End
文本结束对齐。例如:表格中的数值列通常需要 text-end。
边框 (Border) border-l border-s Border Start
起始边框。
border-r border-e Border End
结束边框。例如:竖向分割线。
圆角 (Rounded) rounded-l-* rounded-s-* Rounded Start
起始侧圆角。例如:按钮组最左侧的按钮。
rounded-r-* rounded-e-* Rounded End
结束侧圆角。例如:按钮组最右侧的按钮。

替换速查口诀

  • Left (左) $\rightarrow$ Start (始) (ml $\rightarrow$ ms, pl $\rightarrow$ ps)
  • Right (右) $\rightarrow$ End (终) (mr $\rightarrow$ me, pr $\rightarrow$ pe)

处理图标翻转 (Icons)

添加 classNamertl:rotate-180

  • ChevronLeft / ChevronRight (左右箭头): 需要翻转
  • ArrowLeft / ArrowRight (左右箭头): 需要翻转