Hooks
useDirection
Resolve layout/text direction from local override or a context provider. Defaults to "ltr" when neither is provided.
useDirection
useDirection returns the current layout direction "ltr" or "rtl". It supports:
- Local override: pass a preferred direction directly to the hook for one‑off usage.
- Context provider: wrap parts of your app with
DirectionProviderto set direction for a subtree. - Sensible default: returns
"ltr"if no local or provider value is present.
This hook is useful when building components that need to mirror layout for right‑to‑left languages (e.g., Arabic, Hebrew). It keeps direction resolution explicit and easy to compose.
API
type Direction = 'ltr' | 'rtl';
/**
* Resolve direction with optional local override, then provider, else "ltr".
*/
function useDirection(localDir?: Direction): Direction;Provider
type Direction = 'ltr' | 'rtl';
type DirectionProviderProps = {
dir: Direction;
children?: React.ReactNode;
};
function DirectionProvider(props: DirectionProviderProps): JSX.Element;Provider props
Prop
Type
Usage
1) Resolve direction with provider (recommended)
import * as React from 'react';
import { DirectionProvider, useDirection } from '@loke/ui/use-direction';
function MirroredArrow() {
const dir = useDirection(); // resolves from provider or "ltr"
const isRtl = dir === 'rtl';
return (
<span aria-hidden>
{isRtl ? '←' : '→'}
</span>
);
}
export function App() {
// Set RTL globally for a subtree
return (
<DirectionProvider dir="rtl">
<div className="flex items-center gap-2">
<span>Next</span>
<MirroredArrow />
</div>
</DirectionProvider>
);
}2) Local override (no provider needed)
import { useDirection } from '@loke/ui/use-direction';
function InlineChevron({ forceDir }: { forceDir?: 'ltr' | 'rtl' }) {
// local override takes precedence
const dir = useDirection(forceDir);
return <span aria-hidden>{dir === 'rtl' ? '«' : '»'}</span>;
}
export function Example() {
return (
<div className="flex flex-col gap-2">
<div>
Default (no provider, no override): <InlineChevron />
</div>
<div>
Forced RTL: <InlineChevron forceDir="rtl" />
</div>
<div>
Forced LTR: <InlineChevron forceDir="ltr" />
</div>
</div>
);
}3) Toggle direction at runtime
import * as React from 'react';
import { DirectionProvider, useDirection } from '@loke/ui/use-direction';
function Indicator() {
const dir = useDirection();
return <span className="text-sm text-muted-foreground">dir: {dir}</span>;
}
export function DirectionToggleDemo() {
const [dir, setDir] = React.useState<'ltr' | 'rtl'>('ltr');
return (
<DirectionProvider dir={dir}>
<div className="flex items-center gap-3">
<Indicator />
<button
type="button"
className="rounded border px-2 py-1"
onClick={() => setDir((d) => (d === 'ltr' ? 'rtl' : 'ltr'))}
>
Toggle
</button>
</div>
</DirectionProvider>
);
}Behavior
- Precedence:
- Hook argument
localDir(if provided) - Nearest
DirectionProvidervalue - Fallback
"ltr"
- Hook argument
- Pure computation: the hook does not mutate DOM attributes. Use it to branch behavior or classes in components.
- Composability: nest
DirectionProviderto override direction for sub‑trees (e.g., embedded widgets or localized sections).
Patterns and tips
- Pair with conditional classes:
const dir = useDirection(); const justifyClass = dir === 'rtl' ? 'justify-start' : 'justify-end'; - Prefer
DirectionProviderhigh in the tree to avoid passing direction props everywhere. - Use local override for one‑off rendering (icons/text that differ in RTL).
Import
import { useDirection, DirectionProvider } from '@loke/ui/use-direction';useIsMobile
Detect whether the current viewport is “mobile” (by default, width < 768px) using a media query, and adapt your UI behavior accordingly.
useSize
Observe and return a DOM element’s width and height using ResizeObserver — updates synchronously via a layout effect and returns undefined until an element is available.