Skip to content

Surfaces

Splitter

Bit.BlazorUISplitPaneResizable

Two panels, side by side or stacked, with a gutter between them the reader drags or moves from the keyboard. Panels take sizes and limits, the split can be bound as a percentage, remembered across visits and folded away, and the gutter is a WAI-ARIA window splitter.

Notes

The gutter is the control: it is the one tab stop of a splitter and reports its position to screen readers, so give every splitter an AriaLabel that says what it resizes.

A splitter fills the height of its container - give that container, or the splitter's Style, a height.

Usage

Every example is live. Open its code to see exactly what produced the component running underneath.

Basic

Put content in FirstPanel and SecondPanel and name the gutter with AriaLabel. Drag the gutter, or focus it and use the arrow keys; a double-click puts it back. Each panel scrolls its own content.

First panel

Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams.
Second panel

Each word carried meaning, each pause brought understanding. The spaces here are open for growth.

Vertical

Vertical stacks the panels: the first one is on top, sizes become heights and the up and down arrows move the gutter.

First panel
Second panel

Size & limits

FirstPanelSize or SecondPanelSize pins one panel in pixels while the other takes the rest. The MinSize and MaxSize of each panel bound the gutter for the pointer, the keyboard and Percent alike - and so does a min or max size set in CSS through Styles or Classes, in any unit.

Starts at 200px, stays between 120px and 320px.
Never narrower than 100px.

Takes the rest, never under 30% (CSS).
Starts at 150px.

Percent

Percent is the first panel's share of the splitter, 0 to 100. It keeps its proportion when the container resizes, binds both ways, and wins over the panel sizes while it has a value. Set one way, it is the page's to hold; DefaultPercent only sets where the split starts and resets to.


First panel
Second panel

Starts at 30%, free to move, double-click to go back.
Second panel

Dragging

DragStep lands the split on a pixel grid - a column, a tile, a line of text - for the pointer and the keyboard alike. LazyResize drags a line instead of the panels and lays them out once, on release - for content too heavy to lay out on every frame, such as a large grid, an editor or a chart.


Stops every 50 pixels
The panels follow the pointer.

Gutter

GutterSize sets the thickness of the gutter. However thin it is, a press is caught up to GutterHitSize (24px, 44px on touch) without taking room from the panels. GutterIconName draws an icon on it and GutterTemplate any decoration - nothing focusable, the gutter itself is the control.


GutterSize
Second panel

A 1px hairline, grabbed anywhere within 16px
Second panel

GutterIconName
Second panel

GutterTemplate
Second panel

Collapsible

Collapsible lets the first panel fold away: Enter or Ctrl + arrow on the gutter, or a drag into the edge. Press the folded gutter to open it again, back at its old size. Collapsed binds, CollapsedSize leaves a strip of the panel showing, SnapSize sets how close to the edge a drag must end to fold, and CollapseSecondPanel folds the second panel instead.

A panel that folds away
Collapsed: False

Folds only when dragged within 40px of the edge.
Second panel

A document that takes the whole splitter once the inspector is away
An inspector that folds to the end

Collapse button

ShowCollapseButton puts the fold on the gutter where the pointer can see it. The chevron follows the orientation, the folding side and the writing direction; CollapseIconName and ExpandIconName (or CollapseIcon and ExpandIcon) replace it. The keys on the gutter already do the same, so the button stays out of the tab order.

Press the chevron to fold this away.
Second panel

A stacked splitter folds upwards.
Second panel

CollapseIconName and ExpandIconName
An inspector with icons of its own

Cancelling a collapse

OnCollapsing runs before the panel folds or opens, with IsCollapsing and the Reason. Set Cancel to leave the panel as it is; the callback is awaited, so it can wait for a confirmation.


Folds away only with permission
Second panel

Nothing has been folded yet.

Events

OnResizeStart is followed by exactly one of OnResizeEnd and OnResizeCancel (Escape, or the browser taking the pointer away); all carry the first panel's share. OnResize reports every frame of a drag - leave it unset when only the result matters, and no calls are made while dragging. OnCollapsedChange reports folds, and OnGutterDoubleClick double-clicks.

First panel
Second panel

No resize yet.


NoResetOnDoubleClick turns off the built-in reset, so the double-click can do something else - here, split the panels evenly:

