Splitter
Two or more panes divided by draggable, adjustable handles, sized in percent.
Installation
Splitter ships with the library — install it once, then import:
import { Splitter } from "@delacour/react-native-ui/splitter";Or copy the source into your project, to own and edit it:
bunx delacour@latest add splitterUsage
import { Splitter } from "@/components/ui/splitter";
import { Text } from "@/components/ui/text";
import { View } from "react-native";
export default function Example() {
return (
<View className="flex-1 p-4">
<Splitter className="h-96" defaultLayout={[35, 65]}>
<Splitter.Pane minSize={20} maxSize={50}>
<Text.Label>Sidebar</Text.Label>
</Splitter.Pane>
<Splitter.Handle accessibilityLabel="Resize sidebar" />
<Splitter.Pane minSize={40}>
<Text.Label>Detail</Text.Label>
</Splitter.Pane>
</Splitter>
</View>
);
}The root needs an extent
Sizes are percentages of the box, so give the root flex-1 or a fixed height. A splitter with no
size divides nothing.
Drag a seam
A drag moves only the two panes beside the handle and settles on the nearest step; a double tap resets.
Panes
variant="panes" gives each pane its own card surface, with a gap in place of the seam's rule.
<Splitter className="h-64" variant="panes">
<Splitter.Pane />
<Splitter.Handle />
<Splitter.Pane />
</Splitter>Three columns
Any number of panes, one handle between each pair; a handle moves only the two panes beside it.
<Splitter className="h-64" defaultLayout={[25, 50, 25]}>
<Splitter.Pane minSize={15} />
<Splitter.Handle accessibilityLabel="Resize files" />
<Splitter.Pane minSize={30} />
<Splitter.Handle accessibilityLabel="Resize inspector" />
<Splitter.Pane minSize={15} />
</Splitter>Vertical
orientation="vertical" stacks the panes and drags along y.
<Splitter className="h-80" orientation="vertical" defaultLayout={[60, 40]}>
<Splitter.Pane minSize={25} />
<Splitter.Handle accessibilityLabel="Resize editor" />
<Splitter.Pane minSize={20} />
</Splitter>Collapsible
A collapsible pane folds away once dragged past half its minSize, and useSplitter() can toggle it.
function ToggleSidebar() {
const { togglePane } = useSplitter();
return (
<Button onPress={() => togglePane(0)}>
<Button.Label>Toggle sidebar</Button.Label>
</Button>
);
}
<Splitter className="h-64">
<Splitter.Pane isCollapsible minSize={25} maxSize={50} />
<Splitter.Handle accessibilityLabel="Resize sidebar" />
<Splitter.Pane minSize={40}>
<ToggleSidebar />
</Splitter.Pane>
</Splitter>Controlled layout
onLayoutChange fires once per release, never per frame — the place to persist a layout.
const [layout, setLayout] = useState([30, 70]);
<Splitter layout={layout} onLayoutChange={setLayout}>
<Splitter.Pane />
<Splitter.Handle />
<Splitter.Pane />
</Splitter>Accessibility
Each handle is adjustable: it reads its label and the size of the pane before it, and offers increment, decrement, reset and — beside a collapsible pane — collapse or expand.
<Splitter step={10}>
<Splitter.Pane />
<Splitter.Handle accessibilityLabel="Resize navigation" />
<Splitter.Pane />
</Splitter>A double tap on a handle resets the layout.
Splitter or SplitView
Splitter is the general engine: two or more panes, either axis, stopping where the finger lets go. SplitView is two stacked panes that settle on named snap points.
API Reference
Anatomy
| Part | What it is |
|---|---|
Splitter | Owns the layout, the measurement and the settle |
Splitter.Pane | One region, sized in percent, with an optional floor, ceiling and collapse |
Splitter.Handle | The draggable, adjustable seam between the pane before it and the pane after it |
Splitter
Prop
Type
Splitter.Pane
Prop
Type
Splitter.Handle
Prop
Type
useSplitter
Prop
Type