Components / structure

Splitter

Not a Separator. If the line cannot be dragged, it has no keyboard contract and no role beyond separator, and this component's machinery is all cost.

Rendered from the package · open on its own

Summary

A draggable divider between two panes — a canvas and its inspector.

APG patternWindow Splitter
Built onnative elements
Statusstable
Since0.1.0
<Splitter id="editor" label="Resize inspector" defaultSize={70} min={30} max={85}
  primary={<Canvas />} secondary={<Inspector />} />

Anatomy

Two panes with a separator between them. The separator is focusable and carries the aria-value* set.

PartElementRequired
pane<div>yes
separator<div>yes

Properties

PropertyValuesDefaultWhat it does
orientationhorizontal · verticalhorizontalWhich way the panes are arranged, and therefore which arrow keys move the divider.
defaultSizenumber30Primary pane size as a percentage.
minnumber10The smallest the primary pane may become, as a percentage. Below this the divider clamps rather than collapsing, so a pane never disappears by accident.
maxnumber90The largest the primary pane may become, as a percentage.
stepnumber2Percentage points moved per arrow key press.
labelstringrequiredRequired — names the separator for a keyboard user.
labelledBystringnoneId of the primary pane's visible heading. Wins over label.
primaryReact.ReactNoderequiredThe pane the size refers to and the label names.
secondaryReact.ReactNoderequiredThe other pane. It takes whatever is left.
idstringnoneOptional. A stable id is generated when omitted; aria-controls is always wired.

States

StateExpressed as
Focused:focus-visible
Hover:hover

Behavior

The separator takes focus and moves with arrow keys. A divider you can only drag is unusable without a pointer, which is the failure this pattern exists to prevent. Home and End collapse and expand; Enter restores the previous size from collapsed.

Accessibility

The separator is named, and the name says what moving it does — Resize inspector, not Divider.

Its hit area is widened under a coarse pointer by a pseudo-element rather than by making the line thicker, so the target grows and the appearance does not.

It has no upstream test suite. Window Splitter is one of four patterns the W3C ships no regression tests for.

Keyboard

KeyResult
Arrow keysMove the divider by one step
Home / EndCollapse and expand
EnterRestores the previous size from collapsed

Roles, states and properties

AttributeSet by
aria-controlsset at render
aria-labelset at render
aria-labelledbyset at render
aria-orientationset at render
aria-valuemaxset at render
aria-valueminset at render
aria-valuenowset at render
rolealways separator

Focus

The separator itself takes focus, which is the failure this pattern exists to prevent — a divider you can only drag is unusable without a pointer.

Screen reader

Not recorded as verified. Stage 4 of the readiness ladder — driving each component with VoiceOver and NVDA — is unstarted across the package, and no component should claim otherwise until docs/journal/ records the session that did it.

Contrast and target size

npm run check:contrast audits every color pair this component uses across all four skins, light and dark, and fails the build on a shortfall. Two waivers are on the record in docs/audit/DEFERRED.md.

It takes the touch floor under (pointer: coarse) — the visual size is unchanged on a desktop pointer.

Tested

  • test/apg/partials-sweep.test.jsx

Known gaps

_No upstream requirement is recorded as not applicable._

Appearance

TokenUsed for
--se-accentbackground
--se-borderbackground
--se-duration-instanttransition
--se-ease-standardtransition
--se-focus-coloroutline
--se-focus-offsetoutline-offset
--se-focus-widthoutline
--se-space-1block-size, inline-size
--se-space-2inset-block, inset-inline
--se-target-mininset-inline

Motion

None while dragging — the pane tracks the pointer. Collapse and expand are instant, because they are a jump rather than a movement.

Content

The label names the pane that moves. If both move, name the one the reader thinks of as adjustable.

Usage

When not to use it. For a layout that could be intrinsic. data-se-layout="sidebar" gives a panel a floor and lets main take the rest with no control at all, and a splitter a reader never touches is a control that costs a tab stop for nothing.

Notes

Not a Separator. If the line cannot be dragged, it has no keyboard contract and no role beyond separator, and this component's machinery is all cost.