Getting Started
The kit inherits RTL from Arco Mobile. Flip a single useRtl flag on the
ContextProvider and set dir="rtl" on the document — layout direction,
flex alignment, cell chevrons, drawers and carousels mirror automatically.
// Self-contained RTL demo. The preview app's root ContextProvider runs with
// useRtl={false}; here we nest a second ContextProvider with useRtl + a
// dir="rtl" wrapper so only this subtree mirrors. That lets the docs page
// show LTR and RTL side by side in one iframe without any host changes.
import type { ReactNode } from "react"
import { ContextProvider } from "@arco-design/mobile-react"
import { Flex, Footnote1, TouchCell } from "@appboxo/ui-kit"
import { PreviewLayout, Section } from "./_section"
const ROWS_LTR: Array<[string, string]> = [
["Account", "Personal"],
["Currency", "USD"],
["Language", "English"],
]
const ROWS_RTL: Array<[string, string]> = [
["الحساب", "شخصي"],
["العملة", "درهم"],
["اللغة", "العربية"],
]
function CellCard({ rows }: { rows: Array<[string, string]> }) {
return (
<Flex
vertical
gap={2}
style={{ background: "var(--fill-white)", borderRadius: 12 }}
>
{rows.map(([key, val]) => (
<TouchCell
key={key}
className="rtl-tc"
activeClass="cell-active"
onClick={() => {}}
label={key}
>
<Footnote1 color="text-3">{val}</Footnote1>
</TouchCell>
))}
<style>{`
.rtl-tc .arco-cell-inner { min-height: 24px; padding: 12px 16px; }
/* Push the value to the trailing edge; flex-end follows the active
writing direction, so it lands right in LTR and left in RTL. */
.rtl-tc .cell-content.has-label { justify-content: flex-end; }
.cell-active { background: var(--fill-2); }
`}</style>
</Flex>
)
}
function Dir({ rtl, children }: { rtl: boolean; children: ReactNode }) {
return (
<div dir={rtl ? "rtl" : "ltr"}>
<ContextProvider system="ios" useRtl={rtl} useDarkMode={false}>
{children}
</ContextProvider>
</div>
)
}
export function RtlDemoPreview() {
return (
<PreviewLayout>
<Section
title="LTR · useRtl=false"
description="Label leads, value + chevron trail on the right."
>
<Dir rtl={false}>
<CellCard rows={ROWS_LTR} />
</Dir>
</Section>
<Section
title="RTL · useRtl=true"
description="Everything mirrors: label trails right, chevron flips to the left."
>
<Dir rtl>
<CellCard rows={ROWS_RTL} />
</Dir>
</Section>
</PreviewLayout>
)
}
Enable
Two things, both at app startup:
import { ContextProvider } from "@arco-design/mobile-react"
// 1. Tell the browser the writing direction (do this before React paints).
document.documentElement.setAttribute("dir", "rtl")
// 2. Turn on Arco's RTL mode.
ReactDOM.createRoot(document.getElementById("root")!).render(
<ContextProvider system="ios" useRtl useDarkMode={false}>
<App />
</ContextProvider>
)For a per-locale app, drive both off the active language instead of hardcoding:
const isRtl = ["ar", "he", "fa", "ur"].includes(locale)
document.documentElement.setAttribute("dir", isRtl ? "rtl" : "ltr")
// ...
<ContextProvider system="ios" useRtl={isRtl}>What flips automatically
- Layout direction —
Flexrows,justifyshortcuts and page gutters mirror. - Cells —
TouchCell/ ArcoCellmove the label to the right and flip the trailing chevron to the left. - Drawer / PopupSwiper — swipe-in edge and close affordances mirror.
- Carousel — slide direction and indicator order reverse.
- Icons that imply direction — Arco's built-in back/forward arrows swap sides.
What you must handle
- Set
diron the root —useRtlstyles the kit, but the browser still needsdir="rtl"on<html>for native text wrapping, scrollbars and caret behavior. - Keep LTR islands LTR — numbers, phone numbers, currency amounts, code and URLs should not mirror. Wrap them:
<span dir="ltr">+971 50 123 4567</span>- Custom directional icons — any icon you ship yourself that points
left/right (custom back buttons, "next" chevrons) won't auto-flip. Mirror
it with a transform when
dir === "rtl":
[dir="rtl"] .my-chevron { transform: scaleX(-1); }- Prefer logical CSS — in your own overrides use
margin-inline-start/padding-inline-endinstead of-left/-rightso they follow direction.
Per-brand
RTL is orthogonal to theming — any brand can run in either direction. In
practice the Arabic-market brands (adib, riyad, saib, sajda,
sindibad, uab, aya, dana) ship RTL by default, while the rest stay
LTR. The token contract is unchanged; only writing direction differs.
Build mini-apps with Boxo
Appboxo UI Kit is the design system behind partner mini-apps shipping on the Boxo platform.
Learn more about Boxo