Skip to main content
The Accordion component provides expandable/collapsible content sections with smooth animations.

Basic Usage

import reflex_ui as ui

ui.accordion(
    items=[
        {"trigger": "Section 1", "content": "Content for section 1"},
        {"trigger": "Section 2", "content": "Content for section 2"},
        {"trigger": "Section 3", "content": "Content for section 3"}
    ]
)

Item Structure

Each item is a dictionary with:
trigger
str | Component
required
The clickable header text or component
content
str | Component
required
The collapsible content
value
str
Unique identifier (defaults to “item-”)
disabled
bool
default:"False"
Disables this specific item

With Components

ui.accordion(
    items=[
        {
            "trigger": rx.text("What is Reflex?", weight="bold"),
            "content": rx.text("Reflex is a framework for building web apps in pure Python.")
        },
        {
            "trigger": "How do I get started?",
            "content": rx.el.div(
                rx.text("Install with: "),
                rx.code("pip install reflex")
            )
        }
    ]
)

Controlled State

class State(rx.State):
    open_items: list[str] = ["item-1"]

ui.accordion(
    items=[...],
    value=State.open_items,
    on_value_change=State.set_open_items
)
value
list[str]
Currently expanded items (controlled)
default_value
list[str]
Initially expanded items (uncontrolled)
on_value_change
EventHandler[list[str]]
Event fired when expanded items change

Multiple vs Single

multiple
bool
default:"True"
Allow multiple items to be open simultaneously
# Only one item open at a time
ui.accordion(
    items=[...],
    multiple=False
)

Other Props

disabled
bool
default:"False"
Disables all accordion items
orientation
Literal['horizontal', 'vertical']
default:"vertical"
Visual orientation for keyboard navigation
loop_focus
bool
default:"True"
Whether arrow keys loop to first item at end
keep_mounted
bool
default:"False"
Keep closed panels in DOM for animations

Compositional API

For full control, compose manually:
ui.accordion.root(
    ui.accordion.item(
        ui.accordion.header(
            ui.accordion.trigger(
                "Custom Trigger",
                ui.icon("PlusSignIcon")
            )
        ),
        ui.accordion.panel(
            rx.el.div(
                "Panel content",
                class_name="py-4 px-6"
            )
        ),
        value="custom-1"
    ),
    ui.accordion.item(
        # ... more items
    )
)

Accordion Components

accordion.root

Container for all accordion items.
ui.accordion.root(
    # accordion.item components
    multiple=True
)

accordion.item

Groups a trigger with its panel.
ui.accordion.item(
    ui.accordion.header(...),
    ui.accordion.panel(...),
    value="unique-id"
)

accordion.header

Wrapper for the trigger (for semantic HTML).
ui.accordion.header(
    ui.accordion.trigger(...)
)

accordion.trigger

Clickable button to toggle the panel.
ui.accordion.trigger(
    "Section Title",
    ui.icon("ChevronDown")
)

accordion.panel

Collapsible content area.
ui.accordion.panel(
    "Content here",
    keep_mounted=True
)

Styling Classes

Access predefined styles via ui.accordion.class_names:
  • ROOT: Container with borders and shadows
  • ITEM: Individual item (empty by default)
  • HEADER: Header wrapper
  • TRIGGER: Clickable trigger button with hover states
  • PANEL: Content panel with height animation
  • PANEL_DIV: Inner padding wrapper
  • TRIGGER_ICON: Animated icon (rotates when open)

Custom Icons

The default trigger icon rotates 45° when open (creating an X from a +). Customize by using the compositional API:
ui.accordion.trigger(
    "My Section",
    ui.icon("ChevronDownIcon", class_name="transition-transform group-data-[panel-open]:rotate-180")
)

Dynamic Items

Use reactive lists:
class State(rx.State):
    faq_items: list[dict] = [
        {"trigger": "Q1", "content": "A1"},
        {"trigger": "Q2", "content": "A2"}
    ]

ui.accordion(items=State.faq_items)

Implementation Details

From source code at reflex_ui/components/base/accordion.py:169:
  • Built on Base UI Accordion primitives
  • High-level API auto-generates structure from items list
  • Supports both static lists and reactive Var lists
  • Height animation via CSS transitions on --accordion-panel-height
  • Plus icon rotates and scales when item opens
  • Border dividers between items

Build docs developers (and LLMs) love