<- Back to Layout Components

Definition

Row is the base horizontal layout container. It renders its children side by side.

Scope

Use Row for toolbars, inline controls, action groups, metadata bars, and side-by-side layout sections.

Do not use Row for vertical stacks. Use Column when children must be arranged top to bottom. Use semantic layout components when the region represents a page shell section such as a header, sidebar, or content area.

Properties

Property Type Default Notes
children list[str | Component] [] Horizontal child collection. Supports append/remove patches.
align string "left" desktop, "top" web Common values are left, center, right, top, bottom, and fill.
spacing int 0 Gap between children. Supports binding and direct updates.
style string client default Standard style property.
padding list[int] client default Web renderer padding.
width int | string client default Optional fixed width on desktop.
height int | string client default Optional fixed height on desktop.
stretch bool client default Web layout stretch hint. Desktop rows use an expanding size policy.

Static Children

builder.add(sdk.ui.Button("row_action_1", "Action 1", variant="default"))
builder.add(sdk.ui.Button("row_action_2", "Action 2", variant="default"))
builder.add(sdk.ui.Button("row_action_3", "Action 3", variant="default"))

row = sdk.ui.Row(
    "toolbar",
    ["row_action_1", "row_action_2", "row_action_3"],
)
row.set_property("align", "left")
row.set_property("spacing", 8)
builder.add(row)

Store Binding

Bind spacing when the row gap is controlled by page or global store state.

builder.set_store("/components_test/row/spacing", 8, scope="page")

row = sdk.ui.Row("toolbar", ["row_action_1", "row_action_2"])
row.set_property(
    "spacing",
    bound.store("/components_test/row/spacing", scope="page", default=8),
)
builder.add(row)

Data Model Binding

Use data-model binding when the row spacing comes from the current surface data.

builder.set_data("/components_test/row_model/spacing", 8)

row = sdk.ui.Row("toolbar", ["row_action_1", "row_action_2"])
row.set_property(
    "spacing",
    bound.data("/components_test/row_model/spacing", default=8),
)
builder.add(row)

Property Updates

Declare capabilities before updating spacing directly.

row = sdk.ui.Row("toolbar", ["row_action_1", "row_action_2"])
row.set_property("spacing", 8)
row.allow("spacing.set")
builder.add(row)

The action updates store, data model, and live component state:

surface_id = ctx["_surface_id"]
spacing = 20

return sdk.effects.respond(
    sdk.effects.ui_messages([
        {"stateUpdate": {"scope": "page", "values": {"/components_test/row/spacing": spacing}}},
        sdk.ui.Builder.build_data_model_update_payload(
            surface_id=surface_id,
            data={"components_test": {"row_model": {"spacing": spacing}}},
        ),
    ]),
    sdk.effects.ui_property_update(
        "toolbar",
        "spacing",
        spacing,
        surface_id=surface_id,
    ),
)

Dynamic Children

Use collection patches for dynamic horizontal content. The patch target is children.

row = sdk.ui.Row("toolbar", ["row_action_1", "row_action_2"])
row.allow("children.append", "children.remove")
builder.add(row)

Append and remove actions target the children collection:

return sdk.effects.respond(
    sdk.effects.ui_collection_append(
        "toolbar",
        "children",
        sdk.ui.Button("row_action_3", "Action 3", variant="default").to_dict(),
        surface_id=ctx["_surface_id"],
    ),
    sdk.effects.ui_collection_remove(
        "toolbar",
        "children",
        {"id": "row_action_3"},
        surface_id=ctx["_surface_id"],
    ),
)

Visibility And Permissions

show_if, hide_if, and required_permissions are available on Row.

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

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

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

Notes

  • Put inline controls and side-by-side sections directly in Row.children.
  • Use children.append and children.remove for incremental horizontal lists.
  • Use Column inside a Row when one horizontal section needs vertical content.
  • Use spacing for the gap between children when the gap must be explicit or dynamic.