Skip to content

Split

Two panes and a seam you can drag — the chat beside a preview, an editor or a document.

  • <aparte-split>
  • .aparte-split
On this page
Open

When the chat builds something, the result needs room beside it. <aparte-split> puts two panes side by side with a seam between them: drag it, or focus it and use the arrow keys. A pane holds a chat; a chat never holds a split.

The size is CSS: --aparte-split-position is the first pane’s size, and --aparte-split-min and --aparte-split-max bound it in any unit, so the browser does the clamping. Without the element, the .aparte-split classes give the same two panes with no drag.

Open

orientation="vertical" puts the panes one above the other. primary="end" makes the second pane the one position sizes.

html
<aparte-split collapsed=""></aparte-split>
js
el.addEventListener('aparte-split-resize', (e) => use(e.detail));

Installation and the framework-specific traps: React · Vue · Svelte · Angular.

The split stores nothing: position goes in, and aparte-split-resize comes out once the reader lets go. Save the value from the event, and restore it by setting position.

On a narrow window (under breakpoint, 48rem by default, or none), the split shows one pane at a time; buttons carrying data-aparte-split-pane="start" or "end" switch between them, with no script. single shows one pane at any width, and collapsed folds the first pane to its minimum.

VariableWhat it sets
--aparte-split-positionThe first pane’s size (38%).
--aparte-split-min, --aparte-split-maxIts bounds, in any unit.
--aparte-split-handle-sizeThe seam’s width.

<aparte-split> · class AparteSplit

Attributes

AttributeDescription
positionThe primary pane’s size, as a percentage of the container. Reflected on commit, never per drag frame.
orientationhorizontal (panes side by side, the default) or vertical (stacked). Names the CONTAINER’s axis.
primarystart (default) or end: which pane position sizes.
collapsedThe primary pane folded to its minimum. Enter on the seam toggles it; a second Enter restores the size it had.
breakpointBelow this width the split shows one pane at a time. A length (default 48rem), or none to never stack.
panestart (default) or end: which pane is shown while stacked.
disabledNo drag, no keys, no tab stop; the seam stays drawn.
labelThe seam’s accessible name. Defaults to the locale’s splitHandleLabel.
singleShow one pane — the one pane names — whatever the width: the seam and the other pane are gone, as under the breakpoint. For a host that decides itself when a second pane exists (a preview with nothing to preview yet). collapsed is not this: it folds the primary pane to --aparte-split-min and keeps the seam. The CSS route, .aparte-split--only-start / --only-end, is the same state for a host that owns its breakpoints.
data-stackedWritten BY the element while one pane is shown. Read-only; style against it.

Properties

PropertyTypeDescription
positionnumberThe primary pane’s size, as a percentage of the container. Setting it commits.
orientation'horizontal' | 'vertical'The container’s axis: horizontal (side by side) or vertical (stacked).
primary'start' | 'end'Which pane position sizes.
collapsedbooleanThe primary pane is folded to its minimum.
pane'start' | 'end'Which pane is shown while the split is stacked.
disabledbooleanNo drag, no keys, no tab stop. The seam stays drawn.
stacked (readonly)booleanTrue while the split is showing one pane. Read-only. Both routes into that state count. data-stacked is the one this element writes from its own breakpoint; .aparte-split--only-start / --only-end are the CSS route a host takes when it owns its breakpoints and sets breakpoint="none". The sheet gives the two byte-identical rules, so the element has to read them the same way — every guard downstream keys on this getter, and a split stacked by the class alone would measure a one-track grid and commit position="100".
singlebooleanOne pane on demand, whatever the width (#54). Reflected.

Methods

MethodDescription
collapse(): voidFold the primary pane to its minimum, remembering the size it had.
expand(): voidUnfold it, back to the size it had before it collapsed.
toggleCollapse(): void
showPane(which: 'start' | 'end'): voidShow one pane, which only has a visible effect while the split is stacked.
reset(): voidBack to the position the split was FIRST connected with — a re-parent restores that, it does not redefine it. What a double-click on the seam does.

Events

EventTypeDescription
aparte-split-resizeCustomEvent<AparteSplitResizeDetail>The position settled: after a drag, a key, a double-click or a property set. Never during a drag — persist from here.

CSS variables

VariableDefaultDescription
--aparte-split-position38%The primary pane’s size.
--aparte-split-minmin(20rem, 100%)Floor of the primary pane. Any length or percentage.
--aparte-split-max60%Ceiling of the primary pane.
--aparte-split-handle-size12pxThe seam’s track: the grab zone, and what the grid reserves between the panes. The painted line inside it is --aparte-split-seam-width.
--aparte-split-hit-area12pxThe invisible grab zone around it. Grows to the touch target on a coarse pointer.

.aparte-split · .aparte-split--only-end · .aparte-split--only-start · .aparte-split--primary-end · .aparte-split--vertical · .aparte-split__handle · .aparte-split__pane · .aparte-split__scrim

  • The seam is a separator with its current value, named from the splitHandleLabel key (or label). It follows the window splitter pattern: arrow keys move it, Shift moves it by 10%, Home and End go to the bounds, Enter folds the first pane.
  • Its grab zone grows to a touch-sized target on a coarse pointer.
  • App shell — the main area a split fills.
  • Artifact — a document that belongs in the second pane.
  • Layout guide — the builder layout, step by step.