Double-click the gutter
to split evenly.

Programmatic control

From a reference: SetPercent, GetPercent (measured, so it answers before any drag), ResetSize, Collapse, Expand, ToggleCollapse (not limited by Collapsible) and FocusAsync. A Percent or Collapsed the page binds one way stays the page's.


First panel
Second panel

Nothing has been measured yet.

Persistence

PersistKey remembers the position and the fold in local storage - or session storage, with PersistInSessionStorage - and restores them on the next visit. Use one key per splitter. Move the gutter below and reload the page.

Where you left it
Second panel

Read-only & disabled

ReadOnly locks the split and keeps the look; Disabled locks it and dims the splitter. Either way the gutter leaves the tab order and becomes a plain separator; the methods still work.

Read-only
The gutter stays where it is.

Disabled
The whole splitter is dimmed.

Nested

Splitters nest in either direction to build multi-pane layouts; each keeps its own sizes, limits, gutter and state.

Sidebar
Editor
Preview
Terminal

Accessibility

The gutter follows the WAI-ARIA window splitter pattern: one tab stop, a separator named by AriaLabel that controls the first panel and reports its share, within the range the panel's limits (and a fold) allow.
  • Arrow keys move it by KeyboardStep pixels (10 by default); Shift + arrow, Page Up and Page Down by ten steps.
  • Home and End take it to the smallest and largest size the panels allow.
  • Enter, or Ctrl + the arrow towards or away from the folding panel, folds and opens it.
  • Escape cancels a drag in progress.
A panel folded to 0px is made inert, so Tab never lands in content that is off the screen. Fold the panel below and tab through: the button inside it is skipped.

A drag needs a single-pointer alternative (WCAG 2.5.7): the collapse button and the double-click are one, and controls of the page's own driving Percent are another.


One arrow key moves the gutter 50px.

Cascading parameters

BitParams hands a BitSplitterParams to every splitter under it, so a layout sets the shared look and behavior once. The values are defaults: a splitter keeps whatever it sets itself. The panels, Percent, Collapsed, PersistKey and the callbacks stay per instance.

From the cascade
Second panel

No collapse button of its own
Second panel

Outside the cascade
Second panel

External Icons

Use icons from external libraries like FontAwesome and Bootstrap Icons with the GutterIcon parameter (BitIconInfo).

FontAwesome:

First panel
"fa-solid fa-arrows-left-right"

First panel
BitIconInfo.Css("fa-solid fa-grip-vertical")

First panel
BitIconInfo.Fa("solid grip-lines-vertical")


Bootstrap:

First panel
GutterIcon=@("bi bi-grip-vertical")

First panel
BitIconInfo.Bi("arrow-left-right")

Style & Class

Style and Class dress the root - where the height goes. Styles and Classes reach the parts: the panels, the gutter, its grip or icon, the collapse button and its icon, and the lazy drag's line. The public --bit-Splitter-* CSS variables restyle every state at once, from a splitter's Style, a wrapper or :root.


Component's Style & Class:

Style
Second panel
Class
Second panel


Styles & Classes:

Styles
Second panel
Classes
Second panel


CSS variables:

One splitter's Style
Hover and drag the gutter
Set on a wrapper,
the variables reach
every splitter inside it.

RTL

In a right-to-left splitter - by Dir or by a dir on any ancestor - the first panel is on the right; dragging the gutter left, or the arrow key pointing away from the panel, makes it bigger, and the collapse chevron turns with it.

پنل اول
پنل دوم

CSS variables

The public custom properties this component reads off its root, for what no parameter covers.

Every variable is read with a fallback and never declared by the component, so it inherits like any other custom property: set one on :root (or in a [bit-theme] block) to restyle every instance, on any ancestor to restyle the ones inside it, or on the Style of one instance to restyle that one alone. Leave a variable unset and the component falls back to the theme token beside it.

BitSplitter CSS variables

