split-surface

Resizable panel splitter with two layers of progressive enhancement: attribute init and full web component.

Overview

The splitter provides resizable panel support as a two-layer progressive enhancement story — from attribute init to full web component — matching a "platform-first, enhance upward" philosophy.

Layer 1: Attribute Init

Light JS (~80 lines). Apply data-splitter to a container. A small init script injects a full-height drag divider between the first two children with pointer and keyboard events.

Main content area

Vertical Splitting

Constraints

Set data-min and data-max on children to constrain how far the divider can move.

Keyboard

KeyAction
ArrowLeft / ArrowRightMove divider 1%
Shift + ArrowMove divider 10%
HomeMove to minimum
EndMove to maximum

Layer 2: Web Component

Full component. Self-contained <split-surface> element with persistence, collapsible panels, custom events, and JS API.

Main content panel

All Attributes

AttributeValuesDefaultDescription
direction"horizontal", "vertical"horizontalSplit axis
positionnumber50Split position as percentage (0–100)
minnumber10Minimum panel size percentage
maxnumber90Maximum panel size percentage
persiststringlocalStorage key for position persistence
collapsiblebooleanDouble-click divider to collapse first panel

Required Structure

ElementRequiredDescription
first childyesFirst panel content
second childyesSecond panel content — divider is auto-created between them

Events

EventDetailDescription
split-surface:resize{ position }Fired when panel is resized
split-surface:collapse{ collapsed }Fired when panel is collapsed or expanded

JavaScript API

Property / MethodTypeDescription
element.positionnumberGet/set current position (0-100)
element.collapsedbooleanGet/set collapsed state
element.reset()methodRestore to initial position, clear persistence

Progressive Enhancement

Without JavaScript, <split-surface> renders as a simple two-column flex layout. The :not(:defined) selector provides the fallback. Once JS registers the component, the divider appears.

Which Layer to Choose

LayerJSKeyboardARIAPersistenceBest for
data-splitter~80 linesYesYesNoEnhanced layout containers with accessibility
<split-surface>~120 linesYesYesYesFull-featured standalone component

Related