Stop Making Developers Guess Which Icons to Mirror in RTL
Stop Making Developers Guess Which Icons to Mirror in RTL
别再让开发者去猜哪些图标需要在 RTL 界面中镜像了
Direction is part of an icon’s behavior. In right-to-left interfaces, some icons should mirror. Others should not. A back arrow usually changes direction. A checkmark does not. A reply icon may be directional. A clock should normally remain unchanged. A brand logo definitely should not be mirrored just because the interface is RTL. The problem is that this knowledge often lives in documentation, design files, or simply in someone’s head. That does not scale. 方向性是图标行为的一部分。在从右到左(RTL)的界面中,有些图标需要镜像,而有些则不需要。返回箭头通常需要改变方向,但勾选标记则不需要。回复图标可能具有方向性,而时钟图标通常应保持不变。品牌 Logo 绝对不应该仅仅因为界面是 RTL 就进行镜像。问题在于,这些知识往往只存在于文档、设计文件或某人的脑海中,这无法扩展。
The fragile approach
脆弱的实现方式
A common implementation looks like this: <Icon name="arrow-back" className={isRTL ? "mirror" : ""} /> Then somewhere else: <Icon name="reply" className={isRTL ? "mirror" : ""} /> And somewhere else again, another developer has to decide whether an icon should flip. The same design decision is being made repeatedly. Eventually, inconsistencies appear. One screen mirrors an icon. Another does not. A third developer is not sure and searches the design system documentation. The issue is not really RTL support. The issue is that directional behavior has not been encoded in the icon system.
一种常见的实现方式如下:<Icon name="arrow-back" className={isRTL ? "mirror" : ""} />,然后在其他地方又写上 <Icon name="reply" className={isRTL ? "mirror" : ""} />。在别处,另一位开发者又得重新决定某个图标是否需要翻转。同样的设计决策被反复做出,最终导致了不一致:一个页面镜像了图标,另一个却没有。第三位开发者感到困惑,不得不去查阅设计系统文档。问题的核心不在于 RTL 支持本身,而在于方向性行为没有被编码进图标系统中。
Put the decision next to the icon
将决策与图标绑定
An icon catalog can store more than geometry. For example:
{
"name": "arrow-back",
"directionSensitive": true,
"mirrorInRTL": true
}
A non-directional icon could instead be:
{
"name": "check",
"directionSensitive": false,
"mirrorInRTL": false
}
The important change is simple: the application no longer has to guess. The icon already declares how it behaves. 图标目录不仅可以存储几何形状,还可以存储更多信息。例如:
{
"name": "arrow-back",
"directionSensitive": true,
"mirrorInRTL": true
}
而非方向性图标可以是:
{
"name": "check",
"directionSensitive": false,
"mirrorInRTL": false
}
这一重要的改变很简单:应用程序不再需要猜测,图标本身已经声明了它的行为方式。
Direction can be part of the icon contract
方向性可以成为图标契约的一部分
We often think of an icon asset as: name, SVG path, viewBox, size. But production icon systems frequently need more information: name, geometry, accessibility role, categories, aliases, directional behavior. Once icons are consumed through components, packages, APIs, or generated code, this metadata becomes even more useful. Instead of writing RTL logic everywhere, the component can handle it centrally: 我们通常认为图标资源包含:名称、SVG 路径、viewBox 和尺寸。但生产级的图标系统往往需要更多信息:名称、几何形状、无障碍角色、分类、别名以及方向性行为。一旦图标通过组件、包、API 或生成的代码被消费,这些元数据就会变得更加有用。与其到处编写 RTL 逻辑,不如让组件进行集中处理:
function Icon({ name, dir = "ltr" }) {
const icon = catalog[name];
const shouldMirror = dir === "rtl" && icon.mirrorInRTL;
return (
<svg className={shouldMirror ? "icon-mirrored" : ""} viewBox={icon.viewBox}>
{icon.path}
</svg>
);
}
Now the rendering layer applies a rule already defined by the icon system. 现在,渲染层只需应用图标系统预先定义好的规则即可。
Not every directional icon is the same
并非所有方向性图标都一样
It can also be useful to distinguish between directionSensitive and mirrorInRTL. They describe different things. directionSensitive tells us that the icon has semantic direction. mirrorInRTL tells the renderer what to do in an RTL interface. Today, both values may often match. But separating meaning from rendering behavior leaves room for more advanced cases later. For example, a design system might eventually use a different asset rather than a geometric mirror.
区分 directionSensitive(方向敏感)和 mirrorInRTL(在 RTL 中镜像)也很有用。它们描述的是不同的事物:directionSensitive 告诉我们该图标具有语义上的方向性;mirrorInRTL 则告诉渲染器在 RTL 界面中该怎么做。目前,这两个值可能经常一致,但将“含义”与“渲染行为”分离开来,为未来更高级的场景留出了空间。例如,设计系统最终可能会选择使用不同的资源文件,而不是简单的几何镜像。
The metadata should travel with the asset
元数据应随资源一同分发
This becomes especially important when one icon catalog feeds several outputs: SVG files, React components, Vue components, design system packages, desktop applications, documentation, icon APIs. If RTL behavior exists only in one implementation, every other consumer has to rediscover the rule. If it belongs to the icon metadata, the same decision can propagate everywhere. 当一个图标目录需要支持多种输出(如 SVG 文件、React 组件、Vue 组件、设计系统包、桌面应用、文档、图标 API)时,这一点尤为重要。如果 RTL 行为只存在于某一种实现中,其他所有使用者都必须重新探索该规则。如果它属于图标元数据的一部分,那么相同的决策就可以传播到任何地方。
Icon catalog → metadata → generated components → consistent RTL behavior. That is much more robust than relying on tribal knowledge. 图标目录 → 元数据 → 生成的组件 → 一致的 RTL 行为。这比依赖口口相传的“部落知识”要稳健得多。
A small rule with a large effect
小规则,大影响
RTL support is sometimes treated as a final presentation detail. For icons, it can be more fundamental than that. Some symbols have directional meaning. That meaning is part of how the icon behaves. And behavior is exactly the kind of information a mature icon system should encode once instead of asking every developer to reconstruct it. RTL support is icon metadata, not tribal knowledge. Direction can be part of the icon contract. RTL 支持有时被视为最后的展示细节。但对于图标而言,它可能更为基础。某些符号具有方向性含义,这种含义是图标行为的一部分。而行为正是成熟的图标系统应该一次性编码好的信息,而不是让每个开发者去重复构建。RTL 支持是图标的元数据,而非口口相传的经验。方向性可以成为图标契约的一部分。