Skip to content

RTL Support

RTL (right-to-left) number inputs have a subtle rendering challenge: the numbers themselves are always left-to-right (digits flow 0→9 regardless of script), but the surrounding text and layout flows right-to-left.

raqam handles this automatically for all RTL locales.

raqam detects RTL locales via Intl.NumberFormat.resolvedOptions().locale:

// Detected as RTL:
"ar", "ar-EG", "ar-SA", "ar-MA" // Arabic
"fa", "fa-IR", "fa-AF" // Persian
"he", "he-IL" // Hebrew
"ur", "ur-PK" // Urdu

No configuration needed. Import the locale, set the locale prop, and the correct styles are applied automatically.

For RTL locales, raqam applies two CSS properties to the input element:

direction: ltr; /* numbers flow left-to-right */
text-align: right; /* text is visually right-aligned */
unicode-bidi: embed; /* correct BiDi embedding for currency */

This ensures:

  • Typing ۱, ۲, ۳ inserts digits correctly from left to right
  • The cursor stays in the right place
  • Currency symbols (like or $) appear on the correct side

The input element receives data-rtl="" when the locale is RTL. Use this for additional CSS customization:

input[data-rtl] {
/* extra RTL-specific styles */
padding-inline-end: 12px;
}
import "raqam/locales/fa";
import { NumberField } from "raqam";
<NumberField.Root
locale="fa-IR"
formatOptions={{ style: "currency", currency: "IRR" }}
defaultValue={1234567}
>
<NumberField.Label>مبلغ</NumberField.Label> {/* "Amount" in Persian */}
<NumberField.Group>
<NumberField.Decrement></NumberField.Decrement>
<NumberField.Input />
<NumberField.Increment>+</NumberField.Increment>
</NumberField.Group>
</NumberField.Root>

The input accepts both Persian digits (۱۲۳) and ASCII digits (123), normalizing them to the same value internally.

import "raqam/locales/ar";
import { NumberField } from "raqam";
<NumberField.Root
locale="ar-EG"
formatOptions={{ style: "currency", currency: "EGP" }}
defaultValue={9999}
>
<NumberField.Input />
</NumberField.Root>

Formatted value: ٩٬٩٩٩٫٠٠ ج.م.‏

When embedding a number field in a right-to-left page, wrap the field in a container with dir="rtl":

<div dir="rtl">
<!-- raqam handles the input direction internally -->
<NumberField.Root locale="fa-IR" ...>
...
</NumberField.Root>
</div>

All keyboard shortcuts work correctly in RTL mode:

  • ↑/↓ increment/decrement
  • Backspace over grouping separators (e.g. ٬) skips them correctly
  • Home/End jump to minValue/maxValue