<- Back to Layout Components

Splitter creates a horizontal resizable pane group. Use it when adjacent areas must share bounded space and the user needs to resize them, for example list/detail, editor/preview, or comparison views.

The component is a container: each pane is a child component. Put scroll containers inside the panes when pane content must scroll independently.

Properties

Property Type Default Notes
children list[str | Component] [] Pane components. The desktop and web renderers support runtime append/remove.
sizes list[int] equal split Initial pane sizes. Web normalizes values to percentages; desktop passes values to QSplitter.setSizes.
max_sizes list[int] [] Optional maximum width per pane. Use 0 or omit an entry for no maximum.
stretch bool false Allows the splitter to fill available flex space.

Static Splitter

left = sdk.ui.Column("splitter_left", [])
left.set_property("align", "fill")
left.set_property("stretch", True)
left.set_property("style", "min-height: 0;")
builder.add(left)

right = sdk.ui.Column("splitter_right", [])
right.set_property("align", "fill")
right.set_property("stretch", True)
right.set_property("style", "min-height: 0;")
builder.add(right)

splitter = sdk.ui.Splitter("splitter", [left.id, right.id])
splitter.set_property("stretch", True)
splitter.set_property("sizes", [650, 350])
builder.add(splitter)

Store Binding

Bind sizes and max_sizes to page store values when pane sizing is part of client state.

splitter = sdk.ui.Splitter("splitter_store", [left.id, right.id])
splitter.set_property("stretch", True)
splitter.set_property(
    "sizes",
    bound.store("/components_test/splitter/sizes", scope="page", default=[500, 300]),
)
splitter.set_property(
    "max_sizes",
    bound.store("/components_test/splitter/max_sizes", scope="page", default=[0, 0]),
)
builder.add(splitter)

Data Model Binding

Use data-model binding when pane sizing comes from the surface data model.

splitter = sdk.ui.Splitter("splitter_data", [left.id, right.id])
splitter.set_property("stretch", True)
splitter.set_property(
    "sizes",
    bound.data("/components_test/splitter_model/sizes", default=[500, 300]),
)
splitter.set_property(
    "max_sizes",
    bound.data("/components_test/splitter_model/max_sizes", default=[0, 0]),
)
builder.add(splitter)

Property Updates

Declare capabilities before updating sizes or max_sizes directly.

splitter = sdk.ui.Splitter("splitter_live", [left.id, right.id])
splitter.set_property("stretch", True)
splitter.set_property("sizes", [500, 300])
splitter.set_property("max_sizes", [0, 0])
splitter.allow("sizes.set", "max_sizes.set")
builder.add(splitter)

The action updates store, data model, and live splitter properties:

return sdk.effects.respond(
    sdk.effects.ui_property_update("splitter_live", "sizes", [300, 500], surface_id=surface_id),
    sdk.effects.ui_property_update("splitter_live", "max_sizes", [0, 620], surface_id=surface_id),
)

Dynamic Children

children supports append and remove updates. Update sizes in the same action so each pane has a non-zero size after the collection change.

splitter = sdk.ui.Splitter("splitter_dynamic", [pane_1.id, pane_2.id])
splitter.set_property("stretch", True)
splitter.set_property("sizes", [500, 300])
splitter.allow("children.append", "children.remove", "sizes.set")
builder.add(splitter)

# In the action:
return sdk.effects.respond(
    sdk.effects.ui_collection_append("splitter_dynamic", "children", pane_component_dict, surface_id=surface_id),
    sdk.effects.ui_property_update("splitter_dynamic", "sizes", [500, 300, 250], surface_id=surface_id),
)

Visibility And Permissions

show_if, hide_if, and required_permissions are available on Splitter.

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

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

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

Notes

  • Splitter is horizontal in the current desktop and web renderers.
  • Keep split panes at min-height: 0 when the splitter lives inside a bounded-height layout.
  • Use scroll areas inside panes for independent scrolling.
  • Keep sizes aligned with the number of children when changing panes dynamically.