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
| Name | Type | Default | Description |
|---|---|---|---|
| class | String | "" | CSS class applied to the root element. |
| allow_loop | bool | false | When true, keyboard navigation wraps from the last item back to the first and vice versa. |
Item
| Name | Type | Default | Description |
|---|---|---|---|
| class | String | "" | CSS class applied to the item wrapper element. |
| disabled | bool | false | When true, prevents the item from being opened or receiving focus. |
Toggle
| Name | Type | Default | Description |
|---|---|---|---|
| class | String | "" | CSS class applied to the toggle button. |
Content
| Name | Type | Default | Description |
|---|---|---|---|
| class | String | "" | CSS class applied to the content wrapper. |
| show_class | String | "" | CSS class applied when the content is visible. |
| hide_class | String | "" | CSS class applied while the content is hiding (during the transition out). |
| hide_delay | Duration | 200ms | How long to wait before unmounting the content after closing begins. Should match your CSS transition duration. |
Data Attributes
| Attribute | Description |
|---|---|
| data-state | "open" when the item is expanded; "closed" when collapsed. Present on Item and Toggle. |
| data-highlighted | Present on Item and Toggle when the item has keyboard focus. |
| data-disabled | Present on Item and Toggle when the item is disabled. |
Keyboard Navigation
| Key | Description |
|---|---|
| ArrowDown | Moves focus to the next item's toggle. |
| ArrowUp | Moves focus to the previous item's toggle. |
| Home | Moves focus to the first item's toggle. |
| End | Moves focus to the last item's toggle. |
| Enter / Space | Toggles the focused item open or closed. |