Splitter
A number or percent size is flexible; a px or rem size stays fixed as the container changes.
Source
LLM docs
Package
Examples
11
Properties
44
Hooks
1
Basics
Drag or focus the separator to resize the panes.
Loading demo…
import { Block, Splitter, Text } from '@plocks/ui';
export function Demo() {
return (
<Block fullWidth>
<Splitter h={200}>
<Splitter.Pane defaultSize={35} min={20} bg="surface" p="md">
<Text>Sidebar</Text>
</Splitter.Pane>
<Splitter.Pane defaultSize={65} min={20} bg="subtle" p="md">
<Text>Content</Text>
</Splitter.Pane>
</Splitter>
</Block>
);
}Fixed and Flexible Sizes
A pixel-sized sidebar keeps its width as the container changes.
Loading demo…
import { Block, Splitter, Text } from '@plocks/ui';
export function Demo() {
return (
<Block fullWidth>
<Splitter h={160}>
<Splitter.Pane defaultSize="180px" min="120px" bg="subtle" p="md">
<Text>Fixed sidebar</Text>
</Splitter.Pane>
<Splitter.Pane defaultSize={100} bg="surface" p="md">
<Text>Flexible content</Text>
</Splitter.Pane>
</Splitter>
</Block>
);
}Vertical Orientation
Vertical panes resize from a horizontal separator.
Loading demo…
import { Block, Splitter, Text } from '@plocks/ui';
export function Demo() {
return (
<Block fullWidth>
<Splitter orientation="vertical" h={220}>
<Splitter.Pane defaultSize={50} bg="surface" p="md">
<Text>Top</Text>
</Splitter.Pane>
<Splitter.Pane defaultSize={50} bg="subtle" p="md">
<Text>Bottom</Text>
</Splitter.Pane>
</Splitter>
</Block>
);
}Collapsible Pane
A collapsible pane can be toggled through the imperative ref.
Loading demo…
import { useRef } from 'react';
import { Block, Button, Splitter, Text } from '@plocks/ui';
import type { SplitterHandle } from '@plocks/ui';
export function Demo() {
const splitterRef = useRef<SplitterHandle>(null);
return (
<Block fullWidth>
<Button size="sm" onPress={() => splitterRef.current?.toggleCollapse(0)}>
Toggle sidebar
</Button>
<Splitter splitterRef={splitterRef} h={150} mt="sm">
<Splitter.Pane defaultSize={30} collapsible bg="subtle" p="md">
<Text>Sidebar</Text>
</Splitter.Pane>
<Splitter.Pane defaultSize={70} bg="surface" p="md">
<Text>Content</Text>
</Splitter.Pane>
</Splitter>
</Block>
);
}Multiple Panes
Handles appear between every adjacent pair.
Loading demo…
import { Block, Splitter, Text } from '@plocks/ui';
export function Demo() {
return (
<Block fullWidth>
<Splitter h={160}>
<Splitter.Pane defaultSize={25} bg="subtle" p="md">
<Text>One</Text>
</Splitter.Pane>
<Splitter.Pane defaultSize={50} bg="surface" p="md">
<Text>Two</Text>
</Splitter.Pane>
<Splitter.Pane defaultSize={25} bg="subtle" p="md">
<Text>Three</Text>
</Splitter.Pane>
</Splitter>
</Block>
);
}Without Grip
withHandle={false} keeps the separator line without the visual grip.Loading demo…
import { Block, Splitter, Text } from '@plocks/ui';
export function Demo() {
return (
<Block fullWidth>
<Splitter h={160} withHandle={false} lineSize={4}>
<Splitter.Pane defaultSize={50} bg="surface" p="md">
<Text>One</Text>
</Splitter.Pane>
<Splitter.Pane defaultSize={50} bg="subtle" p="md">
<Text>Two</Text>
</Splitter.Pane>
</Splitter>
</Block>
);
}Controlled Sizes
The parent owns the pane sizes through
sizes and onSizeChange.Loading demo…
import { useState } from 'react';
import { Block, Splitter, Text } from '@plocks/ui';
export function Demo() {
const [sizes, setSizes] = useState<[number, number]>([40, 60]);
return (
<Block fullWidth>
<Splitter h={160} sizes={sizes} onSizeChange={(next) => setSizes(next as [number, number])}>
<Splitter.Pane bg="subtle" p="md">
<Text>First ({Math.round(sizes[0])}%)</Text>
</Splitter.Pane>
<Splitter.Pane bg="surface" p="md">
<Text>Second</Text>
</Splitter.Pane>
</Splitter>
</Block>
);
}Nested Splitters
A pane can contain another splitter with its own direction.
Loading demo…
import { Block, Splitter, Text } from '@plocks/ui';
export function Demo() {
return (
<Block fullWidth>
<Splitter h={220}>
<Splitter.Pane defaultSize={40} bg="subtle" p="md">
<Text>Left</Text>
</Splitter.Pane>
<Splitter.Pane defaultSize={60}>
<Splitter orientation="vertical" h={220}>
<Splitter.Pane defaultSize={50} bg="surface" p="md">
<Text>Top</Text>
</Splitter.Pane>
<Splitter.Pane defaultSize={50} bg="subtle" p="md">
<Text>Bottom</Text>
</Splitter.Pane>
</Splitter>
</Splitter.Pane>
</Splitter>
</Block>
);
}Redistribute Space
redistribute="nearest" borrows from farther panes when a neighbor reaches its minimum.Loading demo…
import { Block, Splitter, Text } from '@plocks/ui';
export function Demo() {
return (
<Block fullWidth>
<Splitter h={160} redistribute="nearest">
{['A', 'B', 'C', 'D'].map((item) => (
<Splitter.Pane
key={item}
defaultSize={25}
min={item === 'B' ? 20 : 10}
bg="subtle"
p="sm"
>
<Text>{item}</Text>
</Splitter.Pane>
))}
</Splitter>
</Block>
);
}Line Size
lineSize and handleColor customize the visible separator.Loading demo…
import { Block, Splitter, Text, useTheme } from '@plocks/ui';
export function Demo() {
const theme = useTheme();
return (
<Block fullWidth>
<Splitter h={160} lineSize={4} handleColor={theme.colors.primary[5]}>
<Splitter.Pane defaultSize={40} bg="subtle" p="md">
<Text>Navigation</Text>
</Splitter.Pane>
<Splitter.Pane defaultSize={60} bg="surface" p="md">
<Text>Content</Text>
</Splitter.Pane>
</Splitter>
</Block>
);
}Imperative API
splitterRef exposes collapse and expand controls for each pane.Loading demo…
import { useRef } from 'react';
import { Block, Button, Flex, Splitter, Text } from '@plocks/ui';
import type { SplitterHandle } from '@plocks/ui';
export function Demo() {
const splitterRef = useRef<SplitterHandle>(null);
return (
<Block fullWidth>
<Flex gap="sm">
<Button onPress={() => splitterRef.current?.collapse(0)}>Collapse</Button>
<Button onPress={() => splitterRef.current?.expand(0)}>Expand</Button>
</Flex>
<Splitter h={160} splitterRef={splitterRef} mt="sm">
<Splitter.Pane defaultSize={35} collapsible bg="subtle" p="md">
<Text>Sidebar</Text>
</Splitter.Pane>
<Splitter.Pane defaultSize={65} bg="surface" p="md">
<Text>Content</Text>
</Splitter.Pane>
</Splitter>
</Block>
);
}React Native design for iOS, Android, and Web.
Quick Links
Resources