Skip to content
# ScrollablePane **Also known as:** ScrollView, ScrollArea, ScrollViewer ## Description ScrollablePane is a box that scrolls whatever is put in it, for content that does not fit in the room the page has for it. The scrolling is the browser's own, so the momentum, the keyboard and the assistive technology of the platform come with it; what the component adds is everything around that. It sizes the box - fixed, full, fit, or growing up to a maximum before it starts scrolling - picks which axes scroll, keeps a scroll from carrying on into the page behind it, reserves the gutter so the layout does not jump, restyles the scrollbars in the colors of the theme and hides them until they are wanted, fades the edges that still have content beyond them, snaps onto the items of a strip one at a time, answers a drag and a wheel where a mouse has no other way of scrolling sideways, and puts the box in the tab order for readers who scroll with the keyboard. It reports where it stands and which way it is going as it moves, brackets a whole scroll with a start and an end, and calls back as each edge is reached, which is what an endless list is built on; it opens where it is told to and can be driven from code with ScrollTo, ScrollBy, ScrollToStart, ScrollToEnd and ScrollToElement; and it holds the reader's place as content arrives at either end - pinned to the bottom of a log that is still being written to, and standing still while a page of older messages loads in above. ## Parameters | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | AutoScroll | `bool` | false | Keeps the pane pinned to the end of its content as the content grows. It pins once as soon as it is turned on, and after that only while the reader left the pane standing at the end. | | AutoScrollThreshold | `int` | 0 | How near the end of the content (in pixels) the pane has to have been left for AutoScroll to keep pinning it there. | | AutoHeight | `bool` | false | Makes the height of the pane auto. | | AutoSize | `bool` | false | Makes both height and width of the pane auto. | | AutoWidth | `bool` | false | Makes the width of the pane auto. | | AutoHideScrollbar | `bool` | false | Keeps the Modern scrollbar of the pane out of sight until the pointer is over it or something in it holds the focus. | | Body | `RenderFragment?` | null | Alias for the ChildContent parameter. | | ChildContent | `RenderFragment?` | null | The content of the pane, it can be any custom tag or text. | | DragMomentum | `bool` | false | Lets a released drag carry on at the speed it was let go at and slow to a stop, instead of stopping dead with the button. It only applies to DragScroll. | | DragScroll | `bool` | false | Lets the pane be scrolled by dragging its content with a mouse or a pen, which is how a strip that only scrolls sideways is reached without a horizontal wheel. | | Fade | `bool` | false | Fades out each edge of the pane that still has content beyond it, and takes the fade off the moment that edge is reached. | | FadeSize | `string?` | null | How far the Fade reaches into the pane, as any CSS length. It defaults to 2rem. | | FitHeight | `bool` | false | Makes the height of the pane fit-content. | | FitSize | `bool` | false | Makes both height and width of the pane fit-content. | | FitWidth | `bool` | false | Makes the width of the pane fit-content. | | Focusable | `bool` | false | Puts the pane itself in the tab order, so a pane holding nothing focusable can still be scrolled with the keyboard. | | FullHeight | `bool` | false | Makes the height of the pane 100%. | | FullSize | `bool` | false | Makes both height and width of the pane 100%. | | FullWidth | `bool` | false | Makes the width of the pane 100%. | | Gutter | `BitScrollbarGutter?` | null | Allows to reserve space for the scrollbar, preventing unwanted layout changes as the content grows while also avoiding unnecessary visuals when scrolling isn't needed. | | Height | `string?` | null | The height of the pane. | | Horizontal | `bool` | false | Lays the content out on a single line that scrolls sideways instead of wrapping, and turns the vertical scrolling off. | | HorizontalWheel | `bool` | false | Turns a vertical wheel over a pane that only scrolls sideways into a sideways scroll, and hands the scroll back to the page once the pane reaches that end. | | InitialScrollLeft | `double?` | null | Where the pane stands the first time it is rendered, measured from the visual left edge of the content in pixels. It is applied once and never animated. | | InitialScrollTop | `double?` | null | Where the pane stands the first time it is rendered, measured from the top of the content in pixels. It is applied once and never animated. | | MaxHeight | `string?` | null | The maximum height of the pane, which is what makes it grow with its content and only start scrolling once there is too much of it. | | MaxWidth | `string?` | null | The maximum width of the pane. | | MinHeight | `string?` | null | The minimum height of the pane. | | MinWidth | `string?` | null | The minimum width of the pane. | | Modern | `bool` | false | Enables a modern style for the scrollbar of the pane, drawn in the colors of the theme instead of by the operating system. | | NoScroll | `bool` | false | Turns the scrolling of the pane off while leaving its content interactive and the scrolling API of the component working. | | OnReachedBottom | `EventCallback` | | Callback for when the pane has been scrolled to the bottom of its content. | | OnReachedLeft | `EventCallback` | | Callback for when the pane has been scrolled to the visual left edge of its content. | | OnReachedRight | `EventCallback` | | Callback for when the pane has been scrolled to the visual right edge of its content. | | OnReachedTop | `EventCallback` | | Callback for when the pane has been scrolled to the top of its content. | | OnScroll | `EventCallback<BitScrollOffset>` | | Callback for when the pane is scrolled, carrying where it now stands. | | OnScrollEnd | `EventCallback<BitScrollOffset>` | | Callback for when the pane has come to rest after being scrolled, carrying where it stopped. | | OnScrollStart | `EventCallback<BitScrollOffset>` | | Callback for when the pane starts being scrolled, carrying where it stood as it set off. | | Overflow | `BitOverflow?` | null | Controls the visibility of scrollbars in the pane. | | OverflowX | `BitOverflow?` | null | Controls the visibility of X-axis scrollbar in the pane. It has the last word on that axis, over both Overflow and Horizontal. | | OverflowY | `BitOverflow?` | null | Controls the visibility of Y-axis scrollbar in the pane. It has the last word on that axis, over both Overflow and Horizontal. | | Overscroll | `BitOverscroll?` | null | What the browser does with a scroll that has already reached the edge of the pane. | | OverscrollX | `BitOverscroll?` | null | What the browser does with a horizontal scroll that has already reached the edge of the pane. | | OverscrollY | `BitOverscroll?` | null | What the browser does with a vertical scroll that has already reached the edge of the pane. | | PreserveScroll | `bool` | false | Keeps the reader's place when content is added above what they are looking at, which is what a conversation that loads older messages at its top needs. Every engine but WebKit already does this on its own, so it only steps in where the browser is not anchoring the pane - which a pane setting overflow-anchor: none on itself is not, on any engine. | | ReachOffset | `int` | 0 | How near an edge (in pixels) counts as having reached it, for the four edge callbacks. | | Role | `string?` | null | The ARIA role of the pane. A pane renders none of its own; set it to region or group, along with AriaLabel, where the pane is a part of the page in its own right. | | ScrollbarColor | `string?` | null | Sets the color of the scrollbar thumb and track, in that order. For specific colors, it has to contain both colors separated by a space or otherwise it won't work. | | ScrollbarWidth | `BitScrollbarWidth?` | null | Sets the desired thickness of scrollbars when they are shown. | | ScrollPadding | `string?` | null | The inset the pane keeps between its edges and anything scrolled into view inside it, as any CSS length. | | ScrollThrottle | `int` | 0 | The shortest interval (in milliseconds) between two OnScroll reports. Reports are always coalesced to at most one per animation frame. | | Smooth | `bool` | false | Animates every move the pane does not make by hand: the scrolling API, a fragment navigation into it, and the pinning AutoScroll does. | | Snap | `BitScrollSnap?` | null | Makes the pane come to rest on the snap positions of its content instead of anywhere between them. | | SnapAlign | `BitScrollSnapAlign?` | null | Where the direct children of the pane come to rest in it while Snap is on. | | SnapStop | `bool` | false | Keeps a fast scroll from passing over the snap positions it goes by, which is what turns a snapping strip into a carousel that moves one item per gesture. | | Width | `string?` | null | The width of the pane. | | 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. | | 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. | | IsEnabled | `bool` | true | Gets or sets a value indicating whether the component is enabled and can respond to user interaction. | | 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 | | :--- | :--- | :------------ | :---------- | | FocusAsync | `ValueTask FocusAsync() / ValueTask FocusAsync(bool preventScroll)` | | Gives the focus to the pane itself, which only takes it while Focusable or a TabIndex has put it in the tab order. | | GetScrollOffset | `ValueTask<BitScrollOffset?>` | | Reads where the pane currently stands, straight from the browser. | | Refresh | `ValueTask` | | Re-measures the pane and brings the fade and the edge callbacks back up to date, for the size changes neither of its observers can see. | | ScrollBy | `ValueTask ScrollBy(double x, double y, bool? smooth = null)` | | Scrolls the pane by a distance from wherever it currently stands, in pixels and measured on the screen: a positive x always moves the pane rightwards. | | ScrollTo | `ValueTask ScrollTo(double? left, double? top, bool? smooth = null)` | | Scrolls the pane to an absolute position, in pixels from the top and from the visual left edge of the content. An axis that is left null stays where it is. | | ScrollToElement | `ValueTask ScrollToElement(string elementId, double offset = 0, bool? smooth = null, BitScrollAlignment alignment = BitScrollAlignment.Start)` | | Brings an element inside the pane into view by scrolling the pane itself, leaving every scrolling ancestor of it alone. | | ScrollToEnd | `ValueTask ScrollToEnd(bool? smooth = null)` | | Scrolls the pane to the end of its content, both horizontally and vertically, which on the horizontal axis is the visual left edge of a right-to-left pane. | | ScrollToStart | `ValueTask ScrollToStart(bool? smooth = null)` | | Scrolls the pane back to the start of its content, both horizontally and vertically, which on the horizontal axis is the visual right edge of a right-to-left pane. | | 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 ### BitScrollAlignment Enum | Name | Value | Description | | :--- | :--- | :---------- | | Start | 0 | The element is brought to the start of the pane: its top edge to the top of the pane, and its leading edge to the leading edge of the pane. | | Center | 1 | The element is centered in the pane along both axes. | | End | 2 | The element is brought to the end of the pane: its bottom edge to the bottom of the pane, and its trailing edge to the trailing edge of the pane. | | Nearest | 3 | The pane moves as little as it can: an element that is already fully in view is not moved to at all, and one that is not is brought to whichever edge it is nearest. | ### BitScrollSnap Enum | Name | Value | Description | | :--- | :--- | :---------- | | None | 0 | The pane does not snap, which is the initial value. | | Proximity | 1 | The pane snaps to a position only when it comes to rest near one, so a scroll can still be left anywhere between two items. | | Mandatory | 2 | The pane always comes to rest on a snap position, which is what a carousel or a row of pages wants. | ### BitScrollSnapAlign Enum | Name | Value | Description | | :--- | :--- | :---------- | | None | 0 | The children carry no snap position of their own. | | Start | 1 | Each child comes to rest at the start of the pane. | | Center | 2 | Each child comes to rest in the middle of the pane. | | End | 3 | Each child comes to rest at the end of the pane. | ### BitOverflow Enum | Name | Value | Description | | :--- | :--- | :---------- | | Auto | 0 | Scrollbars are displayed automatically when needed based on the content size, and hidden when not needed. | | Hidden | 1 | Scrollbars are always hidden, even if the content overflows the visible area. | | Scroll | 2 | Scrollbars are always visible, allowing users to scroll through the content even if it doesn't overflow the visible area. | | Visible | 3 | Overflow content is not clipped and may be visible outside the element's padding box. | ### BitOverscroll Enum | Name | Value | Description | | :--- | :--- | :---------- | | Auto | 0 | The initial value: the scroll carries on into the nearest scrolling ancestor once the pane has reached its edge, and the platform's own overscroll affordance is kept. | | Contain | 1 | The scroll stops at the edge of the pane instead of carrying on into the page behind it, while the platform's own overscroll affordance inside the pane is kept. | | None | 2 | Like Contain, and the platform's own overscroll affordance is suppressed as well, so the pane neither bounces nor triggers a pull to refresh at its edges. | ### BitScrollbarGutter Enum | Name | Value | Description | | :--- | :--- | :---------- | | Auto | 0 | The initial value. Classic scrollbars create a gutter when overflow is scroll, or when overflow is auto and the box is overflowing. Overlay scrollbars do not consume space. | | Stable | 1 | When using classic scrollbars, the gutter will be present if overflow is auto, scroll, or hidden even if the box is not overflowing. When using overlay scrollbars, the gutter will not be present. | | BothEdges | 2 | If a gutter would be present on one of the inline start/end edges of the box, another will be present on the opposite edge as well. | ### BitScrollbarWidth Enum | Name | Value | Description | | :--- | :--- | :---------- | | Auto | 0 | The default scrollbar width for the platform. | | Thin | 1 | A thin scrollbar width variant on platforms that provide that option, or a thinner scrollbar than the default platform scrollbar width. | | None | 2 | No scrollbar shown, however the element will still be scrollable. | ### 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 ### BitScrollOffset Properties Where a pane stands, as measured in the browser. Everything is in CSS pixels. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Left | `double` | 0 | The raw scrollLeft of the pane, so in a right-to-left pane it starts at 0 at the right edge and runs negative. | | Top | `double` | 0 | How far the content has been scrolled down. | | ScrollWidth | `double` | 0 | The full width of the content, including the part of it that is scrolled out of sight. | | ScrollHeight | `double` | 0 | The full height of the content, including the part of it that is scrolled out of sight. | | ClientWidth | `double` | 0 | The width of the visible area of the pane, without its scrollbar. | | ClientHeight | `double` | 0 | The height of the visible area of the pane, without its scrollbar. | | Rtl | `bool` | false | Whether the pane was laid out right to left when it was measured, which is what tells the two readings of a Left of 0 apart. | | DeltaLeft | `double` | 0 | How far the pane moved sideways since the position before this one was reported, positive rightwards on the screen. Only the reports OnScroll makes carry it. | | DeltaTop | `double` | 0 | How far the pane moved up or down since the position before this one was reported, positive downwards. Only the reports OnScroll makes carry it. | | OffsetLeft | `double` | 0 | The distance from the visual left edge of the content, which is Left made positive and direction independent. | | MaxLeft | `double` | 0 | The largest horizontal offset the pane can reach. | | MaxTop | `double` | 0 | The largest vertical offset the pane can reach. | | ScrollableX | `bool` | false | Whether the content is wider than the pane. | | ScrollableY | `bool` | false | Whether the content is taller than the pane. | | AtLeft | `bool` | false | Whether the pane is standing at the visual left edge of its content. | | AtRight | `bool` | false | Whether the pane is standing at the visual right edge of its content. | | AtTop | `bool` | false | Whether the pane is standing at the top of its content. | | AtBottom | `bool` | false | Whether the pane is standing at the bottom of its content. | | PercentX | `double` | 0 | How far the pane has been scrolled sideways, from 0 at the visual left edge to 1 at the right one. | | PercentY | `double` | 0 | How far the pane has been scrolled down, from 0 at the top to 1 at the bottom. | | ScrollingDown | `bool` | false | Whether the move this report carries was downwards, which is what a header that folds away on the way down reads. | | ScrollingUp | `bool` | false | Whether the move this report carries was upwards. | | ScrollingRight | `bool` | false | Whether the move this report carries was to the right on the screen, whichever way the pane reads. | | ScrollingLeft | `bool` | false | Whether the move this report carries was to the left on the screen, whichever way the pane reads. | ## Examples \n**Basic**: ```razor

Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape. Imagine this text as the scaffolding of something remarkable, a foundation upon which connections and inspirations will be built.

