Skip to content
# AppShell ## Description BitAppShell is the outermost element of an app. It insets the four edges of the screen by the device safe areas (notch, rounded corners, home indicator), makes room for the on-screen keyboard, and owns the one region the app scrolls in - so the header and footer stay put, only the middle moves, and a Modal, Panel, Dialog or Overlay inside it holds the right scroller on its own. That scroller can be driven from code, reports where it stands, pins to new content, keeps the reader's place across navigation and prints at full length. ## Parameters | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | AutoGoToTop | `bool` | false | Enables auto-scroll to the top of the main container on navigation. A navigation that only changes the fragment of the url (an in-page anchor) is left alone. PersistScroll takes precedence over it. | | AutoScroll | `bool` | false | Keeps the main container pinned to the end of its content as the content grows, for as long as the reader left it standing at the end. | | AutoScrollThreshold | `int` | 0 | How near the end of the content (in pixels) the main container has to have been left for AutoScroll to keep pinning it there. | | AvoidKeyboard | `bool` | false | Takes the height of the on-screen keyboard off the scrolling area while it is open, publishes it on the root as the --bit-ash-keyboard-inset CSS variable and marks the root with the data-bit-ash-keyboard attribute. A focused element the shorter middle leaves below its bottom edge is scrolled back into view. It measures 0 wherever the browser shrinks the layout viewport itself. | | ChildContent | `RenderFragment?` | null | The content of the app shell. It is rendered inside the main (scrolling) container. | | Classes | `BitAppShellClassStyles?` | null | Custom CSS classes for different parts of the app shell. | | FullScreen | `bool` | false | Pins the app shell to the four edges of the screen, so it fills the window whatever height the page around it has - which is what saves the host page from carrying a height of its own down through html and body. | | Gutter | `BitScrollbarGutter?` | null | Reserves the room the scrollbar of the main container takes, whether or not there is anything left to scroll, so the layout does not shift between a page that scrolls and a page that does not. | | NoBottomInset | `bool` | false | Removes the bottom safe area inset of the app shell, leaving the other three where they are. | | NoEndInset | `bool` | false | Removes the trailing side safe area inset of the app shell - the right of a left-to-right shell - leaving the other three where they are. | | NoInsets | `bool` | false | Removes the safe area insets, so the four edges of the app shell are not inset at all and the content fills the whole screen. | | NoScroll | `bool` | false | Prevents the reader from scrolling the main container at all; the content that overflows is clipped. The scrolling methods of the component still move it. | | NoStartInset | `bool` | false | Removes the leading side safe area inset of the app shell - the left of a left-to-right shell - leaving the other three where they are. | | NoTopInset | `bool` | false | Removes the top safe area inset of the app shell, leaving the other three where they are. | | OnKeyboardInsetChanged | `EventCallback<double>` | | Callback for how much of the app shell the on-screen keyboard covers, in pixels, raised as that changes and with 0 as it closes. Only a shell with AvoidKeyboard set measures it at all. | | OnReachedBottom | `EventCallback` | | Callback for when the main container reaches the bottom of its content, raised once per arrival rather than on every frame that stays there. | | OnReachedLeft | `EventCallback` | | Callback for when the main container reaches the visual left edge of its content, which is the same edge whichever way the shell reads. | | OnReachedRight | `EventCallback` | | Callback for when the main container reaches the visual right edge of its content. | | OnReachedTop | `EventCallback` | | Callback for when the main container reaches the top of its content. | | OnScroll | `EventCallback<BitScrollOffset>` | | Callback for the scroll position of the main container, raised as it is scrolled. Nothing is measured or reported until one of the scroll callbacks is handled. | | OnScrollEnd | `EventCallback<BitScrollOffset>` | | Callback for when a scroll of the main container comes to a stop. | | OnScrollStart | `EventCallback<BitScrollOffset>` | | Callback for when a scroll of the main container begins. | | OverflowX | `BitOverflow?` | null | What the main container does with content that overflows it sideways. Hidden clips it instead of offering it, and NoScroll wins over both axes. | | OverflowY | `BitOverflow?` | null | What the main container does with content that overflows it downwards. See OverflowX. | | Overscroll | `BitOverscroll?` | null | Determines what happens when the main container is scrolled past its edge. It defaults to None: no scroll chaining out of the shell and no pull-to-refresh or rubber-banding. | | PersistScroll | `bool` | false | Persists scroll position of the main container per url in session storage and restores it on navigation; another page with nothing stored opens at its top, while a navigation that only changes the query (a filter, a search box) or the fragment is left where it stands. One shell per page owns the store, so it is not part of BitAppShellParams. | | PreserveScroll | `bool` | false | Keeps the place of the reader when content is added above what they are looking at, which is what an endless list growing upwards needs. | | ReachOffset | `int` | 0 | How near an edge (in pixels) counts as having reached it, for OnReachedTop and OnReachedBottom. | | ScrollBehavior | `BitScrollBehavior?` | null | The scroll behavior of the main container, which decides how every move the reader does not make by hand is animated. It defaults to Smooth, and is taken back off under the reduced motion preference. | | ScrollPadding | `string?` | null | The room the main container keeps between its edges and anything scrolled into view inside it, as any CSS length - which is what keeps a header stuck to the top of the shell from covering what was just scrolled to. | | ScrollRestoration | `BitAppShellScrollRestoration` | BitAppShellScrollRestoration.Url | Which navigations PersistScroll restores: Url restores every navigation to a url left scrolled (app tabs); History only the back and forward buttons, opening every other navigation at its top as a browser does. | | ScrollThrottle | `int` | 0 | The shortest interval (in milliseconds) between two OnScroll reports. The default of 0 reports once per animation frame. | | StableInsets | `bool` | false | Sizes the four inset bars from the largest safe areas the device can ask for rather than from the ones it is asking for right now, so the layout is not relaid out as the browser slides its own chrome in and out. | | Styles | `BitAppShellClassStyles?` | null | Custom CSS styles for different parts of the app shell. | | TrackScrollState | `bool` | false | Marks the root with data-bit-ash-scrolled while the main container is away from its top, and with data-bit-ash-scroll-direction (up or down) for the way it was last scrolled, so a header can lift or hide itself in CSS alone. | | ValueList | `BitCascadingValueList?` | null | The cascading value list to be provided for the children of the app shell. Its values are provided before (so they can be overridden by) the ones of the Values parameter. | | Values | `IEnumerable<BitCascadingValue>?` | null | The cascading values to be provided for the children of the app shell. | | 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 | | :--- | :--- | :------------ | :---------- | | ClearPersistedScroll | `Func<string?, Task>` | | Forgets every scroll position PersistScroll has kept, for the pages of this app shell and of any other - or, given a url, only the position kept for that one page. | | Container | `const string` | "BitAppShell.Container" | The name the app shell cascades the element of its main container under, which is what a Modal, a Panel, a Dialog or an Overlay inside the shell reads to hold the right scroller. | | ContainerId | `const string` | "BitAppShell-container" | The id the main container carries when the app shell has no Id of its own. | | ContainerRef | `ElementReference?` | null | The element reference to the main container of the app shell. | | GetScrollOffset | `Func<Task<BitScrollOffset?>>` | | Reads where the main container currently stands, measured in the browser. | | GoToBottom | `Func<BitScrollBehavior?, Task>` | | Scrolls the main container to the bottom of its content. | | GoToTop | `Func<BitScrollBehavior?, Task>` | | Scrolls the main container to top. | | MainContainerId | `string` | | The id of the main container element of this app shell: ContainerId, or the Id of the shell with "-container" after it. | | Refresh | `Func<Task>` | | Re-measures the main container and reports whatever has changed since it was last measured - for the changes neither its own size nor its content announce, such as a web font that has finished loading. | | ScrollBy | `Func<double, double, BitScrollBehavior?, Task>` | | Scrolls the main container by an amount, from wherever it currently stands. | | ScrollTo | `Func<double?, double?, BitScrollBehavior?, Task>` | | Scrolls the main container to a position. A null axis is left where it stands. | | ScrollToElement | `Func<string, double, bool, BitScrollAlignment, BitScrollBehavior?, Task>` | | Brings an element inside the main container into view by scrolling the container itself rather than every scroller the page sits in. | | 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 ### BitScrollBehavior Enum | Name | Value | Description | | :--- | :--- | :---------- | | Smooth | 0 | Scrolling should animate smoothly. | | Instant | 1 | Scrolling should happen instantly in a single jump. | | Auto | 2 | Scroll behavior is determined by the computed value of scroll-behavior. | ### BitAppShellScrollRestoration Enum | Name | Value | Description | | :--- | :--- | :---------- | | Url | 0 | Every navigation to a url that was left scrolled is restored, however it was navigated to - the tabs of a mobile app, each keeping its own place. | | History | 1 | Only the browser's back and forward navigations are restored; every other navigation opens the page at its top, as a browser does. | ### BitOverflow Enum | Name | Value | Description | | :--- | :--- | :---------- | | Auto | 0 | A scrollbar is offered along that axis when the content overflows, and nothing is shown when it does not. | | Hidden | 1 | The overflow is clipped and no scrollbar is offered, though the axis can still be moved through the scrolling methods of the component. | | Scroll | 2 | A scrollbar is always shown along that axis, whether or not there is anything to scroll. | | Visible | 3 | The overflow is neither clipped nor scrollable, so it is painted outside the container. | ### BitScrollbarGutter Enum | Name | Value | Description | | :--- | :--- | :---------- | | Auto | 0 | The initial value: a classic scrollbar takes its room only while there is something to scroll, and an overlay scrollbar takes none at all. | | Stable | 1 | The room is reserved whether or not there is anything to scroll, so the layout does not shift as pages of different lengths follow one another. | | BothEdges | 2 | Like Stable, with the same room reserved on the opposite edge as well, so the content stays centered. | ### BitOverscroll Enum | Name | Value | Description | | :--- | :--- | :---------- | | Auto | 0 | The scroll carries on into the nearest scrolling ancestor, and the platform's own overscroll affordance is kept. | | Contain | 1 | The scroll stops at the edge instead of carrying on into the page behind it, while the platform's own overscroll affordance is kept. | | None | 2 | Like Contain, and the platform's own overscroll affordance is suppressed as well, so the container neither bounces nor triggers a pull to refresh. | ### BitScrollAlignment Enum | Name | Value | Description | | :--- | :--- | :---------- | | Start | 0 | The element is brought to the start of the container. | | Center | 1 | The element is centered in the container along both axes. | | End | 2 | The element is brought to the end of the container. | | Nearest | 3 | The container moves as little as it can. | ### 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 ### BitCascadingValueList Properties A List<BitCascadingValue> with typed helpers for building and revising a set of cascading values; its collection initializer takes { value, name } pairs. These are the members the shell's ValueList is usually built with; the BitCascadingValueProvider page documents all of them. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Add<T>(T value, string? name = null, bool isFixed = false, bool enabled = true) | `void` | | Adds a typed BitCascadingValue to the list, cascading the value as the static type of T. | | Add(BitCascadingValue? value) | `void` | | Adds an already created BitCascadingValue to the list. A null item is ignored. | | Set<T>(T value, string? name = null, bool isFixed = false, bool enabled = true) | `void` | | Replaces every entry of the static type of T and the given name with one new entry, in the place of the first, or appends it when there is none. | ### BitCascadingValue Properties One value to cascade: what is cascaded, as which type, under which name, and whether it is fixed or provided at all. Bare values and (value, name) tuples of the common primitive, date, string and BitDir types convert to it implicitly. These are the members the shell's Values are usually built with; the BitCascadingValueProvider page documents all of them, including the factories and the typed BitCascadingValue<T>. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Value | `object?` | null | The value to be provided. Assigning a value not assignable to ValueType throws an ArgumentException; assigning a different value refreshes the consumers. | | Name | `string?` | null | The optional name of the cascading value, matched case-insensitively; an empty or white-space name means no name. | | IsFixed | `bool` | false | Marks a value that never changes, so its consumers are not subscribed for change notifications. | | Enabled | `bool` | true | Whether the value is provided at all. A disabled value is skipped as if it had never been added, so an outer or root-level value of the same type and name shows through. | ### BitAppShellClassStyles Properties | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Root | `string?` | null | Custom CSS classes/styles for the root of the BitAppShell. | | Top | `string?` | null | Custom CSS classes/styles for the top inset bar of the BitAppShell. | | Center | `string?` | null | Custom CSS classes/styles for the center row of the BitAppShell, which holds the two side inset bars and the main container. | | Left | `string?` | null | Custom CSS classes/styles for the leading side inset bar of the BitAppShell. | | Main | `string?` | null | Custom CSS classes/styles for the main (scrolling) container of the BitAppShell. | | Right | `string?` | null | Custom CSS classes/styles for the trailing side inset bar of the BitAppShell. | | Bottom | `string?` | null | Custom CSS classes/styles for the bottom inset bar of the BitAppShell. | ### BitScrollOffset Properties Where the main container of the app shell stands, as measured in the browser. Everything is in CSS pixels; the members derived from the measured ones cost nothing to read. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Left | `double` | 0 | The raw scrollLeft of the container. | | Top | `double` | 0 | How far the content has been scrolled down. | | ScrollWidth | `double` | 0 | The full width of the content, including the part scrolled out of sight. | | ScrollHeight | `double` | 0 | The full height of the content, including the part scrolled out of sight. | | ClientWidth | `double` | 0 | The width of the visible area, without its scrollbar. | | ClientHeight | `double` | 0 | The height of the visible area, without its scrollbar. | | Rtl | `bool` | false | Whether the container was laid out right to left when it was measured. | | DeltaLeft / DeltaTop | `double` | 0 | How far the container has moved since the position before this one was reported. Only the OnScroll reports carry them. | | OffsetLeft | `double` | | The distance from the visual left edge, which is Left made positive and direction independent. | | MaxLeft / MaxTop | `double` | | The largest offset each axis can reach, which is how much of the content is out of sight. | | ScrollableX / ScrollableY | `bool` | | Whether there is anything to scroll along each axis at all. | | AtLeft / AtRight / AtTop / AtBottom | `bool` | | Whether the container is standing at each edge, within a pixel of slack. | | PercentX / PercentY | `double` | | How far the container has been scrolled along each axis, from 0 to 1. | | ScrollingUp / ScrollingDown / ScrollingLeft / ScrollingRight | `bool` | | Which way the move this report carries went, derived from the deltas - which is what a header that folds away on the way down reads. | ## 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-AppShell-background` | var(--bit-clr-bg-pri) | Background of the shell, and of the four inset bars unless they are given their own. | | `--bit-AppShell-color` | var(--bit-clr-fg-pri) | Text color the content inherits, paired with the background. Set it to inherit to keep the host page's own. | | `--bit-AppShell-inset-background` | --bit-AppShell-background | Background of the four inset bars. | | `--bit-AppShell-inset-top-background` | --bit-AppShell-inset-background | Background of the top bar, behind the status bar - commonly the color of the header below it. | | `--bit-AppShell-inset-bottom-background` | --bit-AppShell-inset-background | Background of the bottom bar, behind the home indicator. | | `--bit-AppShell-inset-start-background` | --bit-AppShell-inset-background | Background of the leading side bar (left in LTR, right in RTL). | | `--bit-AppShell-inset-end-background` | --bit-AppShell-inset-background | Background of the trailing side bar (right in LTR, left in RTL). | | `--bit-AppShell-safe-area-top` | env(safe-area-inset-top) | How far the top edge is inset. Set it to map the insets a native host measured, or to keep a minimum with max(). StableInsets defaults it to the device maximum; NoInsets and NoTopInset win over it. | | `--bit-AppShell-safe-area-bottom` | env(safe-area-inset-bottom) | How far the bottom edge is inset. NoInsets and NoBottomInset win over it. | | `--bit-AppShell-safe-area-start` | the inline-start env() inset | How far the leading edge is inset. NoInsets and NoStartInset win over it. | | `--bit-AppShell-safe-area-end` | the inline-end env() inset | How far the trailing edge is inset. NoInsets and NoEndInset win over it. | ## Examples \n**Basic**: ```razor
Header
@foreach (var i in Enumerable.Range(1, 12)) {
Row @i
}
``` \n**Safe area insets**: ```razor @* The safe-area variables inherit, so any element around the shell can set them. *@
@foreach (var i in Enumerable.Range(1, 12)) {
Row @i
}
``` ```csharp private bool noInsets; private bool noTopInset; private bool noEndInset; private bool noStartInset; private bool noBottomInset; // Desktop browsers report no safe areas, so the shell is handed the ones a phone would report // (which the No*Inset flags still take back to zero), and the bars are painted to be seen. private const string deviceInsets = "--bit-AppShell-safe-area-top:1.5rem;--bit-AppShell-safe-area-bottom:1.5rem;" + "--bit-AppShell-safe-area-start:1rem;--bit-AppShell-safe-area-end:1rem;" + "--bit-AppShell-inset-background:var(--bit-clr-pri)"; ``` \n**Keyboard inset**: ```razor
Keyboard inset: @keyboardInset.ToString("0") px
@foreach (var i in Enumerable.Range(1, 10)) {
Row @i
}
@* Stuck to the bottom of the scrolling middle, whose height AvoidKeyboard shortens - so the composer rides up with the keyboard instead of disappearing behind it. *@
Send
``` ```csharp private string? message; private double keyboardInset; private void HandleKeyboardInset(double inset) { keyboardInset = inset; StateHasChanged(); } // .composer { position: sticky; bottom: 0; } // // Chrome placed OUTSIDE the shell reads the same measurement: // .fab { bottom: calc(var(--bit-ash-keyboard-inset) + 1rem); } // and chrome that hides while the reader types is styled against the attribute: // .bit-ash[data-bit-ash-keyboard] .tab-bar { display: none; } ``` \n**Scrolling from code**: ```razor GoToTop GoToBottom ScrollTo(240) ScrollBy(+120) ScrollToElement GetScrollOffset
@offsetText
@foreach (var i in Enumerable.Range(1, 30)) {
Row @i @(i == 20 ? "(the ScrollToElement target)" : null)
}
``` ```csharp private bool instantScroll; private BitAppShell? scrollShell; private string offsetText = "-"; private Task ScrollToTarget() => scrollShell?.ScrollToElement("target-row") ?? Task.CompletedTask; private async Task ReadOffset() { var offset = await (scrollShell?.GetScrollOffset() ?? Task.FromResult(null)); offsetText = offset is null ? "-" : $"Top {offset.Top:0} of {offset.MaxTop:0} ({offset.PercentY * 100:0}%), AtTop: {offset.AtTop}, AtBottom: {offset.AtBottom}"; } ``` \n**Scroll events & state**: ```razor
Top: @scrollTop.ToString("0") px (@((scrollPercent * 100).ToString("0"))%)
Direction: @scrollDirection
Phase: @scrollPhase
Reached: @reachedEdge
Header
@foreach (var i in Enumerable.Range(1, 40)) {
Row @i
}
``` ```csharp private double scrollTop; private double scrollPercent; private string scrollPhase = "idle"; private string reachedEdge = "-"; private string scrollDirection = "-"; private void HandleScroll(BitScrollOffset offset) { scrollTop = offset.Top; scrollPercent = offset.PercentY; scrollDirection = offset.ScrollingDown ? "down" : offset.ScrollingUp ? "up" : "-"; StateHasChanged(); } private void HandleScrollStart() { scrollPhase = "scrolling"; StateHasChanged(); } private void HandleScrollEnd() { scrollPhase = "idle"; StateHasChanged(); } private void HandleReachedTop() { reachedEdge = "top"; StateHasChanged(); } private void HandleReachedBottom() { reachedEdge = "bottom"; StateHasChanged(); } ``` \n**Overflow & overscroll**: ```razor ScrollBy(+80)
A row wider than the shell
@foreach (var i in Enumerable.Range(1, shortOverflowPage ? 1 : 20)) {
Row @i
}
``` ```csharp private bool noScroll; private bool stableGutter; private bool clipOverflowX; private bool shortOverflowPage; private BitAppShell? overflowShell; private BitOverscroll overscroll = BitOverscroll.None; ``` \n**Scroll padding**: ```razor ScrollToElement(row 15) GoToTop
@* Stuck to the top of the scrolling middle, which is what the padding leaves room for. *@
A sticky header
@foreach (var i in Enumerable.Range(1, 30)) {
Row @i @(i == 15 ? "(the target)" : null)
}
``` ```csharp private bool stickyPadding; private BitAppShell? paddingShell; private string? paddingValue => stickyPadding ? "2.5rem 0 0 0" : null; private Task ScrollToPaddedRow() => paddingShell?.ScrollToElement("padded-row") ?? Task.CompletedTask; ``` \n**Endless content**: ```razor Append to the end Prepend 5 older Refresh
@foreach (var message in feed) {
@message
}
``` ```csharp private bool autoScroll = true; private bool preserveScroll = true; private int feedNext = 13; private int feedOlder; private BitAppShell? feedShell; private readonly List feed = [.. Enumerable.Range(1, 12).Select(i => $"Message {i}")]; private void AppendMessage() => feed.Add($"Message {feedNext++}"); // Older content lands ABOVE what the reader is looking at, which is the arrival PreserveScroll is for. private void PrependMessages() { for (var i = 0; i < 5; i++) { feed.Insert(0, $"Older message {--feedOlder}"); } } ``` \n**Navigation**: ```razor @* MainLayout.razor - the app shell wraps everything the application renders. *@
@Body
@code { private BitAppShell? appShell; // Back and forward put the reader back where they left a page; a link opens it at its top. // Leave ScrollRestoration out to restore every navigation to a page, like the tabs of an app. // Or use AutoGoToTop instead to open every page at its top: // // On sign-out, forget where the previous user was left in each page: private Task SignOut() => appShell?.ClearPersistedScroll() ?? Task.CompletedTask; } ``` \n**Cascading values**: ```razor Change the cascaded name @* AppShellDemoConsumer.razor - anywhere below the shell, however deep. *@
Cascaded by type: @User?.Name (@User?.Role)
Cascaded by name: @Tenant
@code { [CascadingParameter] public AppShellDemoUser? User { get; set; } [CascadingParameter(Name = "Tenant")] public string? Tenant { get; set; } } ``` ```csharp public record AppShellDemoUser(string Name, string Role); private string userName = "Saleh Yusefnejad"; private IEnumerable cascadingValues => [ new(new AppShellDemoUser(userName, "Developer")), new("bit platform", "Tenant"), ]; private void RenameUser() { userName = userName == "Saleh Yusefnejad" ? "Yaser Moradi" : "Saleh Yusefnejad"; } ``` \n**Cascading parameters**: ```razor @* The bars are given a size around both shells, so the inset each one keeps can be seen on a desktop. *@
All cascaded
Own NoBottomInset
``` ```csharp private readonly BitAppShellParams[] appShellParams = [ new() { NoBottomInset = true } ]; ``` \n**Style & Class**: ```razor
@foreach (var i in Enumerable.Range(1, 12)) {
Row @i
}
``` ```csharp private readonly BitAppShellClassStyles shellStyles = new() { Root = "border-radius:0.5rem;overflow:hidden", Top = "height:0.5rem;background:#3a9b3a", Bottom = "height:0.5rem;background:#3a9b3a", Main = "padding:0.75rem", }; private readonly BitAppShellClassStyles shellClasses = new() { Main = "styled-main", }; ``` \n**RTL**: ```razor
@foreach (var i in Enumerable.Range(1, 12)) {
سطر @i
}
``` ```csharp // Desktop browsers report no safe areas, so the shell is handed the ones a phone would report // (which the No*Inset flags still take back to zero), and the bars are painted to be seen. private const string deviceInsets = "--bit-AppShell-safe-area-top:1.5rem;--bit-AppShell-safe-area-bottom:1.5rem;" + "--bit-AppShell-safe-area-start:1rem;--bit-AppShell-safe-area-end:1rem;" + "--bit-AppShell-inset-background:var(--bit-clr-pri)"; // The start bar is wider and of its own color, so the side it lands on can be seen. private const string rtlInsets = $"{deviceInsets};--bit-AppShell-safe-area-start:2rem;--bit-AppShell-inset-start-background:var(--bit-clr-sec)"; ```