Skip to content

Toggle Group

The ToggleGroup component renders a button group where only one item stays active at a time.

Quick Start

ToggleGroup(
    Button("List View", variant="outline-primary"),
    Button("Grid View", variant="outline-primary"),
    Button("Table View", variant="outline-primary"),
    name="view",
    values=["list", "grid", "table"],
)

Usage Scenarios

View Switcher

ToggleGroup(
    Button("List", variant="outline-primary"),
    Button("Grid", variant="outline-primary"),
    Button("Map", variant="outline-primary"),
    name="view_mode",
    values=["list", "grid", "map"],
    active_index=0,
)

Segmented Control

ToggleGroup(
    Button("Day", variant="outline-secondary"),
    Button("Week", variant="outline-secondary"),
    Button("Month", variant="outline-secondary"),
    name="period",
    values=["day", "week", "month"],
    active_index=1,
)

With Custom Active Class

ToggleGroup(
    Button("On", variant="success"),
    Button("Off", variant="outline-danger"),
    name="power",
    values=["on", "off"],
    active_cls="active",
)

Parameter Reference

Parameter Type Default Description
*buttons Any Required Button elements to include in the group
name str \| None None Name for the hidden input that stores the selected value
values list[str] \| None None Values corresponding to each button
active_index int 0 Index of the initially active button
active_cls str "active" CSS class applied to the active button
hidden_input bool True Whether to render a hidden input for form submission
**kwargs Any - Additional HTML attributes

Accessibility

  • Active button gets aria-pressed="true" and aria-current="true".
  • Inactive buttons get aria-pressed="false" and aria-current="false".
  • A hidden input is rendered for form submission when name is provided.

API Reference

faststrap.components.forms.toggle_group.ToggleGroup(*buttons, name=None, values=None, active_index=0, active_cls='active', hidden_input=True, **kwargs)

Render a button group where only one item stays active at a time.

Source code in src/faststrap/components/forms/toggle_group.py
@register(category="forms")
def ToggleGroup(
    *buttons: Any,
    name: str | None = None,
    values: list[str] | None = None,
    active_index: int = 0,
    active_cls: str = "active",
    hidden_input: bool = True,
    **kwargs: Any,
) -> Div:
    """Render a button group where only one item stays active at a time."""
    btn_list = list(buttons)
    if not btn_list:
        raise ValueError("ToggleGroup requires at least one button.")
    if values is not None and len(values) != len(btn_list):
        raise ValueError("values length must match number of buttons.")

    input_id = f"fs-toggle-{uuid4().hex[:8]}"
    safe_active_index = max(0, min(active_index, len(btn_list) - 1))

    for i, button in enumerate(btn_list):
        if not hasattr(button, "attrs"):
            continue
        button_attrs = button.attrs
        button_attrs["data-fs-toggle-item"] = "true"
        button_attrs["data-fs-value"] = values[i] if values is not None else str(i)
        current_cls = button_attrs.get("cls", "")
        if i == safe_active_index:
            button_attrs["cls"] = merge_classes(current_cls, active_cls)
            button_attrs["aria-pressed"] = "true"
            button_attrs["aria-current"] = "true"
        else:
            button_attrs["aria-pressed"] = "false"
            button_attrs["aria-current"] = "false"

    user_cls = kwargs.pop("cls", "")
    attrs: dict[str, Any] = {
        "cls": merge_classes("btn-group", user_cls),
        "role": "group",
        "data_fs_toggle_group": "true",
        "data_fs_active_class": active_cls,
    }
    if hidden_input and name:
        attrs["data_fs_input_id"] = input_id
    attrs.update(convert_attrs(kwargs))

    children: list[Any] = btn_list
    if hidden_input and name:
        selected = values[safe_active_index] if values else str(safe_active_index)
        children.append(Input(type="hidden", name=name, value=selected, id=input_id))
    return Div(*children, **attrs)