The m3e-split-pane component delivers a Material 3-inspired split view with a movable drag handle,
enabling responsive layout composition and precise pane resizing. It supports keyboard interaction, adaptive
orientation, and optional detent snapping for consistent, accessible content distribution.
import "@m3e/web/split-pane";
This section outlines usage examples and configuration guidance for the components in this package.
The m3e-split-pane exposes two slots: start, which renders content on the logical
start side of the layout, and end, which renders content on the logical end side. The
value attribute controls the percentage of the available space occupied by the start pane, with the
end pane automatically filling the remainder. By default, value is 50%. When a user interaction
causes value to change, a cancellable input event is emitted, followed by a
change event. This allows you to react to live resizing as well as commit final adjustments when
the user finishes interacting with the drag handle.
<m3e-split-pane value="50"> <m3e-card slot="start"></m3e-card> <m3e-card slot="end"></m3e-card> </m3e-split-pane>
The m3e-split-pane supports three orientations: horizontal (default),
vertical, and auto. Using auto, the orientation is responsive and
determined by viewport size. Use the orientation attribute to change the orientation.
<m3e-split-pane value="50" orientation="vertical"> <m3e-card slot="start"></m3e-card> <m3e-card slot="end"></m3e-card> </m3e-split-pane>
Use the min and max attributes to control the minimum and maximum percentage the start
pane can occupy.
<m3e-split-pane value="50" min="25" max="75"> <m3e-card slot="start"></m3e-card> <m3e-card slot="end"></m3e-card> </m3e-split-pane>
Use the step attribute to control how much the split pane's value changes with each
keyboard resize action, such as pressing the arrow keys.
<m3e-split-pane value="50" step="10"> <m3e-card slot="start"></m3e-card> <m3e-card slot="end"></m3e-card> </m3e-split-pane>
Use the detents attribute to define the positions a split pane can snap to during resizing. A split
pane may have no detents, a single detent, or multiple detents. Detents influence how the pane resizes, how it
responds to drag gestures, and how the drag handle behaves during keyboard interaction. When detents are
present, the drag handle snaps to the nearest detent as the user moves it and step is ignored; when
no detents are defined, the split pane resizes freely without snapping.
Double-clicking the drag handle, or pressing ENTER or SPACE when it is focused, will
cycle to the next detent. Use the wrap-detents attribute to allow cycling to wrap from the last
detent back to the first.
<m3e-split-pane value="50" detents="0 25 50 75 100" wrap-detents> <m3e-card slot="start"></m3e-card> <m3e-card slot="end"></m3e-card> </m3e-split-pane>
Use the disabled attribute to disable resizing. When disabled, the drag handle is hidden from
interaction, pointer and keyboard input are ignored, and the split pane remains fixed at its current value.
<m3e-split-pane value="50" disabled> <m3e-card slot="start"></m3e-card> <m3e-card slot="end"></m3e-card> </m3e-split-pane>
You can conditionally render the start or end pane either by omitting content from the corresponding slot or by
applying the hidden attribute to slotted elements. When all assigned elements in a slot are hidden,
the split pane treats that side as empty and updates the layout so the visible pane fully occupies the available
space without modifying the current value.
<m3e-split-pane value="50"> <m3e-card slot="start"></m3e-card> <m3e-card slot="end" hidden></m3e-card> </m3e-split-pane>
Split panes can be nested to create complex layouts, allowing you to build multi-pane workspaces by combining multiple binary splits.
<m3e-split-pane value="25" class="complex">
<m3e-card slot="start"></m3e-card>
<m3e-split-pane slot="end" value="50" orientation="vertical">
<m3e-card slot="start"></m3e-card>
<m3e-card slot="end"></m3e-card>
</m3e-split-pane>
</m3e-split-pane>
This component participates in form submission as a
form-associated custom element
(FACE), contributing its state to the form data. The name attribute defines the key under which the
component's value is submitted in a form. When not disabled, the current value is submitted.
The component honors the disabled state as a property-only control. When disabled
at runtime, it does not sprout a disabled attribute into the DOM.
Split panes use the ARIA role="separator", indicating that the drag handle is an interactive
control used to adjust the relative size of two regions.
The drag handle uses aria-controls to reference the pane it resizes. The start pane is wrapped in
an internal container element with a stable ID, and the drag handle's aria-controls attribute
points to that container. This allows assistive technologies to understand which region is affected when the
user adjusts the split pane.
The split pane supports a label attribute, which maps directly to the drag handle's
aria-label. This allows you to provide a clear, descriptive name for screen reader users, such as
“Resize panels” or “Adjust split view”.
The component exposes its orientation, current position, and size constraints through standard ARIA attributes so assistive technologies can accurately convey the layout to users. These attributes allow screen readers to announce how the split pane is arranged, how far the drag handle has been moved, and what the allowable range of movement is.
aria-orientation communicates whether the panes are arranged horizontally or vertically, helping
users understand the spatial direction in which the drag handle can be moved.
aria-valuenow reports the drag handle's current position as a percentage, allowing screen readers
to announce the exact size of the start pane.
aria-valuemin and aria-valuemax define the minimum and maximum allowed sizes,
ensuring users know the full range of movement and whether further adjustment is possible.
aria-valuetext provides a human-readable description of the current size (for example, “Left pane
20%, right pane 80%” or “Top pane collapsed”), improving clarity for screen reader users. You may customize
this text by supplying a valueFormatter function, which allows full control over how the size is
described. This is useful for localization, or presenting alternative formats.
The @m3e/web package uses
JavaScript Modules. To use it directly in a browser without a bundler, use a module script similar to the following.
<script type="module" src="/node_modules/@m3e/web/dist/split-pane.js"></script>
In addition, you must use an import map to include dependencies.
<script type="importmap">
{
"imports": {
"tslib": "https://cdn.jsdelivr.net/npm/tslib@2.8.1/+esm",
"lit": "https://cdn.jsdelivr.net/npm/lit@3.3.0/+esm",
"lit/": "https://cdn.jsdelivr.net/npm/lit@3.3.0/",
"lit-html": "https://cdn.jsdelivr.net/npm/lit-html@3.3.0/+esm",
"lit-html/directive.js": "https://cdn.jsdelivr.net/npm/lit-html@3.3.0/directive.js",
"lit-html/directives/if-defined.js": "https://cdn.jsdelivr.net/npm/lit-html@3.3.0/directives/if-defined.js",
"lit-html/directives/class-map.js": "https://cdn.jsdelivr.net/npm/lit-html@3.3.0/directives/class-map.js",
"@lit/reactive-element": "https://cdn.jsdelivr.net/npm/@lit/reactive-element@2.0.4/+esm",
"@lit/reactive-element/": "https://cdn.jsdelivr.net/npm/@lit/reactive-element@2.0.4/",
"@m3e/web/core": "/node_modules/@m3e/web/dist/core.js",
"@m3e/web/core/bidi": "/node_modules/@m3e/web/dist/core-bidi.js",
"@m3e/web/core/layout": "/node_modules/@m3e/web/dist/core-layout.js"
}
}
</script>
For production builds, use the minified files to ensure optimal load performance.
The @m3e/web package includes a
Custom Elements Manifest (custom-elements.json), which documents the properties,
attributes, slots, events and CSS custom properties of each component.
You can explore the API below, or integrate the manifest into your own tooling.