Files
workspace/code/g3soft-libs/docs/content/ui/usage/rtl.md
T
2026-10-09 22:05:02 +08:00

3.9 KiB
Raw Blame History

title, description
title description
双向布局(RTL) 让组件跟随从右到左的书写方向,以及哪些地方刻意不镜像

双向布局(RTL)

组件库同时支持 LTR / RTL。镜像的原则只有一条:跟随行内方向(inline direction), 而不是「左边换成右边」的粗暴翻转。

怎么开启

整站(推荐):宿主在 <html> 上声明方向,组件零配置跟随:

<html lang="ar" dir="rtl">

视觉镜像完全由 CSS 的 [dir='rtl'] 选择器驱动;需要方向语义的 JS 逻辑 (浮层对齐轴、键盘左右键)由 useDirection() 读取 —— 它会观察 documentElement 的 dir / class / style,运行时切换也能跟上。

局部子树:同一页里既有 LTR 又有 RTL 时,用 G3ConfigProvider:

<G3ConfigProvider direction="rtl">
  <G3Form>…</G3Form>
</G3ConfigProvider>

它会把 dir 挂到子树根,同时通过 provide 下发。这条路径在 SSR 首帧就生效, 不受「挂载后才能探测 DOM」影响,是服务端渲染场景的首选。

组件树外:G3Message / G3Notification 这类拿不到 inject 的实例走全局兜底:

G3UI.config({ direction: 'rtl' })

优先级:ConfigProvider → 全局配置 → 文档方向(<html dir>)→ ltr。

写组件样式的规矩

镜像靠逻辑属性实现,组件 <style> 里不要用 left / right:

场景 用什么
缩进、内边距、边框 padding-inline-start / border-inline-start
定位到某一侧 inset-inline-start / inset-inline-end
圆角 border-start-start-radius 等逻辑角
外边距偏移(栅格 offset) margin-inline-start
带符号的位移 token --g3-dir-sign(LTR 1 / RTL -1)
/* 滑块位移:RTL 下自动反向 */
transform: translateX(calc(#{v('dir-sign', 1)} * 12px));

⚠️ 不要用 scaleX(-1) 做整块镜像,文字会变成反字。只有方向性图标(Chevron 系列) 该翻面,统一在 packages/ui/src/_styles/rtl.scss 里按 lucide 自带的 lucide-* 类名处理。

刻意不镜像的地方

这些是物理语义,dir="rtl" 下不会翻,属设计约定:

位置 原因
G3Drawer / G3Modal / G3Tabs 的 placement="left | right" 字面 API,指定的是物理边
浮层(Popover / Tooltip / Dropdown / Select / DatePicker)的主方向 left / right 与 floating-ui 一致:只镜像 *-start / *-end 的对齐轴
浮层箭头、left: 50% 居中、G3Notification 的停靠边 物理锚定,没有行内语义

另外 G3Grid 的 push / pull 已改为沿行内方向位移(跟随方向), 与 Bootstrap 的物理语义不同,迁移时留意。

键盘

水平方向键按行内方向解释:LTR 里 ArrowRight 是「下一个」,RTL 里反过来是 ArrowLeft。 已覆盖:

  • G3Tabs 标签切换
  • G3Tree 展开 / 收起 / 进子节点 / 回父节点
  • G3DatePicker 日期面板的左右移动
  • G3Splitter 分隔条左右调整

G3Radio / G3Segmented 内部是原生 <input type="radio">,键盘行为交给浏览器。

自测

  • playground 右上角 dir: ltr / rtl 开关;也可用 ?dir=rtl 直接以 RTL 进入
  • pnpm --filter @g3soft/ui test:e2e 里的 e2e/rtl.spec.ts 锁住几何镜像 (滑块、滚动条轨道、树缩进、按钮组圆角、浮层对齐、键盘语义)

已知边界

  • 横向 G3Scrollbar 的拖拽在 RTL 下依赖浏览器 scrollLeft 的符号约定。 新版 Chrome / Edge / Safari 已一致;Firefox 未实测。
  • 运行时用脚本直接翻 <html dir> 时,CSS 立即生效,JS 侧靠 MutationObserver 跟随 (同一帧内可能读到旧值,定位类行为会在下一次展开 / 重算时纠正)。 G3ConfigProvider 路径没有这个问题。
  • 语言包目前只有 zhCN / enUS,没有 ar;文案需自行接入。