Direction Provider
RTL/LTR direction context for right-to-left language support.
Installation#
npx @aniui/cli add direction-providerHello World
LTRThis 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 App() {
return (
<DirectionProvider defaultDirection="rtl">
{/* Your app content */}
</DirectionProvider>
);
}Usage#
app/_layout.tsx
import { DirectionProvider } from "@/components/ui/direction-provider";
export default function App() {
return (
<DirectionProvider defaultDirection="rtl">
{/* Your app content */}
</DirectionProvider>
);
}useDirection Hook#
Access the current direction, RTL state, and direction controls from any child component.
Using useDirection
import { useDirection } from "@/components/ui/direction-provider";
export function LanguageToggle() {
const { direction, isRTL, setDirection } = useDirection();
return (
<Button onPress={() => setDirection(isRTL ? "ltr" : "rtl")}>
Current: {direction.toUpperCase()}
</Button>
);
}PropTypeDefault
direction"ltr" | "rtl"-isRTLboolean-setDirection(dir: Direction) => void-Props#
PropTypeDefault
childrenReact.ReactNoderequireddefaultDirection"ltr" | "rtl"system defaultclassNamestring-Also accepts all View props from React Native.
Important#
Calling setDirection updates the React context immediately, but the full layout flip via I18nManager requires an app restart. This is a React Native limitation.
Accessibility#
- Respects
I18nManagerfor system-level RTL detection. - Supports right-to-left languages such as Arabic, Hebrew, and Persian.
- Uses logical properties so layout adapts to direction context.
Source#
components/ui/direction-provider.tsx
import React, { createContext, useContext, useState, useCallback } from "react";
import { I18nManager, View } from "react-native";
import { cn } from "@/lib/utils";
type Direction = "ltr" | "rtl";
interface DirectionContextValue {
direction: Direction;
isRTL: boolean;
setDirection: (dir: Direction) => void;
}
const DirectionContext = createContext<DirectionContextValue>({
direction: I18nManager.isRTL ? "rtl" : "ltr",
isRTL: I18nManager.isRTL,
setDirection: () => {},
});
export function useDirection() {
return useContext(DirectionContext);
}
export interface DirectionProviderProps extends React.ComponentPropsWithoutRef<typeof View> {
children: React.ReactNode;
defaultDirection?: Direction;
className?: string;
}
export function DirectionProvider({
children,
defaultDirection,
className,
...props
}: DirectionProviderProps) {
const initial = defaultDirection ?? (I18nManager.isRTL ? "rtl" : "ltr");
const [direction, setDir] = useState<Direction>(initial);
const setDirection = useCallback((dir: Direction) => {
setDir(dir);
I18nManager.allowRTL(true);
I18nManager.forceRTL(dir === "rtl");
}, []);
return (
<DirectionContext.Provider
value={{ direction, isRTL: direction === "rtl", setDirection }}
>
<View className={cn("flex-1", className)} {...props}>
{children}
</View>
</DirectionContext.Provider>
);
}