In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. These words are temporary, standing in place of ideas yet to come, a glimpse into the infinite possibilities that lie ahead. Think of this text as a bridge, connecting the empty spaces of now with the vibrant narratives of tomorrow.

In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary. Here lies the start of something new, an opportunity to craft, inspire, and create.

Whether it is a tale of adventure, a reflection of truth, or an idea that sparks change, these lines are yours to fill, to shape, and to make uniquely yours. The journey begins here, in this quiet moment where everything is possible.

For now, these lines are here to remind you of the beauty of beginnings. They are the quiet before the symphony, the foundation upon which your creativity will build. Soon, this space will hold your thoughts, your visions, and your voice.

``` \n**Dimensions**: ```razor

Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape. Imagine this text as the scaffolding of something remarkable, a foundation upon which connections and inspirations will be built.

In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. These words are temporary, standing in place of ideas yet to come, a glimpse into the infinite possibilities that lie ahead. Think of this text as a bridge, connecting the empty spaces of now with the vibrant narratives of tomorrow.

In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary. Here lies the start of something new, an opportunity to craft, inspire, and create.

Whether it is a tale of adventure, a reflection of truth, or an idea that sparks change, these lines are yours to fill, to shape, and to make uniquely yours. The journey begins here, in this quiet moment where everything is possible.