Name Default value Description
--bit-Splitter-gutter-size spacing(1.25) Thickness of the gutter. GutterSize wins over it.
--bit-Splitter-gutter-hit-size spacing(3), spacing(5.5) for a coarse pointer The smallest strip a press takes hold of the gutter in, reaching past a thinner gutter without taking room from the panels. GutterHitSize wins over it.
--bit-Splitter-gutter-background --bit-clr-brd-sec The gutter at rest, and while it cannot be moved.
--bit-Splitter-gutter-hover-background --bit-clr-brd-pri The gutter under the pointer.
--bit-Splitter-gutter-active-background The hover background The gutter while it is being dragged.
--bit-Splitter-gutter-indicator-color --bit-clr-fg-sec The default grip drawn on the gutter - what keeps a gutter at rest at 3:1 against its surroundings.
--bit-Splitter-gutter-icon-color --bit-clr-fg-sec The icon GutterIcon or GutterIconName draws on the gutter.
--bit-Splitter-gutter-icon-size --bit-tg-fs-xs Size of the icon drawn on the gutter.
--bit-Splitter-preview-background --bit-clr-pri The line a LazyResize drag moves in place of the panels.
--bit-Splitter-collapse-button-color --bit-clr-fg-sec The chevron of the collapse button.
--bit-Splitter-collapse-button-background --bit-clr-bg-pri The collapse button at rest.
--bit-Splitter-collapse-button-border-color --bit-clr-brd-pri The outline of the collapse button at rest.
--bit-Splitter-collapse-button-hover-color --bit-clr-pri-text The chevron of the collapse button under the pointer.
--bit-Splitter-collapse-button-hover-background --bit-clr-pri The collapse button and its outline under the pointer.
--bit-Splitter-collapse-button-radius --bit-shp-radius-full Corner radius of the collapse button.

API

Every parameter, public member, sub-class and enum this component exposes.

BitSplitter parameters

