<- Back to Layout Components

Definition

ScrollArea creates a bounded viewport with internal scrolling. It is a layout container: its children render inside the scrollable content widget.

Scope

Use ScrollArea when overflow must stay inside a sidebar, content body, split pane, drawer, or any bounded layout section. Do not use it as a page-height replacement: the parent layout must still provide bounded height with properties such as stretch, height, or min-height: 0.

Properties

Property Type Default Notes
children list[str | Component] [] Content rendered inside the scroll viewport. Runtime append/remove is supported.
stretch bool false Lets the scroll area fill available flex space.
style string None Style applied to the scroll viewport. Supports direct property updates.
content_style string None Style applied to the inner content widget.
transparent bool false Makes the scroll viewport background transparent.
scroll_x bool true Enables horizontal scroll when content overflows.
scroll_y bool true Enables vertical scroll when content overflows.
content_vertical_policy string "expanding" Desktop content sizing policy. Use "maximum" when content should keep natural height.

Static ScrollArea

content = sdk.ui.Column("scrollarea_content", ["row_1", "row_2"])
builder.add(content)

scroll = sdk.ui.ScrollArea("scrollarea", [content.id])
scroll.set_property("stretch", True)
scroll.set_property("scroll_x", False)
builder.add(scroll)

Store Binding

Bind style when viewport styling is driven by client state.

scroll = sdk.ui.ScrollArea("scrollarea_store", [content.id])
scroll.set_property("stretch", True)
scroll.set_property("scroll_x", False)
scroll.set_property(
    "style",
    bound.store("/components_test/scrollarea/style", scope="page", default=""),
)
builder.add(scroll)

Data Model Binding

Use data-model binding when the viewport style comes from the surface data model.

scroll = sdk.ui.ScrollArea("scrollarea_data", [content.id])
scroll.set_property("stretch", True)
scroll.set_property("scroll_x", False)
scroll.set_property(
    "style",
    bound.data("/components_test/scrollarea_model/style", default=""),
)
builder.add(scroll)

Property Updates

Declare capabilities before updating style directly.

scroll = sdk.ui.ScrollArea("scrollarea_live", [content.id])
scroll.set_property("stretch", True)
scroll.set_property("scroll_x", False)
scroll.allow("style.set")
builder.add(scroll)

The action can update store, data model, and the live component:

return sdk.effects.respond(
    sdk.effects.ui_property_update("scrollarea_live", "style", next_style, surface_id=surface_id),
)

Dynamic Children

children supports append and remove updates. This is useful for feeds, logs, and growing content lists.

scroll = sdk.ui.ScrollArea("scrollarea_dynamic", ["row_1", "row_2"])
scroll.set_property("stretch", True)
scroll.set_property("scroll_x", False)
scroll.allow("children.append", "children.remove")
builder.add(scroll)

# In the action:
return sdk.effects.respond(
    sdk.effects.ui_collection_append("scrollarea_dynamic", "children", row_component_dict, surface_id=surface_id),
)

Visibility And Permissions

show_if, hide_if, and required_permissions are available on ScrollArea.

scroll.set_show_if({
    "conditions": [
        {"left": bound.store("/components_test/visibility/scrollarea_show", scope="page", default=True), "op": "==", "right": True}
    ]
})

scroll.set_hide_if({
    "conditions": [
        {"left": bound.store("/components_test/visibility/scrollarea_hide", scope="page", default=False), "op": "==", "right": True}
    ]
})

scroll.set_required_permissions(["components.layout.view"])

Notes

  • ScrollArea needs bounded height from its parent; otherwise the page grows instead of scrolling internally.
  • Use stretch: true when the scroll area must fill a Column, ContentArea, Sidebar, or Splitter pane.
  • Use scroll_x: false for vertical-only panes to avoid horizontal scrollbars.
  • Use transparent: true when the parent should provide the visible background.