TkxSplitter
Resizable split panes — the layout primitive that hosts editor/studio
components like TkxFlowChart, TkxSpreadsheet, or TkxPlayground in
dashboards and IDE-style UIs. Compose TkxSplitterPane children inside a
TkxSplitter; every adjacent pair of panes gets a draggable, keyboard-operable
gutter between them.
import { TkxSplitter, TkxSplitterPane } from 'tekivex-ui';
<div style={{ height: 400 }}> <TkxSplitter direction="horizontal" onResizeEnd={(sizes) => console.log(sizes)}> <TkxSplitterPane defaultSize={30} minSize={15}> sidebar </TkxSplitterPane> <TkxSplitterPane>editor</TkxSplitterPane> </TkxSplitter></div>Dragging a gutter resizes only its two adjacent panes (classic splitter behaviour) — with three panes you get two gutters, and each moves just one boundary. Touch works out of the box via Pointer Events. Double-click a gutter to reset its two panes to their initial sizes.
Vertical splits
Section titled “Vertical splits”direction="vertical" stacks panes top-to-bottom:
<TkxSplitter direction="vertical"> <TkxSplitterPane defaultSize={70}>canvas</TkxSplitterPane> <TkxSplitterPane minSize={15}>console</TkxSplitterPane></TkxSplitter>Controlled vs uncontrolled
Section titled “Controlled vs uncontrolled”Uncontrolled by default: pane defaultSize props seed the internal state
(normalized to sum 100; unspecified panes share the remainder equally).
Pass sizes (percentages, one per pane) for full control — the component then
never mutates itself; it only reports proposed sizes through onResize /
onResizeEnd, and the DOM follows your prop:
const [sizes, setSizes] = useState([30, 70]);
<TkxSplitter sizes={sizes} onResize={setSizes}> <TkxSplitterPane>left</TkxSplitterPane> <TkxSplitterPane>right</TkxSplitterPane></TkxSplitter>onResize fires continuously during a drag (and on every keyboard step);
onResizeEnd fires once on pointer release — useful for persisting layout to
storage without write-spam.
Keyboard model
Section titled “Keyboard model”Each gutter follows the WAI-ARIA window-splitter pattern: it is focusable
(tabIndex=0), exposed as role="separator" with aria-orientation
(a vertical separator for a horizontal split, and vice versa), and
aria-valuenow/aria-valuemin/aria-valuemax reflect the preceding pane’s
percentage.
| Key | Action (horizontal split) | Action (vertical split) |
|---|---|---|
ArrowLeft / ArrowRight | Move divider 2% left / right | — |
ArrowUp / ArrowDown | — | Move divider 2% up / down |
Home | Snap preceding pane to its minSize | same |
End | Snap preceding pane to its max | same |
TkxSplitter props
Section titled “TkxSplitter props”| Prop | Type | Default | Description |
|---|---|---|---|
direction | 'horizontal' | 'vertical' | 'horizontal' | horizontal = panes side-by-side, vertical = stacked. |
sizes | number[] | — | Controlled sizes in percent, one per pane. Omit for uncontrolled mode. |
onResize | (sizes: number[]) => void | — | Fired continuously during drag and on keyboard resize. |
onResizeEnd | (sizes: number[]) => void | — | Fired on pointer release / after a keyboard step. |
gutterSize | number | 6 | Gutter thickness in px. |
disabled | boolean | false | Blocks drag and keyboard resizing. |
className / style | — | — | Applied to the root flex container. |
children | ReactNode | — | 2+ TkxSplitterPane for splitting; other children render as-is. |
The component forwards its ref to the root <div>.
TkxSplitterPane props
Section titled “TkxSplitterPane props”| Prop | Type | Default | Description |
|---|---|---|---|
defaultSize | number | — | Initial size in percent. Unspecified panes share the remainder equally. |
minSize | number | 10 | Minimum size in percent; drag/keyboard clamp here. |
maxSize | number | — | Maximum size in percent. |
className / style | — | — | Applied to the pane <div> (which has overflow: auto). |
children | ReactNode | — | Pane content; scrolls within the pane. |
Gotchas
Section titled “Gotchas”- Percentages normalize.
defaultSizevalues that don’t sum to 100 are scaled proportionally, and panes without adefaultSizesplit whatever is left over equally — you never end up with a broken layout. - Controlled means controlled. With
sizesset, the splitter never moves on its own: update your state fromonResizeor the panes stay put. - Pane content scrolls. Panes are
overflow: auto, so oversized content scrolls inside its pane instead of blowing up the layout. - Gutters are theme-driven. The gutter uses
theme.borderat rest andtheme.primaryon hover/drag/focus — no hardcoded colours.