rc-splitter
Resizable pane splitter with pointer, keyboard, and collapse/restore controls, following the WAI-ARIA Window Splitter pattern.
- Package
@rcarls/rc-splitter- Element
<rc-splitter>- Native dependency
- Pane content slots
- State model
- Controlled or uncontrolled pane size
- Main events
rc-splitter-change- Related
- Theme previews
Installation
- npm
- Yarn
npm install @rcarls/rc-splitter
yarn add @rcarls/rc-splitter
import '@rcarls/rc-splitter/define';
Live demo
Theming
The default demo mode shows the component without a package theme. Use the shared preview controls on this page to compare inherited, light, and dark color schemes or to apply the optional Material theme only inside the demo frames.
Collapsible panes
Set the collapsible attribute to render a toggle button on the separator that collapses or expands the primary pane:
<rc-splitter collapsible>
<div>Primary</div>
<div slot="secondary">Secondary</div>
</rc-splitter>
The button is also keyboard-accessible: while the separator handle has focus, Ctrl+Arrow (left/right for horizontal, up/down for vertical) toggles collapse. The Enter key on the handle itself also toggles collapse independently of the collapsible attribute.
Style the button via ::part(collapse-button). Its position and size are configurable through --rc-splitter-collapse-button-size (default 20px), --rc-splitter-collapse-button-offset, and the button color/background tokens.
Touch targets
A 24 px diameter transparent circle is always present on the drag handle as a ::after pseudo-element. It is non-interactive for mouse and keyboard. On touch devices (any-pointer: coarse) it becomes hittable, providing a WCAG 2.5.8-compliant touch target without widening the visual separator. The visual indicator and touch target are intentionally decoupled.
The #separator uses z-index: 1 so the touch target circle stacks above pane content when it extends past the separator strip edge, ensuring touch events are captured correctly.
Visual indicator
The default drag indicator is a 3-dot grip, rendered as a ::before pseudo-element inside the handle so the touch target (the handle element itself) and the visual remain independent. Hover highlights are scoped to the visual indicator only — they do not highlight the full separator strip.
Customise the indicator via CSS custom properties:
rc-splitter {
/* Switch from dots to a solid line or pill */
--rc-splitter-handle-pattern: none;
--rc-splitter-handle-fill: ButtonBorder;
--rc-splitter-handle-border-radius: 999px; /* pill shape */
--rc-splitter-handle-hover-fill: Highlight; /* hover state on indicator only */
--rc-splitter-handle-transition: 150ms ease;
}
Material 3 theme
When rc-theme-material is applied, the splitter uses an M3-style drag indicator modelled after the M3 bottom sheet drag handle:
- Strip width: 24 px (
1.5rem) — meets WCAG 2.5.8 in the cross axis (combined with the 24 px touch target circle on touch devices) - Indicator: 4 px × 32 px fully-rounded pill (
--rc-splitter-handle-pattern: none,--rc-splitter-handle-fill,--rc-splitter-handle-border-radius: 999px) - Color:
on-surface-variantat 40 % opacity - Hover:
primaryat 8 % opacity — on the pill only, not the strip - Transition: 150 ms with M3 standard easing
All tokens are CSS custom properties so individual values can be overridden without replacing the whole theme layer.
API
Properties
| Property | Markup | Type | Default | Description |
|---|---|---|---|---|
label | label | string | "Splitter" | Accessible label for this splitter. Default label is 'Splitter'. |
orientation | orientation | SplitterOrientation | "horizontal" | Splitter orientation, for keyboard navigation and initial sizing. |
mode | mode | SplitterMode | "length" | Determines length units for min, max and step attributes, one of either `length` (default) or `percent` |
step | step | number | 1 | The step size for resizing, in either pixels or percentage points depending on `mode`. |
min | min | number | 0 | Minimum size of the primary pane in current mode units. Defaults to 0. |
max | max | number | undefined | undefined | Maximum size of the primary pane in current mode units. Defaults to the full container size. |
value | value | Unknown | Not specified | The current splitter value, corresponding to the separator position, in either pixels or percentage points depending on `mode`. |
defaultValue | default-value | Unknown | Not specified | Initial uncontrolled splitter value. |
fixed | fixed | boolean | false | Toggles resizing ability |
collapsible | collapsible | boolean | false | Renders a collapse/expand toggle button on the separator. |
valueText | JS property only | Unknown | Not specified | A human-readable string representation of the value. |
Methods
No public methods are documented in the custom elements manifest.
Events
| Event | Detail type | Description |
|---|---|---|
rc-splitter-change | CustomEvent | No description provided. |
Slots
| Name | Description |
|---|---|
(default) | Primary pane contents |
secondary | Secondary pane contents (optional) |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--rc-splitter-separator-size | 6px | Thickness of the separator bar |
--rc-splitter-separator-handle-size | 100% | Length of the drag handle area within the separator (also the length of the visible indicator) |
--rc-splitter-separator-color | color-mix(in srgb, ButtonBorder 35%, Canvas 65%) | Separator background color |
--rc-splitter-keyline | 1px solid ButtonBorder | Shared separator keyline border |
--rc-splitter-handle-color | ButtonBorder | Color of the dot grip indicators (default visual) |
--rc-splitter-handle-thickness | 4px | Cross-axis size of the visual indicator (dot column width or pill/line thickness) |
--rc-splitter-handle-border-radius | 0 | Border-radius of the visual indicator; set to a large value (e.g. 999px) for a pill shape |
--rc-splitter-handle-pattern | <3-dot radial-gradient> | background-image for the visual indicator; set to `none` to use a solid fill via --rc-splitter-handle-fill instead |
--rc-splitter-handle-fill | transparent | background-color of the visual indicator; effective when --rc-splitter-handle-pattern is none (e.g. for a solid pill) |
--rc-splitter-handle-hover-fill | transparent | background-color of the visual indicator on hover; scoped to the indicator element only, not the full separator strip |
--rc-splitter-handle-transition | 0ms | CSS transition duration/easing for the visual indicator's background-color changes |
--rc-splitter-collapse-button-size | 20px | Diameter of the collapse/expand toggle button |
--rc-splitter-collapse-button-offset | 8px | Distance from the start edge of the separator to the collapse button center |
--rc-splitter-collapse-button-bg | Canvas | Collapse button background color |
--rc-splitter-collapse-button-hover-bg | ButtonFace | Collapse button background color on hover |
--rc-splitter-collapse-button-border | ButtonBorder | Collapse button border color |
--rc-splitter-collapse-button-color | ButtonText | Collapse button icon color |
--rc-splitter-separator-border-inline-start | 1px solid ButtonBorder | Inline-start border |
--rc-splitter-separator-border-inline-end | 1px solid ButtonBorder | Inline-end border |
--rc-splitter-separator-border-block-start | 1px solid ButtonBorder | Block-start border (vertical orientation) |
--rc-splitter-separator-border-block-end | 1px solid ButtonBorder | Block-end border (vertical orientation) |
CSS Parts
| Part | Description |
|---|---|
primary | Primary pane container |
secondary | Secondary pane container |
separator | The separator bar |
separator-handle | The focusable drag handle |
collapse-button | The collapse/expand toggle button (only rendered when `collapsible` is set) |