Skip to content

Expander

Expander is a collapsible container with a clickable header (title + chevron) and expandable content area.

It provides a way to show/hide content sections, reducing visual clutter while keeping related controls accessible.


Quick start

import bootstack as bs

app = bs.App()

exp = bs.Expander(app, title="Settings")
exp.pack(fill="x", padx=10, pady=5)

content = exp.add()
bs.CheckButton(content, text="Enable notifications").pack(anchor="w")
bs.CheckButton(content, text="Dark mode").pack(anchor="w")
bs.CheckButton(content, text="Auto-save").pack(anchor="w")

app.mainloop()

When to use

Use Expander when:

  • you want to hide optional or advanced settings by default

  • screen space is limited and content can be revealed on demand

  • grouping related controls under a collapsible header improves scanability

Consider a different control when:

  • content should always be visible -- use LabelFrame or Frame

  • you need multiple exclusive sections (only one open at a time) -- use Accordion

  • you need tabbed navigation -- use Notebook


Appearance

Styling

The chevron button uses foreground-ghost by default for a subtle appearance. When accent is provided, the chevron inherits that style.

bs.Expander(app, title="Primary Section", accent="primary")

Border

Use show_border=True to add a visible border around the expander.

bs.Expander(app, title="Bordered", show_border=True)

Custom icons

Override the default chevron icons with custom ones.

bs.Expander(
    app,
    title="Custom Icons",
    icon_expanded={'name': 'dash', 'size': 16},
    icon_collapsed={'name': 'plus', 'size': 16},
)

Icon position

Place the chevron before or after the title.

bs.Expander(app, title="Icon Before", icon_position="before")
bs.Expander(app, title="Icon After", icon_position="after")  # default

Examples & patterns

Adding content

Use add() to get a content frame for placing widgets.

exp = bs.Expander(app, title="Options")
exp.pack(fill="x", padx=10, pady=5)

content = exp.add()  # Returns a Frame
bs.Label(content, text="Option 1").pack()
bs.Entry(content).pack(fill="x")

Frame options (padding, color, etc.) can be passed directly:

content = exp.add(padding=10, accent="primary")

Calling add() multiple times returns the same frame (idempotent).

Starting collapsed

Set expanded=False to start in collapsed state.

exp = bs.Expander(app, title="Advanced", expanded=False)

Non-collapsible section

Set collapsible=False to create a section that cannot be toggled (always visible, no chevron).

exp = bs.Expander(app, title="Always Visible", collapsible=False)

Highlight mode

Set highlight=True to show a visual 'selected' state on the header when expanded. This is useful for accordion-style interfaces where the open section should be visually distinct.

exp = bs.Expander(
    app,
    title="Highlighted Section",
    highlight=True,
    accent="primary",
    variant="solid"
)

When highlight=True, the header uses the TTK selected state, which style builders can target for distinct visual treatment.

Programmatic control

exp.expand()    # Expand the content
exp.collapse()  # Collapse the content
exp.toggle()    # Toggle current state

# Property access
if exp.expanded:
    print("Currently expanded")

exp.expanded = False  # Collapse via property

Responding to toggle events

def on_toggle(event):
    print(f"Expanded: {event.data['expanded']}")

exp.on_toggle(on_toggle)

Or bind directly:

exp.bind('<<Toggle>>', lambda e: print(e.data))

Expand/Collapse all

expanders = [exp1, exp2, exp3]

def expand_all():
    for e in expanders:
        e.expand()

def collapse_all():
    for e in expanders:
        e.collapse()

Behavior

  • Clicking anywhere on the header toggles the content (not just the chevron).

  • Keyboard accessible: focus the header, then press Enter or Space to toggle.

  • The <<Toggle>> event fires with event.data = {'expanded': bool}.

  • Content uses pack_forget()/pack() for show/hide, so layout reflows automatically.


Configuration

Dynamic configuration

exp.configure(title="New Title")
exp.configure(collapsible=False)
exp.configure(icon_expanded={'name': 'caret-up', 'size': 14})

Additional resources

  • Accordion -- manages multiple expanders with mutual exclusion

  • LabelFrame -- always-visible labeled container

  • Frame -- general-purpose container

  • Notebook -- tabbed content switching

  • PanedWindow -- resizable split panes

Framework concepts

API reference