For now, these lines are here to remind you of the beauty of beginnings. They are the quiet before the symphony, the foundation upon which your creativity will build. Soon, this space will hold your thoughts, your visions, and your voice.

Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Add a line Reset @for (var i = 1; i <= maxHeightLines; i++) {
Line @i
}
``` ```csharp private int maxHeightLines = 2; ``` \n**Overflow**: ```razor @for (int i = 0; i < overflowItemsCount; i++) { var index = i;
@index
}
``` ```csharp private bool noScroll; private BitOverflow overflow; private double overflowItemsCount = 6; ``` \n**Horizontal**: ```razor Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding.
@for (var i = 1; i <= 12; i++) {
Item @i
}
``` \n**Overscroll**: ```razor
The outer pane
@for (var i = 1; i <= 12; i++) {
Inner @i
}
@for (var i = 1; i <= 6; i++) {
Outer @i
}
``` ```csharp private BitOverscroll overscroll = BitOverscroll.Contain; ``` \n**Scrollbar gutter**: ```razor @for (int i = 0; i < gutterItemsCount; i++) { var index = i;
@index
}
``` ```csharp private BitScrollbarGutter gutter; private double gutterItemsCount = 6; ``` \n**Scrollbar width & color**: ```razor

Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape. Imagine this text as the scaffolding of something remarkable, a foundation upon which connections and inspirations will be built.