Name Type Default value Description
Classes BitSplitterClassStyles? null Custom CSS classes for different parts of the BitSplitter.
CollapseIcon BitIconInfo? null The icon of the collapse button while the panel that folds is open, using BitIconInfo for external icon library support. Takes precedence over CollapseIconName when both are set.
CollapseIconName string? null The name of the built-in Fluent UI icon shown on the collapse button while the panel that folds is open. The default is a chevron pointing at the panel that is about to be folded away, which follows the orientation of the splitter, which panel folds and the writing direction of the page.
Collapsed bool false Whether the panel that folds is collapsed; bindable. A collapsed panel keeps its content in the DOM, drops to CollapsedSize past its minimum, and is made inert when that size is 0. Expanding restores the previous split.
CollapsedSize int 0 The size, in pixels, the folded panel is held at while it is collapsed.
Collapsible bool false Lets the reader fold a panel away from the gutter: Enter, Ctrl + arrow, the collapse button, or a drag that snaps it shut at its edge.
CollapseSecondPanel bool false Folds the second panel instead of the first - an inspector or a preview at the far end. Everything collapse-related follows it; Percent still describes the first panel.
DefaultPercent double? null The share of the splitter, 0 to 100, the first panel starts at and is reset to, while the reader stays free to move it. Wins over the panel sizes; Percent wins over it.
DragStep int 0 A pixel grid the split lands on, for the pointer and the keyboard alike. 0 is no grid.
ExpandIcon BitIconInfo? null The icon of the collapse button while the panel that folds is away, using BitIconInfo for external icon library support. Takes precedence over ExpandIconName when both are set.
ExpandIconName string? null The name of the built-in Fluent UI icon shown on the collapse button while the panel that folds is away. The default is a chevron pointing at the room the panel is about to come back into.
FirstPanel RenderFragment? null The content for the first panel.
FirstPanelSize int? null The initial size of the first panel in pixels. From the first drag on, the split is held as a percentage in Percent, which takes precedence over this and over SecondPanelSize.
FirstPanelMaxSize int? null The max size of the first panel in pixels.
FirstPanelMinSize int? null The min size of the first panel in pixels.
GutterHitSize int? null The smallest strip, in pixels, a press takes hold of the gutter in; it reaches past a thinner gutter without taking room from the panels. Unset, 24 (the WCAG target size), and 44 for a coarse pointer.
GutterIcon BitIconInfo? null The icon for the BitSplitter gutter using BitIconInfo for external icon library support. Takes precedence over GutterIconName when both are set.
GutterIconName string? null The name of the built-in Fluent UI icon to render in the BitSplitter gutter. Ignored when GutterIcon is also set.
GutterSize int? null The size of BitSplitter gutter in pixels.
GutterTemplate RenderFragment? null The custom content of the gutter, in place of the icon or of the default grip indicator. The gutter is the separator itself, so what goes in here is decoration rather than a control.
KeyboardStep int 10 How far, in pixels, an arrow key moves the gutter. Shift + arrow, Page Up and Page Down move ten steps; Home and End go to the limits.
LazyResize bool false Drags a line instead of the panels and lays them out once, on release - for content too heavy to lay out on every frame.
NoResetOnDoubleClick bool false Keeps the gutter from resetting the splitter to the sizes its parameters declare when it is double-clicked.
OnCollapsedChange EventCallback<bool> The callback invoked when the panel that folds is collapsed or expanded.
OnCollapsing EventCallback<BitSplitterCollapseArgs> The callback invoked before the panel that folds is collapsed or expanded, with what is about to happen and what asked for it. Set Cancel on the arguments to leave the panel as it is. The callback is awaited, and nothing else folds the panel while it is running.
OnGutterDoubleClick EventCallback The callback invoked when the gutter is double-clicked, whether or not the double-click also resets the splitter.
OnResize EventCallback<double> The callback invoked continuously while the gutter is being dragged, with the new share of the splitter the first panel takes up, as a percentage. It is coalesced to one call per animation frame, and a splitter with no handler for it makes no interop call at all while it is being dragged.
OnResizeCancel EventCallback<double> The callback invoked when a resize is abandoned rather than finished - by Escape, or by the browser taking the pointer away - with the share of the splitter the first panel is put back to. Exactly one of this and OnResizeEnd follows every OnResizeStart.
OnResizeEnd EventCallback<double> The callback invoked when a resize has finished, with the share of the splitter the first panel ended up taking, as a percentage.
OnResizeStart EventCallback<double> The callback invoked when a resize starts, with the share of the splitter the first panel takes up at that moment, as a percentage.
PersistKey string? null The storage key the position and the fold are remembered under, and restored from on the next visit. Unique per splitter within the origin.
PersistInSessionStorage bool false Keeps what PersistKey remembers in the browser's session storage rather than its local storage, so the position lasts as long as the tab and no longer.
Percent double? null The share of the splitter the first panel takes up, as a percentage between 0 and 100. It survives the container being resized and can be bound, so every drag, key press and collapse is reported back to the page. While it has a value it takes precedence over FirstPanelSize and SecondPanelSize.
ReadOnly bool false Keeps the splitter as it is: the gutter is still shown and still looks like itself, but it cannot be dragged or moved from the keyboard.
SecondPanel RenderFragment? null The content for the second panel.
SecondPanelSize int? null The initial size of the second panel in pixels. Ignored while Percent has a value, which is the case from the first drag on.
SecondPanelMaxSize int? null The max size of the second panel in pixels.
SecondPanelMinSize int? null The min size of the second panel in pixels.
ShowCollapseButton bool false Draws a fold/unfold button on the gutter of a Collapsible splitter. It is kept out of the tab order, since the gutter's keys do the same.
SnapSize int 0 How close, in pixels, to its edge a drag must leave the folding panel for it to snap shut. 0 uses half its minimum size, or a twentieth of the splitter without one.
Styles BitSplitterClassStyles? null Custom CSS styles for different parts of the BitSplitter.
Vertical bool false Sets the orientation of BitSplitter to vertical, stacking the two panels instead of placing them side by side.

BitSplitter public members

Name Type Default value Description
Collapse Task Collapses the panel that folds. Does nothing if it is already collapsed. Not turned away by Collapsible, which is about what the reader may do to the gutter.
Expand Task Expands the panel that folds, putting the split back where it was before the fold.
ToggleCollapse Task Collapses the panel that folds if it is expanded and expands it if it is collapsed.
SetPercent Task Moves the split so that the first panel takes up the given share of the splitter, as a percentage between 0 and 100. The value is still held to the minimum and maximum sizes of both panels.
GetPercent ValueTask<double?> Measures the first panel's current share of the splitter - including a split nobody has moved yet, which Percent does not hold. Null before the splitter is set up or when it has no room.
ResetSize Task Clears Percent and hands the layout back to DefaultPercent, FirstPanelSize and SecondPanelSize - which is what a double-click on the gutter does. A Percent the page binds one way is not reset.
FocusAsync ValueTask Gives the focus to the gutter, which is the control a splitter is driven by. The overload taking a bool prevents the gutter from being scrolled into view.

