AniUI

RTL Support

First-class right-to-left layout support for Arabic, Hebrew, Persian, and other RTL languages.

Hello World

LTR

This is a left-to-right layout example.

Search...
Submit
@
you@example.com
Web preview — components render natively on iOS & Android
import { DirectionProvider } from "@/components/ui/direction-provider";

export default function RootLayout({ children }) {
  return (
    <DirectionProvider defaultDirection="rtl">
      {children}
    </DirectionProvider>
  );
}

Overview#

AniUI components support RTL layouts through two mechanisms:

  • Logical Tailwind properties — components use ps-*, pe-*, ms-*, me-* instead of physical pl-*/pr-* properties, which NativeWind maps to React Native's paddingStart/paddingEnd.
  • DirectionProvider — a context provider that wraps I18nManager and provides a useDirection() hook for reading and setting direction.

Setup#

Install the DirectionProvider component and wrap your root layout:

npx @aniui/cli add direction-provider
app/_layout.tsx
import { DirectionProvider } from "@/components/ui/direction-provider";

export default function RootLayout({ children }) {
  return (
    <DirectionProvider defaultDirection="rtl">
      {children}
    </DirectionProvider>
  );
}

Reading Direction#

Use the useDirection() hook to access the current direction from any child component.

Reading direction
import { useDirection } from "@/components/ui/direction-provider";

function MyComponent() {
  const { isRTL, direction } = useDirection();

  return (
    <View className={cn("flex-row", isRTL && "flex-row-reverse")}>
      <Text>Content adapts to {direction}</Text>
    </View>
  );
}

Logical Properties#

AniUI components use logical CSS properties that automatically adapt to RTL layouts. When writing custom styles, prefer logical properties:

Physical (avoid)Logical (prefer)Description
pl-* / pr-*ps-* / pe-*Padding start/end
ml-* / mr-*ms-* / me-*Margin start/end
text-left / text-righttext-start / text-endText alignment
left-* / right-*start-* / end-*Position
border-l / border-rborder-s / border-eBorder start/end

Flipping Icons#

Directional icons like back arrows need to be flipped in RTL mode. Use scaleX: -1 to mirror them:

Flipping icons
import { useDirection } from "@/components/ui/direction-provider";

function BackButton() {
  const { isRTL } = useDirection();

  return (
    <Pressable onPress={goBack}>
      <Svg
        width={24} height={24}
        viewBox="0 0 24 24"
        style={isRTL ? { transform: [{ scaleX: -1 }] } : undefined}
      >
        <Path d="M15 18l-6-6 6-6" />
      </Svg>
    </Pressable>
  );
}

Component Examples#

Components that use logical properties adapt automatically. No code changes needed.

InputGroup#

InputGroup adapts automatically
// In LTR: [$][___input___]
// In RTL: [___input___][$]  (automatic via logical properties)

<InputGroup>
  <InputGroupAddon align="start">
    <InputGroupText>$</InputGroupText>
  </InputGroupAddon>
  <InputGroupInput placeholder="Amount" />
</InputGroup>

Combobox Multi-select#

Combobox chips flip automatically
// In LTR: [Tag1 ✕] [Tag2 ✕]
// In RTL: [✕ Tag1] [✕ Tag2]  (automatic via logical properties)

<Combobox
  multiple
  selectedValues={["tag1", "tag2"]}
  options={options}
  onSelectedValuesChange={setSelected}
/>

Field#

Field with Arabic text
// Label and description alignment flips automatically
<Field orientation="horizontal">
  <FieldLabel>البريد الإلكتروني</FieldLabel>
  <Input placeholder="أدخل بريدك الإلكتروني" />
  <FieldDescription>سنرسل لك رمز التحقق</FieldDescription>
</Field>

Dynamic Direction Toggle#

Build a settings screen that lets users switch direction:

Settings screen
import { useDirection } from "@/components/ui/direction-provider";
import { SegmentedControl } from "@/components/ui/segmented-control";
import { Field, FieldLabel, FieldDescription } from "@/components/ui/field";

function LanguageSettings() {
  const { direction, setDirection } = useDirection();

  return (
    <Field>
      <FieldLabel>Layout Direction</FieldLabel>
      <SegmentedControl
        values={["LTR", "RTL"]}
        selectedIndex={direction === "ltr" ? 0 : 1}
        onChange={(index) => {
          setDirection(index === 0 ? "ltr" : "rtl");
        }}
      />
      <FieldDescription>
        Changing direction requires restarting the app.
      </FieldDescription>
    </Field>
  );
}

Important#

Calling setDirection updates the React context value immediately for re-renders, but the full layout direction flip via I18nManager.forceRTL() requires an app restart. This is a React Native platform limitation.

For the best user experience, persist the direction preference and apply it before the app renders on next launch.

Component Support#

All AniUI components use logical Tailwind properties and support RTL layouts out of the box.

CategoryComponentsRTLNotes
LayoutField, InputGroup, Card, Grid, SafeAreaFullLogical properties throughout
InputsInput, Textarea, SearchBar, PasswordInput, MaskedInput, PhoneInput, NumberInput, Combobox, SelectFullIcons, addons, and borders flip correctly
DisplayText, Badge, Chip, Label, Kbd, Price, Avatar, ImageFullText alignment handled by NativeWind
FeedbackAlert, Banner, Toast, Spinner, Progress, Skeleton, ConnectionBannerFullDismiss buttons and icons flip
NavigationHeader, TabBar, Tabs, Stepper, ProgressSteps, PaginationFullBack arrows need icon flipping (see above)
OverlaysDialog, AlertDialog, Popover, Tooltip, HoverCard, BottomSheet, DropdownMenu, ContextMenuFullPortal content follows direction context
ActionsButton, Toggle, ToggleGroup, FAB, Switch, Checkbox, RadioGroupFullFAB positions use start/end
DataList, Table, Timeline, ChatBubble, StatCard, Rating, CalendarFullTimeline and chat bubbles flip sides
ProvidersDirectionProvider, ThemeProviderFullCore RTL infrastructure
ChartsAreaChart, BarChart, LineChart, PieChart, RadarChart, RadialChartPartialSVG coordinates are always physical; axis labels may need manual adjustment
GestureSlider, Drawer, SwipeableListItem, CarouselPartialGesture direction and inline styles use physical properties by design

Full = all styles use logical properties, automatic RTL support.
Partial = works in RTL but some visual aspects (SVG coordinates, gesture directions) use physical properties by necessity.

Accessibility#

  • Screen readers automatically respect I18nManager direction settings.
  • Logical properties ensure touch targets and content flow correctly for RTL users.
  • Supports Arabic, Hebrew, Persian, Urdu, and other RTL languages.
  • Works with both Expo SDK 54 (NativeWind v4) and SDK 55 (NativeWind v5).