Splitter
A splitter allow create dynamic layouts split into vertically or horizontally arranged panes. Panes are separated by the splitter bars that allow dragging to resize or expand/collapse them.
One
Two
One
Two
One
Two
One
Two
Features
Install
Install the component from your command line.
Anatomy
Import all parts and piece them together.
<script setup lang="ts">import * as splitter from "@destyler/splitter"import { normalizeProps, useMachine } from "@destyler/vue"import { computed,useId } from "vue"
const [state, send] = useMachine( splitter.machine({ id: useId(), }))
const api = computed(() => splitter.connect(state.value, send, normalizeProps))</script>
<template> <div v-bind="api.getRootProps()"> <div v-bind="api.getPanelProps({ id: 'a' })"> </div> <div v-bind="api.getResizeTriggerProps({ id: 'a:b' })" /> <div v-bind="api.getPanelProps({ id: 'b' })"> </div> </div></template>
import { normalizeProps, useMachine } from '@destyler/react'import * as splitter from '@destyler/splitter'import { useId } from 'react'
export default function SplitterDemo() {const [state, send] = useMachine( splitter.machine({ id: useId(), }))
const api = splitter.connect(state, send, normalizeProps)
return ( <> <div {...api.getRootProps()}> <div {...api.getPanelProps({ id: 'a' })}></div>
<div {...api.getResizeTriggerProps({ id: 'a:b' })}></div>
<div {...api.getPanelProps({ id: 'b' })}></div> </div> </>)}
<script lang="ts"> import * as splitter from "@destyler/splitter" import { normalizeProps, useMachine } from "@destyler/svelte"
const [state, send] = useMachine( splitter.machine({ id: crypto.randomUUID(), }) )
const api = $derived(splitter.connect(state, send, normalizeProps))</script>
<div {...api.getRootProps()}> <div {...api.getPanelProps({ id: 'a' })}></div>
<div {...api.getResizeTriggerProps({ id: 'a:b' })}></div>
<div {...api.getPanelProps({ id: 'b' })}></div></div>
import { normalizeProps, useMachine } from '@destyler/solid'import * as splitter from '@destyler/splitter'import { createMemo, createUniqueId } from 'solid-js'
export default function SplitterDemo() {
const [state, send] = useMachine( splitter.machine({ id: createUniqueId(), }) )
const api = createMemo(() => splitter.connect(state, send, normalizeProps))
return ( <> <div {...api().getRootProps()}> <div {...api().getPanelProps({ id: 'a' })}></div>
<div {...api().getResizeTriggerProps({ id: 'a:b' })}></div>
<div {...api().getPanelProps({ id: 'b' })}></div> </div> </> )}
Listening for events
When the resize trigger of splitter changes,
the onSizeChangeStart
and onSizeChangeEnd
callback is invoked.
const [state, send] = useMachine( splitter.machine({ onSizeChangeStart(detail) { console.log("change start", detail) }, onSizeChangeEnd(detail) { console.log("change end", detail) }, }),)
Changing the orientation
By default, the splitter is assumed to be horizontal.
To change the orientation to vertical,
set the orientation
property in the machine’s context to vertical
.
const [state, send] = useMachine( splitter.machine({ orientation: 'vertical', }),)
Styling guide
Earlier, we mentioned that each splitter part has a
data-part
attribute added to them to select and style them in the DOM.
Resize trigger
When an splitter item is horizontal or vertical,
a data-state
attribute is set on the item and content elements.
[data-scope="splitter"][data-part="resize-trigger"] { /* styles for the item */}
[data-scope="splitter"][data-part="resize-trigger"][data-orientation="horizontal"] { /* styles for the item is horizontal state */}
[data-scope="splitter"][data-part="resize-trigger"][data-orientation="vertical"] { /* styles for the item is horizontal state */}
[data-scope="splitter"][data-part="resize-trigger"][data-focus] { /* styles for the item is focus state */}
[data-scope="splitter"][data-part="resize-trigger"]:active { /* styles for the item is active state */}
[data-scope="splitter"][data-part="resize-trigger"][data-disabled] { /* styles for the item is disabled state */}
Methods and Properties
Machine Context
The splitter machine exposes the following context properties:
Partial<{ root: string; resizeTrigger: (id: string) => string; label: (id: string) => string; panel: (id: string | number) => string; }>
"horizontal" | "vertical"
PanelSizeData[]
(details: SizeChangeDetails) => void
(details: SizeChangeDetails) => void
() => ShadowRoot | Node | Document
Machine API
The splitter api
exposes the following methods:
boolean
boolean
PanelBounds | undefined
(id: PanelId) => void
(id: PanelId) => void
(id: PanelId, size: number) => void
Data Attributes
Root
data-scope
data-part
data-orientation
Panel
data-scope
data-part
data-orientation
Resize Trigger
data-scope
data-part
data-orientation