SplitView
Use the SplitView component to build draggable two-pane layouts with Bulma semantic divider colors, horizontal or vertical orientation, nested workspaces, disabled states, and resize events.
How it works #
How to use:
- Place the component inside a container with an explicit height.
- Provide the two pane fragments through
<Pane1>and<Pane2>. - Optionally set
PrimaryPaneSizeto choose the initial split percentage. - Optionally set
Colorto a Bulma semantic value when the divider should pick up your UI accent color. - Drag the divider with a mouse or touch input, depending on the device.
Project Explorer
- Components
- Pages
- Services
- wwwroot
- Program.cs
File Preview
Drag the divider to decide whether navigation or the working surface should receive more space.
<div style="height: 22rem;">
<SplitView PrimaryPaneSize="32">
<Pane1>
<div style="padding: 1rem;">
<p class="title is-6 mb-3">Project Explorer</p>
<div class="content">
<ul>
<li>Components</li>
<li>Pages</li>
<li>Services</li>
<li>wwwroot</li>
<li>Program.cs</li>
</ul>
</div>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<p class="title is-6 mb-3">File Preview</p>
<div class="box mb-3">
SplitView works well when the left pane lists items and the right pane shows details, previews, or editors for the current selection.
</div>
<div class="content">
<p>Drag the divider to decide whether navigation or the working surface should receive more space.</p>
</div>
</div>
</Pane2>
</SplitView>
</div>
Disable #
How to use:
- Bind
IsDisabledto a boolean field. - Toggle that field when your page enters or leaves a locked layout state.
- Optionally bind
PrimaryPaneSizeso the current split stays visible in your page state.
IsDisabled: False
Current PrimaryPaneSize: 50%Locked Navigation
Disable dragging when you want to preserve a known layout during a wizard, review mode, or presentation flow.
Working Surface
<div class="is-flex is-align-items-center is-flex-wrap-wrap mb-4" style="gap: 0.75rem;">
<Button Color="ButtonColor.Primary" Size="ButtonSize.Small" @onclick="EnableDrag">Enable drag</Button>
<Button Color="ButtonColor.Warning" Size="ButtonSize.Small" @onclick="DisableDrag">Disable drag</Button>
<Button Size="ButtonSize.Small" @onclick="ToggleDrag">Toggle</Button>
<span>Current <code>IsDisabled</code>: <strong>@isDisabled</strong></span>
<span>Current <code>PrimaryPaneSize</code>: <strong>@primaryPaneSize.ToString("0.##")%</strong></span>
</div>
<div style="height: 20rem;">
<SplitView IsDisabled="@isDisabled" @bind-PrimaryPaneSize="primaryPaneSize">
<Pane1>
<div style="padding: 1rem;">
<p class="title is-6 mb-3">Locked Navigation</p>
<div class="content">
<p>Disable dragging when you want to preserve a known layout during a wizard, review mode, or presentation flow.</p>
</div>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<p class="title is-6 mb-3">Working Surface</p>
<div class="box">
Turn dragging off and on with the buttons above, then try moving the divider again.
</div>
</div>
</Pane2>
</SplitView>
</div>
@code {
private bool isDisabled;
private double primaryPaneSize = 50;
private void DisableDrag() => isDisabled = true;
private void EnableDrag() => isDisabled = false;
private void ToggleDrag() => isDisabled = !isDisabled;
}
Colors #
How to use:
- Set
Colorto a Bulma semantic value such asPrimary,Link,Success, orDanger. - Use the semantic color as the divider default when you want a stronger visual cue between the panes.
- Optionally override individual divider states later with the explicit divider color parameters.
SplitViewColor palette so you can see how the interaction states inherit each accent.
Default
Primary
Link
Info
Success
Warning
Danger
White
Light
Dark
Black
<div class="is-flex is-flex-direction-column" style="gap: 1rem;">
<div>
<p class="title is-6 mb-2">Default</p>
<div class="box" style="height: 8rem;">
<SplitView PrimaryPaneSize="34" Color="SplitViewColor.None">
<Pane1>
<div style="padding: 1rem;">
<strong>Overview</strong>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<span>Default neutral divider</span>
</div>
</Pane2>
</SplitView>
</div>
</div>
<div>
<p class="title is-6 mb-2">Primary</p>
<div class="box" style="height: 8rem;">
<SplitView PrimaryPaneSize="34" Color="SplitViewColor.Primary">
<Pane1>
<div style="padding: 1rem;">
<strong>Navigation</strong>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<span>Primary divider accent</span>
</div>
</Pane2>
</SplitView>
</div>
</div>
<div>
<p class="title is-6 mb-2">Link</p>
<div class="box" style="height: 8rem;">
<SplitView PrimaryPaneSize="34" Color="SplitViewColor.Link">
<Pane1>
<div style="padding: 1rem;">
<strong>Activity</strong>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<span>Link divider accent</span>
</div>
</Pane2>
</SplitView>
</div>
</div>
<div>
<p class="title is-6 mb-2">Info</p>
<div class="box" style="height: 8rem;">
<SplitView PrimaryPaneSize="34" Color="SplitViewColor.Info">
<Pane1>
<div style="padding: 1rem;">
<strong>Insights</strong>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<span>Info divider accent</span>
</div>
</Pane2>
</SplitView>
</div>
</div>
<div>
<p class="title is-6 mb-2">Success</p>
<div class="box" style="height: 8rem;">
<SplitView PrimaryPaneSize="34" Color="SplitViewColor.Success">
<Pane1>
<div style="padding: 1rem;">
<strong>Status</strong>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<span>Success divider accent</span>
</div>
</Pane2>
</SplitView>
</div>
</div>
<div>
<p class="title is-6 mb-2">Warning</p>
<div class="box" style="height: 8rem;">
<SplitView PrimaryPaneSize="34" Color="SplitViewColor.Warning">
<Pane1>
<div style="padding: 1rem;">
<strong>Review</strong>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<span>Warning divider accent</span>
</div>
</Pane2>
</SplitView>
</div>
</div>
<div>
<p class="title is-6 mb-2">Danger</p>
<div class="box" style="height: 8rem;">
<SplitView PrimaryPaneSize="34" Color="SplitViewColor.Danger">
<Pane1>
<div style="padding: 1rem;">
<strong>Alerts</strong>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<span>Danger divider accent</span>
</div>
</Pane2>
</SplitView>
</div>
</div>
<div>
<p class="title is-6 mb-2">White</p>
<div class="box has-background-dark" style="height: 8rem;">
<SplitView PrimaryPaneSize="34" Color="SplitViewColor.White">
<Pane1>
<div class="has-text-white" style="padding: 1rem;">
<strong>Contrast</strong>
</div>
</Pane1>
<Pane2>
<div class="has-text-white" style="padding: 1rem;">
<span>White divider accent</span>
</div>
</Pane2>
</SplitView>
</div>
</div>
<div>
<p class="title is-6 mb-2">Light</p>
<div class="box has-background-dark" style="height: 8rem;">
<SplitView PrimaryPaneSize="34" Color="SplitViewColor.Light">
<Pane1>
<div class="has-text-white" style="padding: 1rem;">
<strong>Palette</strong>
</div>
</Pane1>
<Pane2>
<div class="has-text-white" style="padding: 1rem;">
<span>Light divider accent</span>
</div>
</Pane2>
</SplitView>
</div>
</div>
<div>
<p class="title is-6 mb-2">Dark</p>
<div class="box" style="height: 8rem;">
<SplitView PrimaryPaneSize="34" Color="SplitViewColor.Dark">
<Pane1>
<div style="padding: 1rem;">
<strong>Inspector</strong>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<span>Dark divider accent</span>
</div>
</Pane2>
</SplitView>
</div>
</div>
<div>
<p class="title is-6 mb-2">Black</p>
<div class="box" style="height: 8rem;">
<SplitView PrimaryPaneSize="34" Color="SplitViewColor.Black">
<Pane1>
<div style="padding: 1rem;">
<strong>Console</strong>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<span>Black divider accent</span>
</div>
</Pane2>
</SplitView>
</div>
</div>
</div>
Orientation #
How to use:
- Use
SplitViewOrientation.Horizontalfor side-by-side panes. - Use
SplitViewOrientation.Verticalfor stacked panes. - Choose the orientation that best matches the way users compare or edit the content.
Horizontal
Navigation
The panes sit side by side for classic master-detail layouts.
Details
Horizontal mode is a good fit for desktops and wide work areas.
Vertical
Preview
Vertical mode stacks the panes and lets the divider move up and down.
Notes
This layout works nicely for previews above supporting tools or metadata.
<div class="is-flex is-flex-direction-column" style="gap: 1rem;">
<div>
<p class="title is-6 mb-2">Horizontal</p>
<div style="height: 14rem;">
<SplitView Orientation="SplitViewOrientation.Horizontal" PrimaryPaneSize="38">
<Pane1>
<div style="padding: 1rem;">
<p class="mb-2"><strong>Navigation</strong></p>
<div class="content">
<p>The panes sit side by side for classic master-detail layouts.</p>
</div>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<p class="mb-2"><strong>Details</strong></p>
<div class="content">
<p>Horizontal mode is a good fit for desktops and wide work areas.</p>
</div>
</div>
</Pane2>
</SplitView>
</div>
</div>
<div>
<p class="title is-6 mb-2">Vertical</p>
<div style="height: 16rem;">
<SplitView Orientation="SplitViewOrientation.Vertical" PrimaryPaneSize="42">
<Pane1>
<div style="padding: 1rem;">
<p class="mb-2"><strong>Preview</strong></p>
<div class="content">
<p>Vertical mode stacks the panes and lets the divider move up and down.</p>
</div>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<p class="mb-2"><strong>Notes</strong></p>
<div class="content">
<p>This layout works nicely for previews above supporting tools or metadata.</p>
</div>
</div>
</Pane2>
</SplitView>
</div>
</div>
</div>
Mixed #
How to use:
- Place one SplitView inside the pane content of another SplitView.
- Give each nested area its own height by letting the parent pane fill the available space.
- Mix horizontal and vertical orientations to create the workspace shape you need.
Explorer
- Dashboard
- Reports
- Queries
- Settings
Editor
FROM Customers
WHERE IsActive = 1
ORDER BY Name;
Output
Nested SplitView layouts let you combine navigation, editing, diagnostics, and previews in a single reusable pattern.
<div style="height: 24rem;">
<SplitView Orientation="SplitViewOrientation.Horizontal" PrimaryPaneSize="26">
<Pane1>
<div style="padding: 1rem;">
<p class="title is-6 mb-3">Explorer</p>
<div class="content">
<ul>
<li>Dashboard</li>
<li>Reports</li>
<li>Queries</li>
<li>Settings</li>
</ul>
</div>
</div>
</Pane1>
<Pane2>
<SplitView Orientation="SplitViewOrientation.Vertical" PrimaryPaneSize="58">
<Pane1>
<div style="padding: 1rem;">
<p class="title is-6 mb-3">Editor</p>
<div class="box">
SELECT *
<br />
FROM Customers
<br />
WHERE IsActive = 1
<br />
ORDER BY Name;
</div>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<p class="title is-6 mb-3">Output</p>
<div class="content">
<p>Nested SplitView layouts let you combine navigation, editing, diagnostics, and previews in a single reusable pattern.</p>
</div>
</div>
</Pane2>
</SplitView>
</Pane2>
</SplitView>
</div>
Events #
How to use:
- Handle
OnResizeStartedwhen you want to note the beginning of user interaction. - Handle
OnResizedto update live indicators such as labels or measurements while dragging. - Handle
OnResizeEndedwhen you want to persist the final layout choice.
Current PrimaryPaneSize: 40%
Latest OnResized message: No resize yet.
Resizable Pane
Drag the divider and watch the current size plus the event messages update.
Event Summary
The move event updates the live percentage while the start and end events are recorded below.
<div class="mb-4">
<p class="mb-2">Current <code>PrimaryPaneSize</code>: <strong>@currentPrimaryPaneSize.ToString("0.##")%</strong></p>
<p class="mb-0">Latest <code>OnResized</code> message: <strong>@lastResizeMessage</strong></p>
</div>
<div style="height: 18rem;">
<SplitView PrimaryPaneSize="@currentPrimaryPaneSize"
OnResizeStarted="HandleResizeStarted"
OnResized="HandleResized"
OnResizeEnded="HandleResizeEnded">
<Pane1>
<div style="padding: 1rem;">
<p class="title is-6 mb-3">Resizable Pane</p>
<div class="content">
<p>Drag the divider and watch the current size plus the event messages update.</p>
</div>
</div>
</Pane1>
<Pane2>
<div style="padding: 1rem;">
<p class="title is-6 mb-3">Event Summary</p>
<div class="content">
<p>The move event updates the live percentage while the start and end events are recorded below.</p>
</div>
</div>
</Pane2>
</SplitView>
</div>
<div class="mt-5" style="max-height: 180px; overflow-y: auto;">
@foreach (var item in messages)
{
<p>Event: @item.Event, Message: @item.Message, UTC Time: @item.TimeStamp</p>
}
</div>
@code {
private double currentPrimaryPaneSize = 40;
private string lastResizeMessage = "No resize yet.";
private List<SplitViewMessage> messages = new();
private void HandleResized(SplitViewResizeEventArgs args)
{
currentPrimaryPaneSize = args.PrimaryPaneSize;
lastResizeMessage = $"Pane 1: {args.PrimaryPaneSize:0.##}%, Pane 2: {args.SecondaryPaneSize:0.##}%";
}
private void HandleResizeEnded(SplitViewResizeEventArgs args) =>
messages.Add(new("OnResizeEnded", $"Pane 1: {args.PrimaryPaneSize:0.##}%, Pane 2: {args.SecondaryPaneSize:0.##}%", DateTime.UtcNow));
private void HandleResizeStarted(SplitViewResizeEventArgs args) =>
messages.Add(new("OnResizeStarted", $"Pane 1: {args.PrimaryPaneSize:0.##}%, Pane 2: {args.SecondaryPaneSize:0.##}%", DateTime.UtcNow));
private record SplitViewMessage(string Event, string Message, DateTime TimeStamp);
}