Drag the panel's inner edge to resize it, or focus it and use the arrow keys. Double-click the edge, or press Enter on it, to go back to the default width.
A SidePanel slides in from the edge of the page over its content, for details or a form that belongs beside the page rather than in place of it. The user can resize it with a drag handle on its inner edge, as they resize the navigation, and double-click the handle to reset it. It docks to the right, the end of the page, by default; set Position (position) to Start (start) to dock it on the left. The grid buttons open their record form in one when their location is a side panel.
<Button onClick={() => setOpen(true)}>Details</Button>
<SidePanel
open={open}
onOpenChange={setOpen}
title="Details"
widthStorageKey="my-app.details-panel.width"
>
...
</SidePanel><FluentButton OnClick="@(() => _open = true)">Details</FluentButton>
<SidePanel @bind-Open="_open"
Title="Details"
WidthStorageKey="my-app.details-panel.width">
...
</SidePanel>Resizing is on by default; set EnableResizing (enableResizing in React) to false for a fixed width. DefaultWidth, MinWidth and MaxWidth set the starting width and how far the user can take it, and the panel is never wider than the viewport. Give WidthStorageKey a key of the panel's own and it reopens at the width the user left it, across page loads. On a phone the panel takes the whole width and has no handle.
{/* Starts at 560px, resizable between 400px and 900px, and remembered */}
<SidePanel
open={open}
onOpenChange={setOpen}
defaultWidth={560}
minWidth={400}
maxWidth={900}
widthStorageKey="my-app.editor-panel.width"
>
...
</SidePanel>
{/* A fixed width, with no handle */}
<SidePanel open={open} onOpenChange={setOpen} enableResizing={false}>
...
</SidePanel><!-- Starts at 560px, resizable between 400px and 900px, and remembered -->
<SidePanel @bind-Open="_open"
DefaultWidth="560"
MinWidth="400"
MaxWidth="900"
WidthStorageKey="my-app.editor-panel.width">
...
</SidePanel>
<!-- A fixed width, with no handle -->
<SidePanel @bind-Open="_open" EnableResizing="false">
...
</SidePanel>Title and FooterContent (title and footer in React) cover most panels. When the footer depends on state inside the content — a Save button enabled only once a form has changes — compose the panel instead: TitleTemplate and FooterContent in Blazor, and in React SidePanelHeader, SidePanelBody and SidePanelFooter, which can sit inside a context provider of your own.
<SidePanel open={open} onOpenChange={setOpen}>
<RecordContext table="contact" id={id}>
<SidePanelHeader>Details</SidePanelHeader>
<SidePanelBody>...</SidePanelBody>
<SidePanelFooter>
<SaveButton /> {/* reads the record context to know whether there is anything to save */}
</SidePanelFooter>
</RecordContext>
</SidePanel><SidePanel @bind-Open="_open">
<TitleTemplate>Details</TitleTemplate>
<ChildContent>...</ChildContent>
<FooterContent>
<FluentButton OnClick="@SaveAsync" Disabled="@(!_isDirty)">Save</FluentButton>
</FooterContent>
</SidePanel>Open the panel on either side and drag its inner edge to resize it, or focus the edge and use the arrow keys; double-click it, or press Enter on it, to reset it. It remembers its width, so close it, reload the page and open it again.
Drag the panel's inner edge to resize it, or focus it and use the arrow keys. Double-click the edge, or press Enter on it, to go back to the default width.
Name | Type | Default | Description |
|---|---|---|---|
ChildContent | RenderFragment? | The panel's content. | |
DefaultWidth | int | 400 | Width in px before the user resizes, and on double-click reset. Defaults to 400. |
EnableResizing | bool | True | When true (the default), a drag handle on the panel's edge facing the page lets the user resize it. Double-click the handle to reset it to SidePanel.DefaultWidth. There is no handle on a phone, where the panel takes the whole width. |
FooterContent | RenderFragment? | The panel's footer, typically its action buttons. | |
MaxWidth | int | 1200 | Widest the user can make the panel, in px. Defaults to 1200; never wider than the viewport. |
MinWidth | int | 320 | Narrowest the user can make the panel, in px. Defaults to 320. |
Modal | bool | True | Whether the panel is modal. Defaults to true. |
Open | bool | False | Whether the panel is open. Two-way bindable. |
Position | SidePanelPosition | End | Which edge of the page the panel docks to. Defaults to SidePanelPosition.End. |
PreventDismissOnEscape | bool | False | Whether pressing Escape is ignored instead of closing the panel. |
ShowDismiss | bool | True | Whether to show a dismiss (X) button in the title bar. Defaults to true. |
Title | string? | Plain-text title. Ignored when SidePanel.TitleTemplate is set. | |
TitleTemplate | RenderFragment? | Title content. | |
WidthStorageKey | string? | localStorage key the panel remembers its width under, so it reopens at the size the user left it. Leave unset to start at SidePanel.DefaultWidth every time. Give each kind of panel its own key so each remembers its own width. |
ChildContentDefaultWidthEnableResizingtrue (the default), a drag handle on the panel's edge facing the page lets the user resize it. Double-click the handle to reset it to SidePanel.DefaultWidth. There is no handle on a phone, where the panel takes the whole width.FooterContentMaxWidthMinWidthModaltrue.OpenPositionSidePanelPosition.End.PreventDismissOnEscapeShowDismisstrue.TitleSidePanel.TitleTemplate is set.TitleTemplateWidthStorageKeySidePanel.DefaultWidth every time. Give each kind of panel its own key so each remembers its own width.Name | Type | Description |
|---|---|---|
OnDismiss | EventCallback | Raised when the user closes the panel (Escape or the dismiss button), not when SidePanel.Open is set by the parent. |
OpenChanged | EventCallback<bool> | Raised with false when the user closes the panel. |
OnDismissSidePanel.Open is set by the parent.OpenChangedfalse when the user closes the panel.