Splitter
A component that divides your interface into resizable sections
Anatomy
To set up the splitter correctly, you'll need to understand its anatomy and how we name its parts.
Each part includes a
data-part
attribute to help identify them in the DOM.
Examples
Learn how to use the Splitter
component in your project. Let's take a look at the most basic example:
import { Splitter } from '@ark-ui/react/splitter'
export const Basic = () => (
<Splitter.Root panels={[{ id: 'a' }, { id: 'b' }]}>
<Splitter.Panel id="a">A</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">B</Splitter.Panel>
</Splitter.Root>
)
import { Splitter } from '@ark-ui/solid/splitter'
export const Basic = () => (
<Splitter.Root panels={[{ id: 'a' }, { id: 'b' }]}>
<Splitter.Panel id="a">A</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">B</Splitter.Panel>
</Splitter.Root>
)
<script setup lang="ts">
import { Splitter } from '@ark-ui/vue/splitter'
import { ref } from 'vue'
const panels = ref([{ id: 'a' }, { id: 'b' }])
const defaultSizes = ref([50, 50])
</script>
<template>
<Splitter.Root :panels="panels" :defaultSizes="defaultSizes">
<Splitter.Panel id="a">A</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">B</Splitter.Panel>
</Splitter.Root>
</template>
Using Render Props
The Splitter component allows you to pass a function as a child to gain direct access to its API. This provides more control and allows you to modify the size of the panels programmatically:
import { Splitter } from '@ark-ui/react/splitter'
export const RenderProp = () => (
<Splitter.Root panels={[{ id: 'a' }, { id: 'b' }]}>
<Splitter.Context>
{(splitter) => (
<>
<Splitter.Panel id="a">
<button type="button" onClick={() => splitter.resizePanel('a', 10)}>
Set to 10%
</button>
</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">
<button type="button" onClick={() => splitter.resizePanel('b', 10)}>
Set to 10%
</button>
</Splitter.Panel>
</>
)}
</Splitter.Context>
</Splitter.Root>
)
import { Splitter } from '@ark-ui/solid/splitter'
export const RenderProp = () => (
<Splitter.Root defaultSize={[50, 50]} panels={[{ id: 'a' }, { id: 'b' }]}>
<Splitter.Context>
{(api) => (
<>
<Splitter.Panel id="a">
<button type="button" onClick={() => api().resizePanel('a', 10)}>
Set to 10%
</button>
</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">
<button type="button" onClick={() => api().resizePanel('b', 10)}>
Set to 10%
</button>
</Splitter.Panel>
</>
)}
</Splitter.Context>
</Splitter.Root>
)
<script setup lang="ts">
import { Splitter } from '@ark-ui/vue/splitter'
import { ref } from 'vue'
const panels = ref([{ id: 'a' }, { id: 'b' }])
</script>
<template>
<Splitter.Root :panels="panels">
<Splitter.Context v-slot="splitter">
<Splitter.Panel id="a">
<button @click="splitter.resizePanel('a', 10)">Set A to 10%</button>
</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">
<button @click="splitter.resizePanel('b', 10)">Set B to 10%</button>
</Splitter.Panel>
</Splitter.Context>
</Splitter.Root>
</template>
Handling Events
Splitter also provides onSizeChangeStart
and onSizeChangeEnd
events which can be useful to perform some actions
during the start and end of the resizing process:
import { Splitter } from '@ark-ui/react/splitter'
export const Events = () => (
<Splitter.Root
panels={[{ id: 'a' }, { id: 'b' }]}
onResize={(details) => console.log('onResize', details)}
onResizeStart={() => console.log('onResizeStart')}
onResizeEnd={(details) => console.log('onResizeEnd', details)}
onExpand={(details) => console.log('onExpand', details)}
onCollapse={(details) => console.log('onCollapse', details)}
>
<Splitter.Panel id="a">A</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">B</Splitter.Panel>
</Splitter.Root>
)
import { Splitter } from '@ark-ui/solid/splitter'
export const Events = () => (
<Splitter.Root
panels={[{ id: 'a' }, { id: 'b' }]}
defaultSize={[50, 50]}
onResizeStart={() => console.log('onResizeStart')}
onResizeEnd={(details) => console.log('onResizeEnd', details)}
onExpand={(details) => console.log('onExpand', details)}
onCollapse={(details) => console.log('onCollapse', details)}
>
<Splitter.Panel id="a">A</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">B</Splitter.Panel>
</Splitter.Root>
)
<script setup lang="ts">
import { Splitter } from '@ark-ui/vue/splitter'
import { ref } from 'vue'
const panels = ref([{ id: 'a' }, { id: 'b' }])
</script>
<template>
<Splitter.Root
:panels="panels"
@resize="(details) => console.log('onResize', details)"
@resize-start="() => console.log('onResizeStart')"
@resize-end="(details) => console.log('onResizeEnd', details)"
@expand="(details) => console.log('onExpand', details)"
@collapse="(details) => console.log('onCollapse', details)"
>
<Splitter.Panel id="a">A</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">B</Splitter.Panel>
</Splitter.Root>
</template>
Vertical Splitter
By default, the Splitter component is horizontal. If you need a vertical splitter, use the orientation
prop:
import { Splitter } from '@ark-ui/react/splitter'
export const Vertical = () => (
<Splitter.Root orientation="vertical" panels={[{ id: 'a' }, { id: 'b' }]}>
<Splitter.Panel id="a">A</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">B</Splitter.Panel>
</Splitter.Root>
)
import { Splitter } from '@ark-ui/solid/splitter'
export const Vertical = () => (
<Splitter.Root orientation="vertical" defaultSize={[50, 50]} panels={[{ id: 'a' }, { id: 'b' }]}>
<Splitter.Panel id="a">A</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">B</Splitter.Panel>
</Splitter.Root>
)
<script setup lang="ts">
import { Splitter } from '@ark-ui/vue/splitter'
import { ref } from 'vue'
const panels = ref([{ id: 'a' }, { id: 'b' }])
</script>
<template>
<Splitter.Root orientation="vertical" :panels="panels">
<Splitter.Panel id="a">A</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">B</Splitter.Panel>
</Splitter.Root>
</template>
Using the Root Provider
The RootProvider
component provides a context for the splitter. It accepts the value of the useSplitter
hook. You
can leverage it to access the component state and methods from outside the splitter.
import { Splitter, useSplitter } from '@ark-ui/react/splitter'
export const RootProvider = () => {
const splitter = useSplitter({ defaultSize: [50, 50], panels: [{ id: 'a' }, { id: 'b' }] })
return (
<>
<button onClick={() => splitter.setSizes([100, 0])}>Maximize a</button>
<Splitter.RootProvider value={splitter}>
<Splitter.Panel id="a">A</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">B</Splitter.Panel>
</Splitter.RootProvider>
</>
)
}
import { Splitter, useSplitter } from '@ark-ui/solid/splitter'
export const RootProvider = () => {
const splitter = useSplitter({ defaultSize: [50, 50], panels: [{ id: 'a' }, { id: 'b' }] })
return (
<>
<button onClick={() => splitter().setSizes([100, 0])}>Maximize a</button>
<Splitter.RootProvider value={splitter}>
<Splitter.Panel id="a">A</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">B</Splitter.Panel>
</Splitter.RootProvider>
</>
)
}
<script setup lang="ts">
import { Splitter, useSplitter } from '@ark-ui/vue/splitter'
const splitter = useSplitter({
defaultSize: [50, 50],
panels: [{ id: 'a' }, { id: 'b' }],
})
</script>
<template>
<button @click="splitter.setSizes([100, 0])">Maximize a</button>
<Splitter.RootProvider :value="splitter">
<Splitter.Panel id="a">A</Splitter.Panel>
<Splitter.ResizeTrigger id="a:b" aria-label="Resize" />
<Splitter.Panel id="b">B</Splitter.Panel>
</Splitter.RootProvider>
</template>
If you're using the
RootProvider
component, you don't need to use theRoot
component.
API Reference
Root
Prop | Default | Type |
---|---|---|
panels | PanelData[] The size constraints of the panels. | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
defaultSize | number[] The initial size of the panels when rendered. Use when you don't need to control the size of the panels. | |
id | string The unique identifier of the machine. | |
ids | Partial<{
root: string
resizeTrigger(id: string): string
label(id: string): string
panel(id: string | number): string
}> The ids of the elements in the splitter. Useful for composition. | |
keyboardResizeBy | number The number of pixels to resize the panel by when the keyboard is used. | |
nonce | string The nonce for the injected splitter cursor stylesheet. | |
onCollapse | (details: ExpandCollapseDetails) => void Function called when a panel is collapsed. | |
onExpand | (details: ExpandCollapseDetails) => void Function called when a panel is expanded. | |
onResize | (details: ResizeDetails) => void Function called when the splitter is resized. | |
onResizeEnd | (details: ResizeEndDetails) => void Function called when the splitter resize ends. | |
onResizeStart | () => void Function called when the splitter resize starts. | |
orientation | 'horizontal' | 'horizontal' | 'vertical' The orientation of the splitter. Can be `horizontal` or `vertical` |
size | number[] The controlled size data of the panels |
Data Attribute | Value |
---|---|
[data-scope] | splitter |
[data-part] | root |
[data-orientation] | The orientation of the splitter |
Panel
Prop | Default | Type |
---|---|---|
id | string | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Data Attribute | Value |
---|---|
[data-scope] | splitter |
[data-part] | panel |
[data-orientation] | The orientation of the panel |
[data-id] | |
[data-index] | The index of the item |
ResizeTrigger
Prop | Default | Type |
---|---|---|
id | `${string}:${string}` | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
disabled | boolean |
Data Attribute | Value |
---|---|
[data-scope] | splitter |
[data-part] | resize-trigger |
[data-id] | |
[data-orientation] | The orientation of the resizetrigger |
[data-focus] | Present when focused |
[data-disabled] | Present when disabled |
RootProvider
Prop | Default | Type |
---|---|---|
value | UseSplitterReturn | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Accessibility
Complies with the Window Splitter WAI-ARIA design pattern.