static/app/components/core/splitPanel/splitPanel.mdx
import {Container, Stack} from '@sentry/scraps/layout'; import {SplitPanel} from '@sentry/scraps/splitPanel'; import {Text} from '@sentry/scraps/text';
import {PersistedSizeDemo, SinglePaneDemo} from './stories/splitPanelDemos';
import * as Storybook from 'sentry/stories';
export const documentation = import('!!type-loader!@sentry/scraps/splitPanel/splitPanel');
Pass the resizable pane as sized and the flexible pane as fill, with defaultSize setting the sized pane's initial size. The component fills its parent, so give the parent explicit dimensions.
<Storybook.Demo> <Container width="600px" height="240px" border="primary" radius="md" overflow="hidden"> <SplitPanel defaultSize={300} minSize={120} fillMinSize={120} sized={ <Stack padding="md" background="primary" height="100%"> <Text bold>Sized pane</Text> </Stack> } fill={ <Stack padding="md" background="primary" height="100%"> <Text bold>Fill pane</Text> </Stack> } /> </Container> </Storybook.Demo>
<SplitPanel
defaultSize={300}
minSize={120}
fillMinSize={120}
sized={<SizedPane />}
fill={<FillPane />}
/>
By default the sized pane sits before the divider. Set placement="end" to move it after, placing it on the right in horizontal layouts and on the bottom in vertical ones.
<Storybook.Demo> <Container width="100%" height="240px" border="primary" radius="md" overflow="hidden"> <SplitPanel placement="end" defaultSize={220} minSize={120} fillMinSize={240} sized={ <Stack padding="md" background="primary" height="100%"> <Text bold>Sized pane</Text> </Stack> } fill={ <Stack padding="md" background="primary" height="100%"> <Text bold>Fill pane</Text> </Stack> } /> </Container> </Storybook.Demo>
<SplitPanel
placement="end"
defaultSize={220}
minSize={120}
fillMinSize={240}
sized={<SizedPane />}
fill={<FillPane />}
/>
Set orientation="vertical" to stack the panes top-to-bottom instead of side by side.
<Storybook.Demo> <Container width="100%" height="400px" border="primary" radius="md" overflow="hidden"> <SplitPanel orientation="vertical" defaultSize={220} minSize={120} fillMinSize={160} sized={ <Stack padding="md" background="primary" height="100%"> <Text bold>Sized pane</Text> </Stack> } fill={ <Stack padding="md" background="primary" height="100%"> <Text bold>Fill pane</Text> </Stack> } /> </Container> </Storybook.Demo>
<SplitPanel
orientation="vertical"
defaultSize={220}
minSize={120}
fillMinSize={160}
sized={<SizedPane />}
fill={<FillPane />}
/>
orientation also accepts a responsive value, so you can stack the panes on small screens and place them side by side on larger ones.
<SplitPanel
orientation={{xs: 'vertical', md: 'horizontal'}}
defaultSize={220}
sized={<SizedPane />}
fill={<FillPane />}
/>
Use initialSize to restore a saved size and onResizeEnd to persist user changes. defaultSize remains the double-click reset target.
<Storybook.Demo> <PersistedSizeDemo /> </Storybook.Demo>
const [size, setSize] = useLocalStorageState('scraps-splitpanel-size', 220);
<SplitPanel
defaultSize={220}
initialSize={size}
minSize={120}
fillMinSize={240}
onResizeEnd={({endSize}) => setSize(endSize)}
sized={<SizedPane />}
fill={<FillPane />}
/>;
When fill is omitted, the sized pane fills the whole component and no divider is rendered. This is useful for responsive layouts that temporarily collapse to one pane.
<Storybook.Demo> <SinglePaneDemo /> </Storybook.Demo>
const [collapsed, setCollapsed] = useState(false);
<SplitPanel
defaultSize={220}
minSize={120}
fillMinSize={240}
sized={<SizedPane />}
fill={collapsed ? undefined : <FillPane />}
/>
<Button onClick={() => setCollapsed(c => !c)}>
{collapsed ? 'Show fill pane' : 'Hide fill pane'}
</Button>
Drag the divider to resize, or double-click it to reset the panes to defaultSize.
The divider is also keyboard accessible. Focus it and use: