Skip to content

Splitter

  • Layer: Component
  • Base: @ark-ui/solid Splitter
  • Shipped for: Document review’s two-panel layout (doc + Saltie chat)

Splits a container into resizable panels. Sizes are percentages that must sum to 100. The resize trigger is an 8px hit area with a 1px seam that glows cyan on hover, drag, and keyboard focus. Use onSizeChangeEnd to persist the user’s preference.

A — TWO PANELS, DOC + RAIL

LEFT · 60%
RIGHT · 40%

B — ORIENTATION=VERTICAL

TOP
BOTTOM

The handle updates in-memory state via onSizeChangeEnd. In production, write the returned size to localStorage and rehydrate on mount.

C — PERSISTED VIA onSizeChangeEnd

65%
35%
import { Splitter } from "@risingswamp/design-system";
import type { SplitterSizeChangeDetails } from "@ark-ui/solid/splitter";
<Splitter.Root
size={[
{ id: "doc", size: 66, minSize: 45, maxSize: 75 },
{ id: "chat", size: 34, minSize: 25, maxSize: 55 },
]}
onSizeChangeEnd={(details: SplitterSizeChangeDetails) => {
const doc = details.size.find((s) => s.id === "doc");
if (doc?.size != null) persist(doc.size);
}}
>
<Splitter.Panel id="doc">{/* document body */}</Splitter.Panel>
<Splitter.ResizeTrigger id="doc:chat" aria-label="Resize panels" />
<Splitter.Panel id="chat">{/* chat rail */}</Splitter.Panel>
</Splitter.Root>;
PartRole
Splitter.RootFlex container; owns orientation and panel sizes
Splitter.PanelA resizable region; identified by id
Splitter.ResizeTriggerHandle between two panels; id is "<panelA>:<panelB>"
PropTypeDefault
orientation"horizontal" | "vertical""horizontal"
size{ id, size, minSize?, maxSize? }[]
defaultSizesame shape (uncontrolled)
onSizeChange(details: SplitterSizeChangeDetails)
onSizeChangeEnd(details: SplitterSizeChangeDetails)
PropTypeNotes
idstring | numberRequired
snapSizenumberSnap to this size near panel edges
PropTypeNotes
id`${PanelId}:${PanelId}`Identifies which two panels it resizes
disabledbooleanDim and block interaction
stepnumberKeyboard step (percent)
aria-labelstringDefaults to “Resize panels”
KeyAction
ArrowLeft / ArrowRightResize by 1% (horizontal)
ArrowUp / ArrowDownResize by 1% (vertical)
HomeJump to min size
EndJump to max size
EnterToggle between last two sizes
TokenUsage
--colors-borderSeam colour at rest
--colors-accentSeam colour on hover / drag / focus
--glow-primarySeam glow on hover / drag
--shadows-focusFocus-visible ring
--durations-fastState transitions
  • Splitter.ResizeTrigger renders as role="separator" via Ark UI with aria-valuemin, aria-valuemax, aria-valuenow reflecting the resolved size.
  • Keyboard-reachable (Tab focusable) and announced with aria-label.
  • Focus ring uses the system-wide cyan offset-glow; never a solid outline.