Skip to content

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:

vue
<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:

vue
<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. المسافات تُحسب من جهة البداية.

vue
<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-righttext-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-2

dir="rtl"

ps-4 / pe-2
vue
<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:

html
<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 logical start/end positions that mirror left/right and flip their slide transform under RTL; the close button uses ms-auto.
  • Toaster — each viewport is placed with logical start-*/end-*, so the four corner positions (top-start, top-end, bottom-start, bottom-end) mirror automatically. The center positions (top-center, bottom-center) use inset-x-0 mx-auto and are direction-neutral.
  • DatePicker — month navigation chevrons use rtl:rotate-180, and labels are locale-formatted and overridable through the labels prop and label-* slots.
  • Input — leading and trailing icons are positioned with start-3/end-3, and the field padding uses ps-*/pe-*.
  • Password — the visibility toggle sits at end-2, and the field reserves pe-10.
  • InputNumber — prefix, the input, and suffix sit in a flex container with gap-1, so their spacing is direction-safe; the stepper-buttons container adds ms-1.
  • TablePagination — previous/next chevrons use rtl:rotate-180.
  • Tag — the remove button uses ms-0.5/-me-0.5.
  • DropdownMenu and Select — overlay positioning comes from Reka UI's popper primitives, which resolve the document direction and pass it to the positioner.

Known gap: TransferList uses a physical text-left on 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.

Released under the MIT License.