In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. These words are temporary, standing in place of ideas yet to come, a glimpse into the infinite possibilities that lie ahead. Think of this text as a bridge, connecting the empty spaces of now with the vibrant narratives of tomorrow.

In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary. Here lies the start of something new, an opportunity to craft, inspire, and create.

Whether it is a tale of adventure, a reflection of truth, or an idea that sparks change, these lines are yours to fill, to shape, and to make uniquely yours. The journey begins here, in this quiet moment where everything is possible.

For now, these lines are here to remind you of the beauty of beginnings. They are the quiet before the symphony, the foundation upon which your creativity will build. Soon, this space will hold your thoughts, your visions, and your voice.

Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape. Imagine this text as the scaffolding of something remarkable, a foundation upon which connections and inspirations will be built.

In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. These words are temporary, standing in place of ideas yet to come, a glimpse into the infinite possibilities that lie ahead. Think of this text as a bridge, connecting the empty spaces of now with the vibrant narratives of tomorrow.

In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary. Here lies the start of something new, an opportunity to craft, inspire, and create.

Whether it is a tale of adventure, a reflection of truth, or an idea that sparks change, these lines are yours to fill, to shape, and to make uniquely yours. The journey begins here, in this quiet moment where everything is possible.

For now, these lines are here to remind you of the beauty of beginnings. They are the quiet before the symphony, the foundation upon which your creativity will build. Soon, this space will hold your thoughts, your visions, and your voice.

Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape. Imagine this text as the scaffolding of something remarkable, a foundation upon which connections and inspirations will be built.

