Accordion
Organise related questions into expandable sections.

use blinc_cn as cn;
use blinc_layout::prelude::*;
pub fn accordion_demo() -> Div {
div().class("demo-wide").child(
cn::accordion()
.item("start", "What is Blinc?", || {
div()
.class("demo-accordion-copy")
.child(text("A native UI framework built with Rust."))
})
.item("style", "Can I make it my own?", || {
div()
.class("demo-accordion-copy")
.child(text("Use CSS classes and theme variables to restyle every part."))
}),
)
}
@layer components {
.cn-accordion,
.cn-accordion-trigger,
.cn-accordion-content {
font-family: var(--font-sans);
}
.cn-accordion-content {
line-height: var(--leading-normal);
}
.cn-accordion-trigger:focus-visible {
outline: 2px solid var(--focus-ring);
outline-offset: 2px;
}
.cn-chevron {
transition: transform var(--duration-normal) var(--ease-state);
}
.cn-accordion-trigger[data-state="open"] > .cn-chevron {
transform: rotate(180deg);
}
.cn-accordion {
background: var(--cn-accordion-bg, var(--surface));
border: 1.5px solid var(--cn-accordion-border, var(--border));
border-radius: var(--radius-xl);
box-shadow: var(--shadow-md);
}
.cn-accordion-separator {
background: var(--cn-accordion-border, var(--border));
}
.cn-accordion-trigger > .cn-chevron {
color: var(--text-secondary);
}
.cn-accordion-trigger {
padding: var(--space-4) var(--space-3);
cursor: pointer;
color: var(--text-primary);
font-size: var(--text-sm);
}
.cn-accordion-trigger:hover {
background: var(--surface-overlay);
}
.cn-accordion-content {
background: var(--cn-accordion-content-bg, var(--background));
border-top: 1px solid var(--border);
color: var(--text-secondary);
overflow: hidden;
}
.cn-accordion-content[data-state="closed"] {
height: 0;
border-top-width: 0;
}
}
Usage and properties
Organise related questions into expandable sections. Apply CSS after the component layer to restyle the documented parts.
Use the installation guide to add blinc_cn and its component stylesheet. Create the fixture bindings once, and return the demo from your UI builder. Values marked Bound accept Signal/Computed sources where the API supports them; structural options configure the component at construction.
| Property | Type | Update model | This example |
|---|---|---|---|
item(key, label, content) | strings and child builder | Construction | Project details |
mode | AccordionMode | Construction | See the compiled example |
Keyboard and interaction
Tab reaches each trigger; Enter or Space opens or closes its section. :focus-visible marks keyboard focus.
Customizing it
Add application CSS after the default component layer. These selectors are the restyling surface for this component:
.cn-accordion.cn-accordion-trigger.cn-chevron.cn-accordion-content.demo-accordion-copy.cn-accordion-separator
Theme and component variables: --primary, --text-primary, --text-secondary, --surface, --border, --radius-default, --duration-fast, --ease-state.
Built-in themes
The Live theme control installs Blinc's own theme bundles, including their colours, focus rings, corner shapes and motion tokens.
pub fn theme_bundle_for(name: &str) -> blinc_theme::ThemeBundle {
match name {
"restrained" => blinc_theme::RestrainedTheme::bundle(),
"expressive" => blinc_theme::ExpressiveTheme::bundle(),
_ => blinc_theme::HybridTheme::bundle(),
}
.with_css(blinc_cn::cn_styles::CN_STYLES)
}Download the default widget and component stylesheets. Sample assets and licenses are available in the asset guide.
Documentation
From the canonical component guide.
Add each section with a key, label and body builder. One section opens at a time by default:
accordion()
.default_open("start")
.item("start", "How do I get started?", || {
div().child(text("Install Blinc and create an application."))
})
.item("toolchain", "Which toolchain do I need?", || {
div().child(text("Blinc 0.6 requires Rust 1.89 or newer."))
})
.multi_open() allows several sections to stay open:
accordion().multi_open()
.item("account", "Account", || div().child(text("Account details")))
.item("billing", "Billing", || div().child(text("Billing details")))
For application-controlled sections, use .item_with_state(...):
let open = ctx.use_signal(true);
accordion().item_with_state("help", "Help", open, || {
div().child(text("The application can open or close this section."))
})
Each section's trigger and body use .cn-accordion-trigger and
.cn-accordion-content, with data-state="open" or "closed".
Content wrappers and spacing belong to the application. Accordion renders the
body returned by the closure directly; add your own padded container when needed:
accordion().item("help", "Help", || {
div().class("help-copy").child(text("How can we help?"))
})
.help-copy { padding: 12px; }
Keep padding on that caller-owned container so .cn-accordion-content can fold
to zero height.
Override those rules instead of selecting colours in the body builder.
Platforms and version
The component API is available in Blinc 0.6.0. The Live example runs in a dedicated worker and requires a compatible GPU surface. Preview and Code remain available when Live cannot start. The canvas has a descriptive label; a full screen-reader DOM mirror is not provided. The gallery integration is based on revision e2e55c24e078.
Recordings and live demos use the default Hybrid theme with bundled Noto Sans. The recording uses a 560 × 320 logical viewport at twice that resolution. Live follows its container and actual display density. Source base revision · Exact build source · Artifact versions and checksums · Font license.