<- Back to Forms Components

Purpose

Button renders an explicit user action trigger. It can dispatch an action, pass static or bound context, collect mounted input values, show a loading state while an action is pending, and receive runtime property updates.

Constructor

Button(
    id: str,
    label: str,
    action: str | None = None,
    params: dict | None = None,
    icon: str | None = None,
    variant: str = "default",
    mode: str = "solid",
    appearance: str | None = None,
    btnsize: str = "normal",
    shape: str = "default",
)

Properties

Property Type Default Description
label str or literal/bound payload required Visible text. Python constructor wraps plain labels as literalString.
action str or action object none Action dispatched on click. Action objects can include confirm.
params dict {} Extra click context merged with the action context.
icon str none Icon name. Remix icon names can use ric.*, ri.*, or ri-* forms.
variant str default Visual intent. Documented values are default, primary, success, warning, info, and danger.
mode str solid Legacy appearance mode: solid, ghost, or link.
appearance str none Optional appearance override such as default, ghost, or link.
btnsize str normal Size. Supports sm, default, lg and legacy small, normal, large.
shape str default default, round, or icon. icon is normalized as a round icon button by the web client.
active bool or condition/binding false Active visual state.
collect_input_ids list[str] [] Input ids collected and included in click context.
track_loading str | list[str] none Action names that put the button in loading state while pending.
show_if / hide_if condition none Shared visibility rules.
required_permissions list[str] [] Required permissions before rendering.
capabilities list[str] default interactive capabilities Required for direct runtime updates such as label.set, active.set, action.set, and params.set.

Variants, Modes And Icons

The test page renders variant matrices for solid, ghost and link modes, plus icon and icon-only combinations.

sdk.ui.Button("save", "Save", variant="primary", icon="ric.save-line")
sdk.ui.Button("delete", "Delete", variant="danger", icon="ric.delete-bin-line")
sdk.ui.Button("ghost", "Ghost", variant="warning", mode="ghost", icon="ric.alert-line")
sdk.ui.Button("link", "Open", variant="info", mode="link", icon="ric.external-link-line")
sdk.ui.Button("icon_only", "", variant="primary", shape="round", icon="ric.settings-3-line")
sdk.ui.Button("icon_alias", "", variant="default", shape="icon", icon="ric.settings-3-line")

Action Context

In Python, pass action as the action name and params as extra context. In YAML, either use the same action plus params shape or the action object form.

Module actions used by UI components must be fully qualified, for example components.test_button_echo. The Python decorator keeps the local action name, while the component dispatch uses module.action. See Action Dispatch.

button = sdk.ui.Button(
    "run_import",
    "Run import",
    action="components.test_button_echo",
    params={"source": "toolbar"},
    variant="primary",
    icon="ric.play-circle-line",
)

The action receives the merged context. If collect_input_ids is present, the clients also collect the current values of those mounted inputs.

field = sdk.ui.TextField("title_input", "Title", "Initial value")
button = sdk.ui.Button(
    "collect_title",
    "Collect input",
    action="components.test_button_collect",
    params={"input_id": "title_input"},
    variant="primary",
)
button.collect_input_ids("title_input")

Action Confirmation

Use an action object with confirm to require confirmation before the click action is dispatched. If the user cancels the dialog, no backend action is sent. The component test page exposes a trigger counter and the last received payload so the dispatch can be checked directly after confirming.

button = sdk.ui.Button(
    "confirm_python",
    sdk.i18n.t("components.button.confirm.python_primary"),
    variant="primary",
)
button.set_prop(
    "action",
    {
        "name": "components.button_confirm_action",
        "context": {"source": "python_primary"},
        "confirm": {
            "text": sdk.i18n.t("components.button.confirm.prompt"),
            "confirm_text": sdk.i18n.t("components.button.confirm.accept"),
            "cancel_text": sdk.i18n.t("components.button.confirm.cancel"),
        },
    },
)

Bindings And Direct Updates

label and active can be bound to page store or the surface data model in Python. In YAML, label is a constructor argument and is serialized as a literal label by the loader, so the YAML binding example uses active. Direct property updates can still target label in both Python and YAML when the button declares label.set.

from democrai.sdk.ui import bound

store_button = sdk.ui.Button("store_button", "Store label", variant="primary")
store_button.set_property(
    "label",
    bound.store(
        "/components_test/button/store_label",
        scope="page",
        default={"literalString": "Store label"},
    ),
)

data_button = sdk.ui.Button("data_button", "Data label", variant="default")
data_button.set_property(
    "label",
    bound.data(
        "/components_test/button_model/label",
        default={"literalString": "Data label"},
    ),
)

active_button = sdk.ui.Button("active_button", "Active", mode="ghost")
active_button.set_property(
    "active",
    bound.store("/components_test/button/active", scope="page", default=False),
)

live_button = sdk.ui.Button("live_button", "Direct label", variant="primary")
live_button.allow("label.set", "active.set", "action.set", "params.set")

A direct label update uses the current surface id:

return sdk.effects.respond(
    sdk.effects.ui_property_update(
        "live_button",
        "label",
        {"literalString": "Direct label updated"},
        action="set",
        surface_id=ctx["_surface_id"],
    )
)

Visibility And Permissions

Buttons support the shared show_if, hide_if, and required_permissions contract.

button = sdk.ui.Button("guarded_button", "Guarded", variant="primary")
button.set_show_if({
    "conditions": [
        {"left": bound.store("/components_test/button/show", scope="page", default=True), "op": "==", "right": True}
    ]
})
button.set_hide_if({
    "conditions": [
        {"left": bound.store("/components_test/button/hide", scope="page", default=False), "op": "==", "right": True}
    ]
})
button.set_required_permissions(["components.button.use"])

Behavior

  • Desktop normalizes small/normal/large to sm/default/lg.
  • Web maps shape: icon to a round icon button.
  • mode: ghost and mode: link override the base visual style.
  • track_loading disables the button and swaps the icon to a loading indicator while a tracked action is pending.

Screenshots

Desktop preview:

Button desktop

Web preview:

Button web