-
Notifications
You must be signed in to change notification settings - Fork 10
Splitter
- Splitter component specification
Team name: Astrea
Developer name: Bozhidara Pachilova, Monika Kirkova
Designer name: TBD
- Radoslav Karaivanov
- Svilen Dimchevski
- Damyan Petev
- Radoslav Mirchev
| Version | Author | Date | Notes |
|---|---|---|---|
| 1 | Radoslav Karaivanov | 2026-01-12 | Initial draft |
| 2 | Radoslav Karaivanov | 2026-02-06 | Updated to release draft |
The igc-splitter component is a layout container that displays two adjacent panels (panes) separated by a resizable divider bar. It enables users to dynamically adjust the relative sizes of the panels by dragging the divider, and optionally collapse or expand individual panels to maximize workspace efficiency.
The component supports both horizontal (side-by-side) and vertical (stacked) orientations, making it suitable for a variety of layout scenarios such as:
- Code editors: Source code panel alongside preview or console output
- File browsers: Directory tree navigation with file content view
- Email clients: Inbox list with message preview
- Admin dashboards: Navigation sidebar with main content area
- Data analysis tools: Dataset view with visualization or properties panel
- Flexible sizing: Configure initial, minimum, and maximum sizes for each panel using any valid CSS length unit
- Interactive resize: Drag the splitter bar or use keyboard navigation to adjust panel proportions
- Collapse/expand: Optionally allow users to completely collapse panels to maximize space for the other panel
- Nested layouts: Compose complex multi-panel layouts by nesting splitters within panels
- Full customization: Control visibility of UI elements (drag handle, collapse buttons) and customize icons via slots
- Accessibility-first: Full keyboard navigation and screen reader support following WAI-ARIA guidelines
- Themeable: Integrates seamlessly with the library's theming system using CSS custom properties and shadow parts
- The component must render two distinct panels with slotted content support.
- The splitter bar must be interactive, allowing resize operations via mouse/touch drag and keyboard navigation.
- Both horizontal and vertical orientations must be fully supported and dynamically switchable.
- Panel sizes must respect configured constraints (min/max) during all resize operations.
- Collapse/expand functionality must work via UI buttons, keyboard shortcuts, and programmatic API.
- All resize operations must emit appropriate events with accurate size and delta information.
- The component must be fully keyboard accessible with proper focus management and ARIA attributes.
- The element must be integrated and themeable with the theming mechanism of the library.
- The element must be WAI-ARIA compliant, using the appropriate semantic elements and ARIA roles.
- The component must support RTL (Right-to-Left) layouts without additional configuration.
- Nested splitters must function independently without interference.
- The component must handle edge cases gracefully (invalid sizes, conflicting constraints, rapid interactions).
As and end-user, I expect to be able to:
- see two panels of content, side by side, with a divider bar between them.
- resize the panels by dragging the divider bar.
- focus the divider bar and use the keyboard to resize the panels.
- collapse and expand the panels.
As a developer, I expect to be able to:
- slot arbitrary content inside the panels of the element.
- slot another splitter inside one of the panels, allowing for more advanced layouts.
- control the display layout of the panels - either horizontal or vertical.
- set wether the panels can be resized by the end-user interaction.
- set wether a panel can be collapsed.
- set a default size for each panel.
- set a min and max sizes for a panel.
The splitter component presents users with a clear, intuitive interface for managing multi-panel layouts:
Visual Structure
- Two distinct content panels positioned according to the orientation (side-by-side for horizontal, stacked for vertical)
- A visible divider bar between panels that serves as the resize handle
- Optional drag handle icon on the divider bar indicating interactivity
- Optional collapse/expand buttons on each side of the divider bar when collapse functionality is enabled
Resize Interaction
- Mouse/Touch: Users can click or tap on the splitter bar and drag to resize panels. The cursor changes to indicate the resize direction (↔ for horizontal, ↕ for vertical).
- Keyboard: When the splitter bar has focus, arrow keys resize panels in 10px increments. The panel sizes update in real-time as the user navigates.
- Constraints: Resize operations are visually constrained - users cannot drag beyond configured minimum or maximum sizes, providing clear boundaries.
- Feedback: During resize, both panels update smoothly, giving immediate visual feedback of the size changes.
Collapse/Expand Interaction
- UI Buttons: Clicking a collapse button completely hides the associated panel, maximizing space for the other panel. An expand button appears to restore the panel to its previous size.
- Keyboard Shortcuts: Users can press Ctrl + Arrow keys to quickly collapse or expand panels without leaving keyboard navigation.
- Single Panel Constraint: Only one panel can be collapsed at a time, ensuring content is always visible.
Accessibility Experience
- Focus Indicators: The splitter bar displays a clear focus ring when navigated to via keyboard.
- Screen Reader Announcements: Screen readers announce the splitter's current state, including panel sizes and collapse/expand actions.
- Predictable Navigation: Tab order flows naturally, and keyboard shortcuts follow standard conventions.
The igc-splitter component is designed for ease of integration with a declarative API and flexible configuration options.
The simplest splitter requires only slotted content for the two panels:
<igc-splitter>
<div slot="start">Start panel content</div>
<div slot="end">End panel content</div>
</igc-splitter>By default, this creates a horizontal splitter with equal-sized panels.
<igc-splitter orientation="vertical" start-size="300px">
<div slot="start">Top panel (300px)</div>
<div slot="end">Bottom panel (fills remaining space)</div>
</igc-splitter><igc-splitter
start-size="250px"
start-min-size="200px"
start-max-size="400px"
end-min-size="300px"
>
<nav slot="start">Navigation (200-400px)</nav>
<main slot="end">Main content (min 300px)</main>
</igc-splitter><!-- Disable resizing but allow collapsing -->
<igc-splitter disable-resize>
<div slot="start">Fixed-size panel</div>
<div slot="end">Other panel</div>
</igc-splitter>
<!-- Disable both resize and collapse -->
<igc-splitter disable-resize disable-collapse>
<div slot="start">Completely static layout</div>
<div slot="end">No user interaction</div>
</igc-splitter><!-- Hide drag handle -->
<igc-splitter hide-drag-handle>
<div slot="start">Clean look</div>
<div slot="end">No drag icon</div>
</igc-splitter>
<!-- Hide collapse buttons but keep keyboard support -->
<igc-splitter hide-collapse-buttons>
<div slot="start">Collapse via Ctrl+Arrow only</div>
<div slot="end">No visible buttons</div>
</igc-splitter>
<!-- Custom icons via slots -->
<igc-splitter>
<div slot="start">Panel 1</div>
<div slot="end">Panel 2</div>
<igc-icon slot="drag-handle" name="drag_indicator"></igc-icon>
<igc-icon slot="start-collapse" name="chevron_left"></igc-icon>
<igc-icon slot="start-expand" name="chevron_right"></igc-icon>
</igc-splitter>const splitter = document.querySelector('igc-splitter');
// Toggle panel collapse state
splitter.toggle('start'); // Collapse or expand start panel
splitter.toggle('end'); // Collapse or expand end panel
// Listen to resize events
splitter.addEventListener('igcResizing', (event) => {
const { startPanelSize, endPanelSize, delta } = event.detail;
console.log(
`Start: ${startPanelSize}px, End: ${endPanelSize}px, Delta: ${delta}px`
);
});
splitter.addEventListener('igcResizeEnd', (event) => {
// Save final panel sizes to localStorage
localStorage.setItem('panelSizes', JSON.stringify(event.detail));
});<igc-splitter orientation="horizontal" start-size="250px">
<!-- Left sidebar -->
<aside slot="start">
<h2>Sidebar</h2>
<nav>Navigation items...</nav>
</aside>
<!-- Right side with vertical splitter -->
<igc-splitter slot="end" orientation="vertical" start-size="60%">
<!-- Main content area -->
<main slot="start">
<h1>Main Content</h1>
<p>Primary workspace...</p>
</main>
<!-- Bottom panel -->
<div slot="end">
<h3>Console Output</h3>
<pre>Log messages...</pre>
</div>
</igc-splitter>
</igc-splitter>This creates a three-panel layout: a fixed sidebar on the left, main content on top-right, and a console panel on bottom-right.
// Switch to vertical orientation on mobile
const splitter = document.querySelector('igc-splitter');
const mediaQuery = window.matchMedia('(max-width: 768px)');
function handleViewportChange(e) {
splitter.orientation = e.matches ? 'vertical' : 'horizontal';
if (e.matches) {
// Adjust sizes for mobile
splitter.startSize = '40%';
}
}
mediaQuery.addEventListener('change', handleViewportChange);
handleViewportChange(mediaQuery);The splitter component does not contain any text content that requires localization. All visual elements are icon-based, and developers can provide localized aria-label attributes for collapse/expand buttons through shadow parts if needed.
| Key combination | Result |
|---|---|
| Arrow Up | In vertical orientation, decreases the start panel size by 10px (increases end panel). |
| Arrow Down | In vertical orientation, increases the start panel size by 10px (decreases end panel). |
| Arrow Left | In horizontal orientation, decreases the start panel size by 10px (increases end panel). |
| Arrow Right | In horizontal orientation, increases the start panel size by 10px (decreases end panel). |
| Ctrl + Arrow Up | In vertical orientation, collapses/expands the start panel (if collapse is enabled). |
| Ctrl + Arrow Down | In vertical orientation, collapses/expands the end panel (if collapse is enabled). |
| Ctrl + Arrow Left | In horizontal orientation, collapses/expands the start panel (if collapse is enabled). |
| Ctrl + Arrow Right | In horizontal orientation, collapses/expands the end panel (if collapse is enabled). |
| Home | Resizes to the minimum size of the start panel. |
| End | Resizes to the maximum size of the start panel. |
| Property | Attribute | Reflected | Type | Default | Description |
|---|---|---|---|---|---|
| orientation | orientation | Yes | horizontal | vertical |
horizontal | Orientation layout for the splitter panels. |
| disableCollapse | disable-collapse | Yes | boolean | false | Wether the user can collapse the panels of the splitter. |
| disableResize | disable-resize | Yes | boolean | false | Wether the user can resize the panels by interacting with the splitter bar. |
| hideDragHandle | hide-drag-handle | Yes | boolean | false | Controls the visibility of the drag handle on the splitter bar. |
| hideCollapseButtons | hide-collapse-buttons | Yes | boolean | false | Controls the visibility of the expand/collapse buttons on the splitter bar. |
| startSize | start-size | No | string | undefined |
- | The initial display size of the start panel. |
| endSize | end-size | No | string | undefined |
- | The initial display size of the end panel. |
| startMinSize | start-min-size | No | string | undefined |
- | The minimum display size for the start panel. |
| startMaxSize | start-max-size | No | string | undefined |
- | The maximum display size for the start panel. |
| endMinSize | end-min-size | No | string | undefined |
- | The minimum display size for the end panel. |
| endMaxSize | end-max-size | No | string | undefined |
- | The maximum display size for the end panel. |
| Name | Type signature | Description |
|---|---|---|
| toggle | (panel: 'start' | 'end'): void |
Toggles the collapsed state of the given panel. |
| Name | Cancellable | Description |
|---|---|---|
| igcResizeStart | false | Fired when a user start resizing with the splitter bar. |
| igcResizing | false | Fired during user resizing. |
| igcResizeEnd | false | Fired when the user stops resizing. |
Event Details:
All resize events emit the following detail object:
Note
This is a subject to change.
interface IgcSplitterResizeEventDetail {
/** The current size of the start panel in pixels */
startPanelSize: number;
/** The current size of the end panel in pixels */
endPanelSize: number;
/** The change in size since the resize operation started (only for igcResizing and igcResizeEnd) */
delta?: number;
}| Name | Description |
|---|---|
| start | The start panel ot the the splitter. In horizontal layout this is the leftmost panel and in vertical layout it is the topmost. |
| end | The end panel of the splitter. In horizontal layout this is the rightmost panel and in vertical layout it is the bottom one. |
| drag-handle | Optional slot to customize the drag handle icon/content on the splitter bar. |
| start-expand | Optional slot to customize the icon for expanding the start panel. |
| start-collapse | Optional slot to customize the icon for collapsing the start panel. |
| end-expand | Optional slot to customize the icon for expanding the end panel. |
| end-collapse | Optional slot to customize the icon for collapsing the end panel. |
Note
This is a subject to change.
| Part | Description |
|---|---|
| splitter-bar | The resizable bar element between the two panels. |
| drag-handle | The drag handle icon/element on the splitter bar. |
| start-panel | The container for the start panel content. |
| end-panel | The container for the end panel content. |
| start-collapse-btn | The button to collapse the start panel. |
| end-collapse-btn | The button to collapse the end panel. |
| start-expand-btn | The button to expand the start panel when collapsed. |
| end-expand-btn | The button to expand the end panel when collapsed. |
-
Default rendering
- Component renders with default horizontal orientation
- Both panels are visible with equal sizes (if no explicit sizes set)
- Splitter bar is rendered between panels
- Drag handle is visible on the splitter bar
- Collapse buttons are visible (if collapse is not disabled)
-
Orientation
- Setting
orientation="horizontal"renders panels side by side - Setting
orientation="vertical"renders panels stacked vertically - Changing orientation dynamically updates the layout
- Setting
-
Initial sizing
- Setting
startSizeinitializes the start panel to the specified size - Setting
endSizeinitializes the end panel to the specified size - Sizes accept valid CSS length values (px, %, em, etc.)
- When both sizes are set, they should be respected (within container constraints)
- When only one size is set, the other panel fills remaining space
- Setting
-
Mouse/pointer resize
- Dragging the splitter bar resizes both panels
- Resize is constrained by
startMinSizeandstartMaxSize - Resize is constrained by
endMinSizeandendMaxSize - Cursor changes appropriately on hover (e.g., col-resize, row-resize)
- Resize works correctly in both orientations
-
Resize events
-
igcResizeStartfires when drag begins -
igcResizingfires during drag operation -
igcResizeEndfires when drag completes - Event detail contains correct
startPanelSizeandendPanelSize - Event detail contains correct
deltaforigcResizingandigcResizeEnd
-
-
Disable resize
- Setting
disableResize="true"prevents user resizing - Splitter bar is still visible but non-interactive
- Cursor does not change on hover when resize is disabled
- Keyboard resize is also disabled
- Setting
-
Collapse/expand via UI
- Clicking collapse button on start panel collapses it
- Clicking collapse button on end panel collapses it
- Expand button appears when panel is collapsed
- Clicking expand button restores the panel to previous size
- Only one panel can be collapsed at a time
-
Collapse/expand via API
-
toggle('start')toggles the collapsed state of start panel -
toggle('end')toggles the collapsed state of end panel - Method works correctly when called programmatically
-
-
Disable collapse
- Setting
disableCollapse="true"hides collapse/expand buttons - Collapse is not possible via keyboard when disabled
- API method
toggle()should still work (or be a no-op depending on design decision)
- Setting
-
Hide drag handle
- Setting
hideDragHandle="true"hides the drag handle icon - Splitter bar is still interactive for resizing
- Splitter bar is still focusable
- Setting
-
Hide collapse buttons
- Setting
hideCollapseButtons="true"hides all collapse/expand buttons - Collapse is still possible via keyboard (if not disabled)
- Collapse is still possible via API method
- Setting
-
Focus management
- Splitter bar is focusable with
Tabkey (when interactive) - Splitter bar has visible focus indicator
- Focus is not lost during resize or collapse operations
- Splitter bar is focusable with
-
Arrow key resize
- Arrow keys resize panels by 10px increments
- Correct arrow keys work based on orientation
- Resize respects min/max constraints
- Resize triggers appropriate events
-
Keyboard collapse/expand
-
Ctrl + Arrowcombinations collapse/expand panels - Correct combinations work based on orientation
- Works only when collapse is enabled
-
-
Home/End keys
-
Homekey resizes to start panel minimum size -
Endkey resizes to start panel maximum size - Keys work correctly in both orientations
-
-
Nesting behavior
- Splitter can be nested inside another splitter's panel
- Nested splitters maintain independent state
- Resize operations don't interfere with parent/child splitters
- Focus management works correctly with nested splitters
-
Content slots
- Content slotted into
startrenders in start panel - Content slotted into
endrenders in end panel - Content updates when slot content changes
- Complex content (forms, tables, etc.) renders correctly
- Content slotted into
-
Custom icons
- Custom drag handle via
drag-handleslot - Custom expand icons via
start-expandandend-expandslots - Custom collapse icons via
start-collapseandend-collapseslots - Default icons used when slots are empty
- Custom drag handle via
-
Min/max constraints
- Panels respect
startMinSizeduring resize - Panels respect
startMaxSizeduring resize - Panels respect
endMinSizeduring resize - Panels respect
endMaxSizeduring resize - Invalid constraint values are handled gracefully
- Constraints work with different CSS units
- Panels respect
-
Constraint conflicts
- Component handles conflicting constraints gracefully
- When min sizes exceed container, behavior is predictable
- When both panels have max sizes smaller than container, behavior is predictable
-
ARIA attributes
- Splitter bar has
role="separator" -
aria-orientationmatches component orientation -
tabindex="0"when interactive,-1when not -
aria-valuenow,aria-valuemin,aria-valuemaxare set appropriately - Collapse buttons have appropriate
aria-label
- Splitter bar has
-
Screen reader support
- Screen readers announce splitter bar correctly
- Resize operations are announced
- Collapse/expand state changes are announced
-
Right-to-Left
- Splitter works correctly in RTL context
- Horizontal orientation is mirrored in RTL
- Arrow key navigation is reversed appropriately in RTL
- Visual elements (buttons, handles) are positioned correctly
-
Container resizing
- Component adapts when container size changes
- Relative sizes (percentages) update correctly
- Absolute sizes are maintained when possible
-
Rapid interactions
- Rapid resize operations don't cause visual glitches
- Rapid collapse/expand toggles are handled correctly
- Event throttling/debouncing works as expected
-
Invalid configurations
- Invalid size values are handled gracefully
- Invalid orientation values fall back to default
- Missing slot content doesn't break rendering
Following the official guidelines the following ARIA properties must be present on the splitter's bar:
- it must have an ARIA role of separator.
- it must have aria-orientation equal to the orientation value of the splitter element.
- if the splitter is interactive (i.e. resizable or collapsible), it must have a tabindex of 0, otherwise it must be set to -1.
- Nice to have: consider using aria-value|now|min|max if appropriate.
Already covered by the relevant section of the specification.
The splitter element should work in Right-to-Left context without additional setup or configuration.