# Panel
## Description
Panel is an overlay surface that slides in from any edge of the screen to host supplementary content - a form, a filter, a set of details, a navigation menu - without taking the user away from the page behind it. It comes with an optional header, scrolling body and footer, dims or leaves the page usable, locks the page scroll, traps and restores the focus, and is dismissed by the overlay, the Escape key, a swipe or a close button - each of which can be refused.
## Parameters
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| AbsolutePosition | `bool` | false | Lays the panel and its overlay out against the nearest positioned ancestor instead of the screen. The page scroll is then left alone; a named scroller is still locked. |
| AutoToggleScroll | `bool` | false | Toggles the overflow of the scroller while the panel is open, instead of taking the scroll lock. An AbsolutePosition panel is pushed down by the room the scrollbar gave back. |
| Blocking | `bool` | false | Keeps a click on the overlay from dismissing the panel. Escape and the swipe are controlled by NoDismissOnEscape and NoSwipe. |
| Body | `RenderFragment?` | null | Alias of ChildContent, named for the scrolling body between the header and the footer. |
| ChildContent | `RenderFragment?` | null | The content of the panel. |
| Classes | `BitPanelClassStyles?` | null | Custom CSS classes for different parts of the panel. |
| CloseButtonTitle | `string?` | null | The accessible name and tooltip of the close button. Defaults to "Close". |
| CloseIcon | `BitIconInfo?` | null | The icon of the close button from an external icon library, given as its CSS classes. Takes precedence over CloseIconName. |
| CloseIconName | `string?` | null | The name of the built-in Fluent UI icon of the close button. Defaults to Cancel. |
| Footer | `RenderFragment?` | null | The footer of the panel, fixed at its far edge while the body scrolls. |
| FooterText | `string?` | null | A plain-text footer. Footer takes precedence over it. |
| FullSize | `bool` | false | Stretches the panel over the whole screen, overriding Size and the size cap. |
| Header | `RenderFragment?` | null | The header of the panel, fixed at the edge it slides in from while the body scrolls. It names the panel for screen readers unless TitleAriaId or AriaLabel is set. |
| HeaderText | `string?` | null | A plain-text header, rendered as a level-2 heading. Header takes precedence over it. |
| IsAlert | `bool` | false | Reports the panel as an alertdialog instead of a dialog, for urgent content the user has to deal with. |
| IsOpen | `bool` | false | Whether the panel is open. Two-way bindable: the panel writes it back when it dismisses itself. |
| KeepMounted | `bool` | false | Keeps the content in the page after the first opening, hidden while closed, so its state survives a close. Nothing is rendered before the first opening either way. |
| ModeFull | `bool` | false | Gives the overlay a background that dims the page. |
| Modeless | `bool` | false | Renders no overlay, so the page stays usable. A modeless panel is not reported as modal, does not trap the focus and does not lock the scroll. |
| NoAutoFocus | `bool` | false | Leaves the focus where it is when the panel opens. Otherwise the element marked data-autofocus, or the first focusable one, takes it. |
| NoDismissOnEscape | `bool` | false | Keeps the Escape key from dismissing the panel. OnEscapeKeyDown still fires. An Escape that closes a popup inside the panel (an open dropdown list) never reaches the panel either way. |
| NoFocusTrap | `bool` | false | Lets Tab leave the open panel. A Modeless panel never traps the focus. |
| NoRestoreFocus | `bool` | false | Leaves the focus where it is when the panel closes, instead of returning it to the element that had it before the panel opened. |
| NoScrollLock | `bool` | false | Leaves the page scrolling while the panel is open. Wheel and touch gestures on the overlay are forwarded to the named or app-shell scroller. |
| NoSwipe | `bool` | false | Turns off the swipe gesture that dismisses the panel. To keep it but exempt one region (a canvas, a sideways-scrolling table), mark that region data-no-swipe instead; fields and mouse text selection are always exempt. |
| OnDismiss | `EventCallback<MouseEventArgs>` | | Fires whenever the panel closes: close button, overlay, Escape, swipe, Close/Toggle, or IsOpen set to false from outside. Carries the click where there was one. |
| OnDismissing | `EventCallback<BitPanelDismissArgs>` | | Fires before the panel closes itself; set Cancel to keep it open, and read Reason to tell the closings apart. Not raised when IsOpen is set to false from outside. |
| OnEscapeKeyDown | `EventCallback<KeyboardEventArgs>` | | Fires for every Escape pressed inside the open panel, including the ones NoDismissOnEscape refuses - but not for one that closes a popup inside it. |
| OnOpen | `EventCallback` | | Fires when the panel opens. |
| OnOverlayClick | `EventCallback<MouseEventArgs>` | | Fires for a click on the overlay, before the panel is dismissed - and for a Blocking panel too. |
| OnSwipeStart | `EventCallback<decimal>` | | Fires when a swipe starts on the panel, with the start coordinate along its axis. |
| OnSwipeMove | `EventCallback<decimal>` | | Fires while a swipe moves, with the distance along the panel's axis. |
| OnSwipeEnd | `EventCallback<decimal>` | | Fires when a swipe ends, with the distance along the panel's axis. |
| OnToggle | `EventCallback<bool>` | | Fires when the panel opens or closes, with the new state. |
| OnTransitionEnd | `EventCallback<bool>` | | Fires once the panel has finished sliding in or out, with the state it settled in. The other callbacks fire at the start of the movement. |
| Placement | `BitPlacement?` | null | The edge the panel slides in from; Start and End follow the text direction, Left and Right stay where they are named in both. Center and the two combined values fall back to End. Defaults to End. |
| Role | `string?` | null | Replaces the dialog (or alertdialog) role, e.g. complementary or region for a Modeless panel beside the page. |
| ScrollerElement | `ElementReference?` | null | The scroller to lock while the panel is open, when no selector can reach it. Takes precedence over ScrollerSelector and the BitAppShell scroller. |
| ScrollerSelector | `string?` | null | The CSS selector of the scroller to lock while the panel is open. Defaults to the BitAppShell scroller, or the page. |
| ShowCloseButton | `bool` | false | Shows a close button at the end of the header row. |
| Size | `double?` | null | The size in pixels along the axis the panel slides on (the width at Start/End/Left/Right, the height at Top/Bottom). Unset, the panel fits its content; other units go through --bit-Panel-size or Styles.Container. |
| Styles | `BitPanelClassStyles?` | null | Custom CSS styles for different parts of the panel. |
| SubtitleAriaId | `string?` | null | The id of the element that describes the panel (aria-describedby). |
| SwipeTrigger | `decimal?` | null | How far the panel has to be dragged to be dismissed, as a fraction of its size (0 to 1, default 0.25). |
| TitleAriaId | `string?` | null | The id of the element that names the panel (aria-labelledby). Defaults to the header; AriaLabel takes precedence. |
| ZIndex | `int?` | null | The layer of the overlay; the panel sits one above it. A panel declared inside another needs none; this lifts one over a sibling panel or page chrome. |
| 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. An attribute written on the component wins over an entry of the same name. |
| 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. |
## Public Members
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Open | `Task` | | Opens the panel, unless it is disabled. |
| Close | `Task` | | Closes the panel, unless OnDismissing refuses it. |
| Toggle | `Task` | | Opens the panel when it is closed, and closes it when it is open. |
| 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. |
## Enums
### BitPlacement Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Top | 0 | The top edge. |
| Bottom | 1 | The bottom edge. |
| Start | 2 | The edge the reading direction starts from - the left in LTR, the right in RTL. On the vertical axis, which does not turn around, it is the top. |
| End | 3 | The edge the reading direction ends at - the right in LTR, the left in RTL. On the vertical axis, which does not turn around, it is the bottom. |
| Left | 4 | The left edge, in both reading directions. |
| Right | 5 | The right edge, in both reading directions. |
| Center | 6 | The middle of the axis, against neither edge. |
| TopAndBottom | 7 | Both edges of the block axis at once. |
| StartAndEnd | 8 | Both edges of the inline axis at once, following the reading direction the way Start and End do. |
### BitPanelDismissReason Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Programmatic | 0 | The Close or Toggle method. |
| Overlay | 1 | A click on the overlay. |
| Escape | 2 | The Escape key. |
| Swipe | 3 | A swipe towards the edge the panel slid in from. |
| CloseButton | 4 | The close button in the header. |
### 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. |
## Sub Classes
### BitPanelClassStyles Properties
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Root | `string?` | null | Custom CSS classes/styles for the root element of the BitPanel. |
| Overlay | `string?` | null | Custom CSS classes/styles for the overlay of the BitPanel. |
| Container | `string?` | null | Custom CSS classes/styles for the container of the BitPanel, which is the panel surface itself. |
| HeaderContainer | `string?` | null | Custom CSS classes/styles for the header row of the BitPanel, which holds the header beside the close button. |
| Header | `string?` | null | Custom CSS classes/styles for the header of the BitPanel. |
| CloseButton | `string?` | null | Custom CSS classes/styles for the close button of the BitPanel. |
| CloseIcon | `string?` | null | Custom CSS classes/styles for the icon of the close button of the BitPanel. |
| Body | `string?` | null | Custom CSS classes/styles for the body of the BitPanel, which scrolls between the header and the footer. |
| Footer | `string?` | null | Custom CSS classes/styles for the footer of the BitPanel. |
### BitPanelDismissArgs Properties
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Reason | `BitPanelDismissReason` | | What is closing the panel. |
| Mouse | `MouseEventArgs?` | null | The click that is closing the panel, for a dismissal that came from a pointer. |
| Cancel | `bool` | false | Set to true to refuse the dismissal and keep the panel open. |
## CSS Variables
Public CSS custom properties read off the component's root. Set one on `:root` to restyle every instance, on any ancestor to restyle the ones inside it, or on the `Style` of one instance to restyle it and every instance nested inside it, which inherits the value too - a parameter changes one alone, as does the real CSS property on its `Style` / `Styles` when that property does not inherit (`opacity`); an inherited one (`color`, `font-family`) reaches the nested instances that do not set it themselves.
| Name | Default Value | Description |
| :--- | :------------ | :---------- |
| `--bit-Panel-background` | --bit-clr-bg-pri | Fill of the panel. |
| `--bit-Panel-color` | --bit-clr-fg-pri | Text color of the panel and its close button. |
| `--bit-Panel-shadow` | --bit-shd-sheet | Elevation of the panel. |
| `--bit-Panel-radius` | --bit-shp-radius-sheet | Radius of the two corners the panel turns towards the page. FullSize panels stay square. |
| `--bit-Panel-border-width` | 0 | Width of the rule along the edge the panel turns towards the page. |
| `--bit-Panel-border-color` | --bit-clr-brd-sec | Color of that rule. |
| `--bit-Panel-size` | fit-content | Size along the axis the panel slides on, in any CSS unit. The Size parameter wins. |
| `--bit-Panel-max-size` | 85% | Cap of that size, which keeps a strip of the page visible. FullSize lifts it. |
| `--bit-Panel-z-index` | --bit-zin-overlay | Layer of the overlay; the panel sits one above it. The ZIndex parameter wins. |
| `--bit-Panel-overlay-background` | --bit-clr-bg-overlay | Fill of the overlay of a ModeFull panel. |
| `--bit-Panel-overlay-backdrop-filter` | none | Filter applied to the page behind the overlay, e.g. blur(4px). |
| `--bit-Panel-padding` | --bit-spa-dialog | Inset of the header, the body and the footer. |
| `--bit-Panel-header-font-size` | --bit-tpg-fs-xl | Text size of the header. |
| `--bit-Panel-header-font-weight` | --bit-tpg-fw-semibold | Weight of the header. |
## Examples
\n**Basic**:
```razor
Open panel
Toggle panel
Close
```
```csharp
private bool isBasicPanelOpen;
private BitPanel basicPanelRef = default!;
```
\n**Header and footer**:
```razor
HeaderText & FooterText
Header, Body & Footer
You have no new notifications.
@for (var i = 1; i <= 30; i++)
{
var index = i;
}
```
```csharp
private bool isHeaderTextPanelOpen;
private bool isTemplatePanelOpen;
```
\n**Placement and size**:
```razor
Open panel
Size: @(panelFullSize ? "FullSize" : $"{panelSize}px")
```
```csharp
private BitPlacement panelPosition = BitPlacement.End;
private double panelSize = 300;
private bool panelFullSize;
private bool isPositionPanelOpen;
```
\n**Overlay and dismissal**:
```razor
Open panel
```
```csharp
private bool overlayModeFull;
private bool overlayBlocking;
private bool overlayNoEscape;
private bool overlayModeless;
private int overlayClickCount;
private int escapeKeyCount;
private int dismissCount;
private bool isOverlayPanelOpen;
private readonly List> dismissalItems =
[
new() { Text = "A", Value = "A" },
new() { Text = "B", Value = "B" },
new() { Text = "C", Value = "C" },
];
```
\n**Refusing a dismissal**:
```razor
Open panel
```
```csharp
private bool guardPanel = true;
private bool guardedRefused;
private BitPanelDismissReason? guardedReason;
private bool isGuardedPanelOpen;
private BitPanel guardedPanelRef = default!;
// The gestures that could be a slip are refused; the close button and the panel's own Save go through.
private void HandleOnDismissing(BitPanelDismissArgs args)
{
guardedReason = args.Reason;
args.Cancel = guardPanel && args.Reason is BitPanelDismissReason.Overlay
or BitPanelDismissReason.Escape
or BitPanelDismissReason.Swipe;
guardedRefused = args.Cancel;
}
```
\n**Accessibility**:
```razor
Open panel
Close
```
```csharp
private bool a11yNoAutoFocus;
private bool a11yNoFocusTrap;
private bool a11yNoRestoreFocus;
private bool a11yIsAlert;
private bool isA11yPanelOpen;
```
\n**Page scrolling**:
```razor
Open panel
Try scrolling the page behind this panel.
```
```csharp
private string scrollMode = "Lock";
private bool isScrollPanelOpen;
```
\n**Swipe to dismiss**:
```razor
Open panel
```
```csharp
private double swipeTrigger = 0.25;
private bool noSwipe;
private decimal swipeStart;
private decimal swipeDiff;
private bool isSwipePanelOpen;
```
\n**Nested panels**:
```razor
Open outer panel
Open nested panel
Open sibling panel
Declared inside the outer panel, so it covers it without a ZIndex.
Declared beside the outer panel and lifted over it by ZIndex.
```
```csharp
private bool isOuterPanelOpen;
private bool isInnerPanelOpen;
private bool isSiblingPanelOpen;
```
\n**Inside a container**:
```razor
Open panel
Contained by its box.
```
```csharp
private bool isAbsolutePanelOpen;
```
\n**Rendering and events**:
```razor
Open panel
```
```csharp
private bool keepMounted;
private int openCount;
private bool lastToggleState;
private bool lastSettledState;
private bool isRenderPanelOpen;
```
\n**Cascading parameters**:
```razor
Cascaded values
Own Placement
Start edge, 320px, dimmed page and a close button - none of it set on this panel.
Slides in from the end, everything else from the cascade.
```
```csharp
private readonly BitPanelParams[] panelParams =
[
new()
{
Placement = BitPlacement.Start,
Size = 320,
ModeFull = true,
ShowCloseButton = true,
}
];
private bool isCascadedPanelOpen;
private bool isOverridingPanelOpen;
```
\n**External Icons**:
```razor
CloseIcon
CloseIconName
The close button is drawn by FontAwesome.
The close button uses another built-in icon.
```
```csharp
private bool isExternalIconPanelOpen;
private bool isIconNamePanelOpen;
```
\n**Style & Class**:
```razor
Styles
Classes
CSS variables
A 30vw panel, set through the Container.
Every part carries a class of its own.
Rounded inner corners, a primary edge, roomier padding and a darker, blurring overlay.
```
```csharp
private bool isStylesPanelOpen;
private bool isClassesPanelOpen;
private bool isCssVarsPanelOpen;
```
\n**RTL**:
```razor
آغاز
پایان
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.
```
```csharp
private bool isRtlPanelOpenStart;
private bool isRtlPanelOpenEnd;
```
Basic
Once upon a time, stories wove connections between people, a symphony of voices crafting
shared dreams. Each word carried meaning, each pause brought understanding.
Filters
Overlay clicks: @overlayClickCount, Escape presses: @escapeKeyCount, dismissals: @dismissCount
Click the page behind this panel or press Escape.
Last attempt: @(guardedReason?.ToString() ?? "-"), refused: @guardedRefused
Edit profile
The second field takes the focus, since it is marked data-autofocus.
Start: @swipeStart
Diff: @swipeDiff
Dragging here does not move the panel (data-no-swipe).
The panel opens inside this box.
Opened @openCount times, last toggled to @lastToggleState, settled at @lastSettledState