RTL & bilingual
English and Arabic are both first-class. Arabic is RTL, and the library ships the logical utilities, rtl: variants, and per-component fixes needed to render both directions without forking styles.
Direction and fonts
Set dir="rtl" at the edge of the RTL subtree and switch to the Arabic font stack:
<div dir="rtl" class="font-ar">
<!-- Arabic content -->
</div>font-ar resolves to GE SS Two, then Adobe Arabic, then system fallbacks. The package ships no @font-face rules — supply the brand fonts yourself. Add lang="ar" next to dir so screen readers and spellcheckers pick the right language:
<section dir="rtl" lang="ar" class="font-ar">…</section>You can also set direction once on <html>; components inherit it. Never mix scripts inside a single lockup or sentence.
مؤسسة مجدي يعقوب
هذا نص توضيحي بخط «GE SS Two» داخل حاوية RTL. المسافات تُحسب من جهة البداية.
<script setup lang="ts">
import { Button } from '@myghf/ui'
</script>
<template>
<section dir="rtl" lang="ar" class="font-ar rounded-lg border border-border bg-surface p-5">
<h3 class="text-lg font-medium text-foreground">مؤسسة مجدي يعقوب</h3>
<p class="mt-1 text-sm text-muted">
هذا نص توضيحي بخط «GE SS Two» داخل حاوية RTL. المسافات تُحسب من جهة البداية.
</p>
<div class="mt-4 flex items-center gap-2">
<Button variant="default">ابدأ</Button>
<Button variant="outline">إلغاء</Button>
</div>
</section>
</template>Prefer logical utilities
Physical utilities assume left-to-right. Logical ones follow the writing direction, so the same markup mirrors under RTL:
| Physical (avoid) | Logical (prefer) |
|---|---|
pl-* / pr-* | ps-* / pe-* |
ml-* / mr-* | ms-* / me-* |
left-* / right-* | start-* / end-* |
text-left / text-right | text-start / text-end |
border-l-* / border-r-* | border-s-* / border-e-* |
rounded-l-* / rounded-r-* | rounded-s-* / rounded-e-* |
Both blocks below use the identical classes — ps-4 pe-2 — and only the dir attribute differs:
dir="ltr"
ps-4 / pe-2dir="rtl"
ps-4 / pe-2<template>
<div class="grid gap-3 sm:grid-cols-2">
<div dir="ltr" class="rounded-lg border border-border bg-surface p-4">
<p class="text-xs uppercase tracking-wide text-muted">dir="ltr"</p>
<div class="mt-2 flex items-center rounded bg-surface-muted py-2 pe-2 ps-4 text-sm text-foreground">
<span><code>ps-4</code> / <code>pe-2</code></span>
</div>
</div>
<div dir="rtl" lang="ar" class="font-ar rounded-lg border border-border bg-surface p-4">
<p class="text-xs uppercase tracking-wide text-muted">dir="rtl"</p>
<div class="mt-2 flex items-center rounded bg-surface-muted py-2 pe-2 ps-4 text-sm text-foreground">
<span><code>ps-4</code> / <code>pe-2</code></span>
</div>
</div>
</div>
</template>rtl: variants
For the handful of truly directional cases, use Tailwind's rtl: variant:
<ChevronLeft class="size-4 rtl:rotate-180" />
<ChevronRight class="size-4 rtl:rotate-180" />rtl: triggers on a [dir="rtl"] ancestor, so it works no matter where direction is set.
Per-component notes
These components already handle direction:
Drawer— exposes logicalstart/endpositions that mirrorleft/rightand flip their slide transform under RTL; the close button usesms-auto.Toaster— each viewport is placed with logicalstart-*/end-*, so the four corner positions (top-start,top-end,bottom-start,bottom-end) mirror automatically. The center positions (top-center,bottom-center) useinset-x-0 mx-autoand are direction-neutral.DatePicker— month navigation chevrons usertl:rotate-180, and labels are locale-formatted and overridable through thelabelsprop andlabel-*slots.Input— leading and trailing icons are positioned withstart-3/end-3, and the field padding usesps-*/pe-*.Password— the visibility toggle sits atend-2, and the field reservespe-10.InputNumber—prefix, the input, andsuffixsit in a flex container withgap-1, so their spacing is direction-safe; the stepper-buttons container addsms-1.TablePagination— previous/next chevrons usertl:rotate-180.Tag— the remove button usesms-0.5/-me-0.5.DropdownMenuandSelect— overlay positioning comes from Reka UI's popper primitives, which resolve the document direction and pass it to the positioner.
Known gap:
TransferListuses a physicaltext-lefton its row buttons, so labels stay left-aligned under RTL instead of following the direction. Direction-aware fixes are otherwise in place.There is no automated RTL visual test. Correctness is reviewed against the logical-utility rule above and verified by inspection, not by CI.