Biji UI

Accordion

An accordion is a vertically stacked list of items, such as labels or thumbnails, that can be toggled to reveal or hide additional content.

Installation

biji-ui = { version = "0.5.0", features = ["accordion"] }

Usage

use std::time::Duration;
use leptos::prelude::*;
use biji_ui::components::accordion;

#[component]
pub fn MyAccordion() -> impl IntoView {
    let items = [
        ("What is biji-ui?", "A headless UI component library for Leptos."),
        ("Is it accessible?", "Yes, it follows WAI-ARIA patterns."),
    ];

    view! {
        <accordion::Root class="w-full" allow_loop=true>
            {items.into_iter().map(|(title, content)| view! {
                <accordion::Item class="border-b border-border">
                    <accordion::Toggle class="flex w-full items-center justify-between py-5 text-sm font-medium outline-none">
                        {title}
                    </accordion::Toggle>
                    <accordion::Content
                        class="pb-4 text-sm"
                        show_class="opacity-100 transition duration-150 ease-in"
                        hide_class="opacity-0 transition duration-200 ease-out"
                        hide_delay={Duration::from_millis(200)}
                    >
                        {content}
                    </accordion::Content>
                </accordion::Item>
            }).collect::<Vec<_>>()}
        </accordion::Root>
    }
}

RootWith

Use RootWith to access AccordionState inline via the let: binding. The root field exposes the items map so you can read which items are open.

0 of 3 items open

use std::time::Duration;
use leptos::prelude::*;
use biji_ui::components::accordion;

#[component]
pub fn MyAccordion() -> impl IntoView {
    let items = [
        ("What is biji-ui?", "A headless UI component library for Leptos."),
        ("Is it accessible?", "Yes, it follows WAI-ARIA patterns."),
    ];

    view! {
        <accordion::RootWith class="w-full" let:acc>
            <p class="mb-2 text-xs text-muted-foreground">
                {move || {
                    let open_count = acc.root.get().items.with(|m| {
                        m.values().filter(|i| i.open.get()).count()
                    });
                    format!("{} item(s) open", open_count)
                }}
            </p>
            {items.into_iter().map(|(title, content)| view! {
                <accordion::Item class="border-b border-border">
                    <accordion::Toggle class="flex w-full items-center justify-between py-5 text-sm font-medium outline-none">
                        {title}
                    </accordion::Toggle>
                    <accordion::Content
                        class="pb-4 text-sm"
                        show_class="opacity-100 transition duration-150"
                        hide_class="opacity-0 transition duration-200"
                        hide_delay={Duration::from_millis(200)}
                    >
                        {content}
                    </accordion::Content>
                </accordion::Item>
            }).collect::<Vec<_>>()}
        </accordion::RootWith>
    }
}

API Reference

Root / RootWith

NameTypeDefaultDescription
classString""CSS class applied to the root element.
allow_loopboolfalseWhen true, keyboard navigation wraps from the last item back to the first and vice versa.

Item

NameTypeDefaultDescription
classString""CSS class applied to the item wrapper element.
disabledboolfalseWhen true, prevents the item from being opened or receiving focus.

Toggle

NameTypeDefaultDescription
classString""CSS class applied to the toggle button.

Content

NameTypeDefaultDescription
classString""CSS class applied to the content wrapper.
show_classString""CSS class applied when the content is visible.
hide_classString""CSS class applied while the content is hiding (during the transition out).
hide_delayDuration200msHow long to wait before unmounting the content after closing begins. Should match your CSS transition duration.

Data Attributes

AttributeDescription
data-state"open" when the item is expanded; "closed" when collapsed. Present on Item and Toggle.
data-highlightedPresent on Item and Toggle when the item has keyboard focus.
data-disabledPresent on Item and Toggle when the item is disabled.

Keyboard Navigation

KeyDescription
ArrowDownMoves focus to the next item's toggle.
ArrowUpMoves focus to the previous item's toggle.
HomeMoves focus to the first item's toggle.
EndMoves focus to the last item's toggle.
Enter / SpaceToggles the focused item open or closed.