Splitter
hc-splitter splits two panes with a movable handle — the shadcn
Resizable equivalent. It follows the WAI-ARIA Window Splitter
pattern: the handle is a focusable role="separator" whose
aria-valuenow tracks the primary pane’s size. installSplitter wires
the pointer drag, keyboard resize, and ARIA; the layout is plain
flexbox driven by a single --hc-splitter-pos custom property.
Basic usage
Section titled “Basic usage”Give the container a cross-axis size (a height for the default horizontal layout).
<div class="hc-splitter" data-orientation="horizontal" style="block-size:10rem"> <div class="hc-splitter__panel">Primary pane</div> <div class="hc-splitter__handle" role="separator" tabindex="0" aria-label="Resize panels"></div> <div class="hc-splitter__panel">Secondary pane</div></div>import { installSplitter } from '@hypermedia-components/core';installSplitter(); // idempotent; returns an uninstallerThe zero-config @hypermedia-components/core/behaviors entry installs
it automatically.
Vertical
Section titled “Vertical”data-orientation="vertical" stacks the panes with a horizontal handle.
Configuration
Section titled “Configuration”| Attribute | Purpose |
|---|---|
data-orientation | horizontal (default, side-by-side) or vertical (stacked). |
data-value | Initial primary-pane size, percent (default 50). |
data-min / data-max | Allowed range, percent (default 10 / 90). |
data-step | Keyboard step, percent (default 5). |
data-collapsible | Double-click / Enter on the handle toggles the primary pane collapsed ↔ last-open. |
data-persist | localStorage key — saves and restores the position (a persisted 0 restores collapsed). |
Keyboard
Section titled “Keyboard”Tab to the handle, then:
| Key | Action |
|---|---|
← / → (horizontal) or ↑ / ↓ (vertical) | Resize by one step |
Home | Minimum size |
End | Maximum size |
Enter | Toggle collapse (when data-collapsible) |
DOM focus is on the handle; aria-valuenow / aria-valuemin /
aria-valuemax describe the primary pane’s size to assistive tech.
The change event
Section titled “The change event”Each resize dispatches a bubbling hc:splitterchange on the container:
splitter.addEventListener('hc:splitterchange', (e) => { const { value, collapsed, orientation } = e.detail; // value: primary-pane %});collapsed is true while the primary pane is folded away (see below).
Collapse
Section titled “Collapse”Add data-collapsible so the handle can fold the primary pane away and
bring it back. Double-click the handle, or focus it and press
Enter, to toggle between collapsed (0%) and the last open size.
<div class="hc-splitter" data-orientation="horizontal" data-collapsible style="block-size:10rem"> <div class="hc-splitter__panel">Primary pane</div> <div class="hc-splitter__handle" role="separator" tabindex="0" aria-label="Resize panels"></div> <div class="hc-splitter__panel">Secondary pane</div></div>A collapsed splitter carries data-collapsed on the container — style the
panes off it — and hc:splitterchange reports detail.collapsed. The
handle’s aria-valuenow stays within [min, max]; the collapsed state
rides on data-collapsed rather than an out-of-range value.
Persistence
Section titled “Persistence”Add data-persist="<key>" to mirror the position into localStorage and
restore it on the next visit. A persisted 0 restores the collapsed state.
Storage failures (private mode, disabled) degrade silently to the
data-value default.
<div class="hc-splitter" data-orientation="horizontal" data-collapsible data-persist="editor:sidebar" style="block-size:10rem"> …</div>Hyperscript
Section titled “Hyperscript”data-persist covers the common localStorage case; reach for Hyperscript
when you need custom storage (a cookie, a server round-trip, a different
key shape):
<div class="hc-splitter" data-orientation="horizontal" _="on hc:splitterchange call myStore.set('split', event.detail.value)"> …</div>More patterns: Hyperscript → Reacting to component events.
Accessibility
Section titled “Accessibility”- The handle is
role="separator"+tabindex="0"witharia-valuenow/aria-valuemin/aria-valuemaxandaria-controlspointing at the primary pane (per the APG Window Splitter pattern). - The separator’s
aria-orientationis set automatically (a side-by-side split uses averticalseparator line, and vice-versa). - Give the handle an accessible name with
aria-labeloraria-labelledby(the primary pane’s heading).
Theming tokens
Section titled “Theming tokens”| Token path | Purpose |
|---|---|
splitter.handle-size | Handle thickness (the hit area). |
splitter.handle-bg / handle-hover-bg | Handle background (hover / focus tints with data-color). |
splitter.grip-color / grip-active-color | The centred grip bar. |
splitter.grip-length / grip-thickness | Grip dimensions. |
CSS variables
Section titled “CSS variables”Show the generated CSS variables
--hc-splitter-handle-size | -handle-bg | -handle-hover-bg--hc-splitter-grip-color | -grip-active-color | -grip-length | -grip-thickness--hc-splitter-pos (runtime: the primary pane's size, set by installSplitter)Out of scope
Section titled “Out of scope”Three-or-more panes, nested splitters, and pixel-based minimums are deferred.