Window Splitter
Window splitters divide a container into two resizable panes for code editor layouts, preview panels, or master-detail views.
Try it
Usage
Pass primary and secondary pane content. Set value to the primary pane percentage and orientation for horizontal or vertical splits.
import { RuiWindowSplitter } from '@ecopages/radiant-ui/window-splitter';
<RuiWindowSplitter
value={50}
orientation="horizontal"
label="Split view"
primary={<div>Editor</div>}
secondary={<div>Preview</div>}
/>Custom markup
<rui-window-splitter> coordinates any light-DOM tree that matches its query contract. The
RuiWindowSplitter helper stamps these targets; it is not required.
import '@ecopages/radiant-ui/window-splitter';
<rui-window-splitter value={50} orientation="horizontal" label="Split view">
<div data-ref="root" class="rui-window-splitter rui-window-splitter--horizontal">
<div data-ref="primary" class="rui-window-splitter__pane">Editor</div>
<div data-ref="separator" class="rui-window-splitter__separator" role="separator" tabindex={0}></div>
<div data-ref="secondary" class="rui-window-splitter__pane">Preview</div>
</div>
</rui-window-splitter>;Do not set primary pane width / height or separator aria-valuenow — the host owns those.
Initial pane ratio
value sets the primary pane percentage, clamped between 20 and 80. Users can drag the splitter to adjust.
Orientation
Use horizontal for side-by-side panes and vertical for stacked editor/console layouts.
Theming
Window Splitter maps to semantic border, surface, and focus roles, never Tailwind palette steps:
| Part | CSS roles |
|---|---|
Frame (rui-window-splitter) | border, radius-container |
| Panes | background, on-background, --space-inset |
| Separator | border |
| Separator focus | focus-ring |
Override at the theme layer, not in component CSS.
API
RuiWindowSplitter is a custom element (<rui-window-splitter>) that owns the separator and pane sizing; the RuiWindowSplitter JSX view projects the two panes.
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
value | number | 50 | Primary pane size as a percentage (clamped 20–80). |
orientation | horizontal · vertical | horizontal | Split axis. |
label | string | Split view | Accessible name for the separator. |
Light-DOM contract
| Target | Required | Host writes | Author owns |
|---|---|---|---|
[data-ref="root"] | yes | orientation modifier classes | layout wrapper |
[data-ref="primary"] | yes | inline width or height from value | pane content |
[data-ref="separator"] | yes | aria-orientation, aria-valuenow, aria-valuemin, aria-valuemax, aria-label | view seeds role="separator", tabIndex |
[data-ref="secondary"] | yes | — | second pane content |
Nested hosts: none.
Events
| Event | Detail | Description |
|---|---|---|
rui-splitter-change | { value: number } | Emitted when the separator moves. |
View helpers
| Component | Target stamped | Notes |
|---|---|---|
RuiWindowSplitter | [data-ref="root"], [data-ref="primary"], [data-ref="separator"], [data-ref="secondary"] | primary and secondary props supply pane content. |
Props
| Prop | Type | Default | Description |
|---|---|---|---|
primary | JsxRenderable | First pane content for the RuiWindowSplitter view. | |
secondary | JsxRenderable | Second pane content. |
CSS classes
Public BEM classes on the composed surface (documented via @cssclass on RuiWindowSplitterElement):
| Class | Description |
|---|---|
.rui-window-splitter | Root surface. |
.rui-window-splitter--horizontal | Side-by-side panes. |
.rui-window-splitter--vertical | Stacked panes. |
.rui-window-splitter__pane | A pane region. |
.rui-window-splitter__separator | Focusable separator (role="separator"). |
Theme roles
| Part | CSS variables consumed |
|---|---|
| Frame | --border, --radius-container |
| Panes | --background, --on-background, --space-inset |
| Separator | --border |
| Separator focus | --focus-ring |
Accessibility
- The splitter handle is keyboard focusable and adjustable with arrow keys.
- Provide
labelso screen readers identify the split region. - Ensure both panes remain usable at minimum sizes; avoid content that breaks at narrow widths.