BitComponentBase parameters

Name Type Default value Description
AriaLabel string? null Gets or sets the accessible label for the component, used by assistive technologies.
Class string? null Gets or sets the CSS class name(s) to apply to the rendered element.
Dir BitDir? null Gets or sets the text directionality for the component's content.
Disabled bool false Gets or sets a value indicating whether the component is disabled and cannot respond to user interaction.
ForceAnimation bool false Gets or sets a value indicating whether the component's animations play at their full duration even when reduced motion is requested.
HtmlAttributes Dictionary<string, object> new Dictionary<string, object>() Captures additional HTML attributes to be applied to the rendered element, in addition to the component's parameters.
Id string? null Gets or sets the unique identifier for the component's root element.
Style string? null Gets or sets the CSS style string to apply to the rendered element.
TabIndex string? null Gets or sets the tab order index for the component when navigating with the keyboard.
Visibility BitVisibility BitVisibility.Visible Gets or sets the visibility state (visible, hidden, or collapsed) of the component.

BitComponentBase public members

Name Type Default value Description
UniqueId Guid Guid.NewGuid() Gets the readonly unique identifier for the component's root element, assigned when the component instance is constructed.
RootElement ElementReference Gets the reference to the root HTML element associated with this component.

BitSplitterCollapseArgs properties

Name Type Default value Description
IsCollapsing bool The state the panel that folds is about to move to: true while it is being folded away, false while it is being brought back.
Reason BitSplitterCollapseReason What made the panel collapse or expand: the gutter, a drag that snapped it shut, a call to one of the Collapse, Expand and ToggleCollapse methods, or the remembered position being restored.
Cancel bool false Set to true to cancel the collapse or the expansion and leave the panel as it is.

BitSplitterClassStyles properties

Name Type Default value Description
Root string? null The custom CSS class/style for the root element of the BitSplitter.
CollapseButton string? null The custom CSS class/style for the collapse button on the gutter of the BitSplitter.
CollapseButtonIcon string? null The custom CSS class/style for the icon of the collapse button of the BitSplitter.
FirstPanel string? null The custom CSS class/style for the first panel of the BitSplitter.
Gutter string? null The custom CSS class/style for the gutter (the separator) of the BitSplitter.
GutterIcon string? null The custom CSS class/style for the icon rendered inside the gutter of the BitSplitter.
GutterIndicator string? null The custom CSS class/style for the default grip indicator rendered inside the gutter of the BitSplitter.
Preview string? null The custom CSS class/style for the line a lazy drag moves in place of the panels of the BitSplitter.
SecondPanel string? null The custom CSS class/style for the second panel of the BitSplitter.

BitIconInfo properties

Name Type Default value Description
Name string? null Gets or sets the name of the icon.
BaseClass string? null Gets or sets the base CSS class for the icon. For built-in Fluent UI icons, this defaults to "bit-icon". For external icon libraries like FontAwesome, you might set this to "fa" or leave empty.
Prefix string? null Gets or sets the CSS class prefix used before the icon name. For built-in Fluent UI icons, this defaults to "bit-icon--". For external icon libraries, you might set this to "fa-" or leave empty.

BitSplitterCollapseReason enum

Name Value Description
Gutter 0 The gutter was pressed, or moved by the Enter key or Ctrl with an arrow key.
Drag 1 The gutter was dragged close enough to the panel's own edge of the splitter for it to snap shut.
Method 2 The Collapse, Expand or ToggleCollapse method of the splitter was called.
Restore 3 The position the splitter had remembered under its PersistKey was restored.

BitVisibility enum

Name Value Description
Visible 0 The content of the component is visible.
Hidden 1 The content of the component is hidden, but the space it takes on the page remains (visibility:hidden).
Collapsed 2 The component is hidden (display:none).

BitDir enum

Name Value Description
Ltr 0 Ltr (left to right) is to be used for languages that are written from the left to the right (like English).
Rtl 1 Rtl (right to left) is to be used for languages that are written from the right to the left (like Arabic).
Auto 2 Auto lets the user agent decide. It uses a basic algorithm as it parses the characters inside the element until it finds a character with a strong directionality, then applies that directionality to the whole element.

Feedback

Found a mistake, a gap, or something that could be clearer? Every page and every component is one click from its source.