In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. These words are temporary, standing in place of ideas yet to come, a glimpse into the infinite possibilities that lie ahead. Think of this text as a bridge, connecting the empty spaces of now with the vibrant narratives of tomorrow.

In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary. Here lies the start of something new, an opportunity to craft, inspire, and create.

Whether it is a tale of adventure, a reflection of truth, or an idea that sparks change, these lines are yours to fill, to shape, and to make uniquely yours. The journey begins here, in this quiet moment where everything is possible.

For now, these lines are here to remind you of the beauty of beginnings. They are the quiet before the symphony, the foundation upon which your creativity will build. Soon, this space will hold your thoughts, your visions, and your voice.

``` \n**Modern**: ```razor

Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape. Imagine this text as the scaffolding of something remarkable, a foundation upon which connections and inspirations will be built.

In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. These words are temporary, standing in place of ideas yet to come, a glimpse into the infinite possibilities that lie ahead. Think of this text as a bridge, connecting the empty spaces of now with the vibrant narratives of tomorrow.

In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary. Here lies the start of something new, an opportunity to craft, inspire, and create.

Whether it is a tale of adventure, a reflection of truth, or an idea that sparks change, these lines are yours to fill, to shape, and to make uniquely yours. The journey begins here, in this quiet moment where everything is possible.

For now, these lines are here to remind you of the beauty of beginnings. They are the quiet before the symphony, the foundation upon which your creativity will build. Soon, this space will hold your thoughts, your visions, and your voice.

Once upon a time, stories wove connections between people, a symphony of voices crafting shared dreams. Each word carried meaning, each pause brought understanding. ``` ```csharp private bool autoHideScrollbar = true; ``` \n**Fade**: ```razor

Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape. Imagine this text as the scaffolding of something remarkable, a foundation upon which connections and inspirations will be built.

In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. These words are temporary, standing in place of ideas yet to come, a glimpse into the infinite possibilities that lie ahead. Think of this text as a bridge, connecting the empty spaces of now with the vibrant narratives of tomorrow.

In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary. Here lies the start of something new, an opportunity to craft, inspire, and create.

Whether it is a tale of adventure, a reflection of truth, or an idea that sparks change, these lines are yours to fill, to shape, and to make uniquely yours. The journey begins here, in this quiet moment where everything is possible.

For now, these lines are here to remind you of the beauty of beginnings. They are the quiet before the symphony, the foundation upon which your creativity will build. Soon, this space will hold your thoughts, your visions, and your voice.

@for (var row = 1; row <= 8; row++) {
@for (var col = 1; col <= 8; col++) {
R@(row)C@(col)
}
}
``` ```csharp private bool fade = true; private double fadeSize = 2; ``` \n**Scroll events**: ```razor @for (var i = 1; i <= 20; i++) {
Row @i
}
Top: @((scrollOffset?.Top ?? 0).ToString("0")) of @((scrollOffset?.MaxTop ?? 0).ToString("0")) | PercentY: @(((scrollOffset?.PercentY ?? 0) * 100).ToString("0"))% | AtTop: @(scrollOffset?.AtTop.ToString() ?? "-") | AtBottom: @(scrollOffset?.AtBottom.ToString() ?? "-")
State: @scrollState | Going: @scrollDirection
``` ```csharp private double scrollThrottle; private string scrollState = "-"; private string scrollDirection = "-"; private BitScrollOffset? scrollOffset; private void HandleScroll(BitScrollOffset offset) { scrollOffset = offset; // A report that carries no move of its own - the first one, or one the pane's own size changed - // leaves the direction where it was rather than blanking it out. if (offset.ScrollingDown) scrollDirection = $"down ({offset.DeltaTop:0.#}px)"; else if (offset.ScrollingUp) scrollDirection = $"up ({-offset.DeltaTop:0.#}px)"; StateHasChanged(); } private void HandleScrollStart() => scrollState = "scrolling..."; private void HandleScrollEnd(BitScrollOffset offset) => scrollState = $"stopped at {offset.Top:0} ({offset.PercentY * 100:0}%)"; ``` \n**Reaching the edges**: ```razor @foreach (var row in endlessRows) {
@row
} @if (loadingMore) {
Loading...
}
Last edge reached: @reachedEdge | rows: @endlessRows.Count
``` ```csharp private bool loadingMore; private double reachOffset = 40; private string reachedEdge = "-"; private readonly List endlessRows = [.. Enumerable.Range(1, 12).Select(i => $"Row {i}")]; private void HandleReachedTop() => reachedEdge = "top"; private async Task LoadMoreRows() { reachedEdge = "bottom"; if (loadingMore || endlessRows.Count >= 60) return; loadingMore = true; StateHasChanged(); await Task.Delay(600); var next = endlessRows.Count; endlessRows.AddRange(Enumerable.Range(next + 1, 12).Select(i => $"Row {i}")); loadingMore = false; StateHasChanged(); } ``` \n**Scrolling the pane from code**: ```razor To start To end To 200px Down 100px To row 15 To row 15, centered Read position Focus the pane
A header of the pane's own, and 2.5rem of ScrollPadding under it
@for (var i = 1; i <= 25; i++) {
Row @i
}
@readPosition
A pane that opened 250px down, without ever having been at the top:
@for (var i = 1; i <= 25; i++) {
Row @i
}
``` ```csharp private bool smooth = true; private string readPosition = "-"; private BitScrollablePane? scrollablePane; private async Task ReadScrollOffset() { if (scrollablePane is null) return; var offset = await scrollablePane.GetScrollOffset(); readPosition = offset is null ? "-" : $"Top {offset.Top:0} of {offset.MaxTop:0}, at the bottom: {offset.AtBottom}"; } ``` \n**AutoScroll**: ```razor Add lines periodically
The log starts here.
@foreach (var line in autoScrollLines) {
@line
}
``` ```csharp private bool autoScrollRunning; private double autoScrollThreshold; private readonly List autoScrollLines = []; private async Task AddAutoScrollContent() { autoScrollRunning = true; try { for (var i = 0; i < 15; i++) { await Task.Delay(700); autoScrollLines.Add($"A new line arrived at {DateTime.Now:HH:mm:ss} ({Random.Shared.Next(1, 100)})"); StateHasChanged(); } } finally { autoScrollRunning = false; } } ``` \n**Preserving the reader's place**: ```razor @if (loadingOlder) {
Loading older messages...
} @* Keyed, so the older messages are new elements at the TOP rather than new text in the elements that were already there - which is what there is a place to keep for. *@ @foreach (var message in conversation) {
@message
}
Oldest message loaded: @oldestMessage | messages: @conversation.Count
``` ```csharp private bool preserveScroll = true; private bool loadingOlder; private int oldestMessage = 1; private readonly List conversation = [.. Enumerable.Range(1, 14).Select(i => $"Message {i}")]; private async Task LoadOlderMessages() { if (loadingOlder || oldestMessage <= -40) return; loadingOlder = true; StateHasChanged(); await Task.Delay(500); // The older messages go in at the TOP, which is what pushes everything the reader was looking at // down the screen unless the pane keeps their place for them. conversation.InsertRange(0, Enumerable.Range(oldestMessage - 8, 8).Select(i => $"Message {i}")); oldestMessage -= 8; loadingOlder = false; StateHasChanged(); } ``` \n**Keyboard & accessibility**: ```razor

Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape. Imagine this text as the scaffolding of something remarkable, a foundation upon which connections and inspirations will be built.

In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. These words are temporary, standing in place of ideas yet to come, a glimpse into the infinite possibilities that lie ahead. Think of this text as a bridge, connecting the empty spaces of now with the vibrant narratives of tomorrow.

In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary. Here lies the start of something new, an opportunity to craft, inspire, and create.

Whether it is a tale of adventure, a reflection of truth, or an idea that sparks change, these lines are yours to fill, to shape, and to make uniquely yours. The journey begins here, in this quiet moment where everything is possible.

For now, these lines are here to remind you of the beauty of beginnings. They are the quiet before the symphony, the foundation upon which your creativity will build. Soon, this space will hold your thoughts, your visions, and your voice.

``` ```csharp private bool focusable = true; ``` \n**Snapping**: ```razor @for (var i = 1; i <= 10; i++) {
Card @i
}
``` ```csharp private bool snapStop = true; private BitScrollSnap snap = BitScrollSnap.Mandatory; private BitScrollSnapAlign snapAlign = BitScrollSnapAlign.Start; ``` \n**Dragging & the wheel**: ```razor @for (var i = 1; i <= 10; i++) {
Card @i
}
``` ```csharp private bool dragScroll = true; private bool dragMomentum = true; private bool horizontalWheel = true; ``` \n**Style & Class**: ```razor

Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape. Imagine this text as the scaffolding of something remarkable, a foundation upon which connections and inspirations will be built.

In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. These words are temporary, standing in place of ideas yet to come, a glimpse into the infinite possibilities that lie ahead. Think of this text as a bridge, connecting the empty spaces of now with the vibrant narratives of tomorrow.

In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary. Here lies the start of something new, an opportunity to craft, inspire, and create.

Every story starts with a blank canvas, a quiet space waiting to be filled with ideas, emotions, and dreams. These placeholder words symbolize the beginning - a moment of possibility where creativity has yet to take shape. Imagine this text as the scaffolding of something remarkable, a foundation upon which connections and inspirations will be built.

In the beginning, there is silence, a blank canvas yearning to be filled, a quiet space where creativity waits to awaken. These words are temporary, standing in place of ideas yet to come, a glimpse into the infinite possibilities that lie ahead. Think of this text as a bridge, connecting the empty spaces of now with the vibrant narratives of tomorrow.

In this space, potential reigns supreme. It is a moment suspended in time, where imagination dances freely and each word has the power to transform into something extraordinary. Here lies the start of something new, an opportunity to craft, inspire, and create.

``` \n**RTL**: ```razor

داستان‌ها روزگاری پیوند میان مردم را می‌بافتند، سمفونی‌ای از صداها که رویاهای مشترک را می‌ساخت. هر واژه معنایی داشت و هر مکث فهمی به همراه می‌آورد.

در آغاز، سکوت است؛ بومی سفید که در انتظار پر شدن است، فضایی آرام که در آن خلاقیت منتظر بیدار شدن است. این واژه‌ها موقتی‌اند و جای ایده‌هایی را گرفته‌اند که هنوز نیامده‌اند.

در این فضا، امکان حکمرانی می‌کند. لحظه‌ای معلق در زمان، جایی که تخیل آزادانه می‌رقصد و هر واژه توان آن را دارد که به چیزی خارق‌العاده بدل شود.

هر داستانی با بومی سفید آغاز می‌شود؛ فضایی آرام که منتظر پر شدن با ایده‌ها، احساس‌ها و رویاهاست. این واژه‌های موقت نشانهٔ آغازند؛ لحظه‌ای از امکان که هنوز خلاقیت در آن شکل نگرفته است.

فعلاً این سطرها اینجا هستند تا زیبایی آغازها را به یاد بیاورند. آن‌ها سکوت پیش از سمفونی‌اند، بنیادی که خلاقیت شما بر آن ساخته خواهد شد.

داستان‌ها روزگاری پیوند میان مردم را می‌بافتند، سمفونی‌ای از صداها که رویاهای مشترک را می‌ساخت. ```