icon

Morainev0.5.0

Accordion
elementsaccordion

Accordion

Stacked disclosure component with single or multiple expanded sections.

Import#

import { Accordion } from 'moraine'

Slot Structure#

Stacked item list where each item has a clickable header and collapsible content.

root
└── item (×n)
├── header
│ └── trigger
│ ├── leading (Icon, optional)
│ ├── label (optional)
│ └── trailing (Icon, optional)
└── content (optional)

Examples#

Single#

Single-open mode with controlled state and icon leading/trailing slots.

function Single() {
const [openValue, setOpenValue] = createSignal<string[]>(['shipping'])
return (
<div class="w-lg space-y-3">
<Accordion
value={openValue()}
onChange={setOpenValue}
items={[
{
value: 'shipping',
label: 'Shipping information',
leading: 'i-lucide-truck',
content:
'Orders are processed in 1-2 business days and delivered in 3-5 business days.',
},
{
value: 'returns',
label: 'Returns policy',
leading: 'i-lucide-rotate-ccw',
content: 'Returns are accepted within 30 days of delivery.',
},
{
value: 'support',
label: 'Support',
leading: 'i-lucide-life-buoy',
content: 'Reach support any time at [email protected].',
},
]}
/>
<p class="text-xs text-muted-foreground">Current open value: {openValue()?.[0] ?? 'none'}</p>
</div>
)
}

Multiple#

Multiple-open mode with custom trailing icons.

function Multiple() {
return (
<Accordion
multiple
defaultValue={['a']}
items={[
{
value: 'a',
label: 'Account setup',
content: 'Create your account and verify email.',
},
{
value: 'b',
label: 'Team invite',
content: 'Invite teammates to your workspace.',
},
{
value: 'c',
label: 'Billing',
content: 'Add a payment method to continue.',
},
]}
classes={{
root: 'max-w-xl rounded-lg b-1 b-border border-border bg-background',
trigger: 'px-4',
content: 'px-4 text-foreground',
}}
/>
)
}

Disabled + Custom Content#

Mix disabled items with rich JSX content blocks.

function DisabledCustomContent() {
return (
<Accordion
defaultValue={['setup']}
trailing="icon-plus"
items={[
{
value: 'setup',
label: 'Setup checklist',
leading: 'i-lucide-list-checks',
content: (
<div class="space-y-2">
<p>Complete these steps before inviting your team:</p>
<ul class="pl-5 list-disc space-y-1">
<li>Create workspace profile</li>
<li>Configure authentication</li>
<li>Enable notifications</li>
</ul>
<div class="text-xs text-muted-foreground p-2 rounded-md bg-muted">
Tip: You can finish the checklist later from Settings.
</div>
</div>
),
},
{
value: 'security',
label: 'Security review (Locked)',
leading: 'i-lucide-shield-check',
disabled: true,
content: 'Available on Pro plan and above.',
},
{
value: 'integrations',
label: 'Integrations',
leading: 'i-lucide-plug',
content: (
<div class="pt-2 space-y-2">
<p>Connect your tools to automate the workflow.</p>
<p>
Supported: <strong>GitHub</strong>, <strong>Slack</strong>, and{' '}
<strong>Notion</strong>.
</p>
</div>
),
},
]}
classes={{
root: 'max-w-xl rounded-lg b-1 b-border border-border bg-background',
trigger: 'px-3',
content: 'px-4 text-foreground',
}}
/>
)
}

API Reference#

Attributes#

Slotroot1 attribute
Container that owns the accordion item collection and shared state attributes.

Data Attributes

1
Data AttributeDescription
data-disabled
Present when the component or item is disabled.

Props#

PropTypeDefaultDescription
classClassValue
Class applied to the component root or trigger element.
classesAccordionT.Classes | undefined
collapsibleboolean | undefinedtrue
Whether the last expanded item can be collapsed.
defaultValuestring[] | undefined[]
Default list of expanded item values for uncontrolled usage.
disabledboolean | undefinedfalse
Whether the entire accordion is disabled.
idstring | undefined
Unique identifier for the accordion root element.
itemsAccordionT.Item[] | undefined
Array of accordion items to render.
loopFocusboolean | undefinedtrue
Whether arrow-key focus wraps from the last trigger to the first and vice versa.
multipleboolean | undefinedfalse
Whether multiple accordion items can be expanded at the same time.
onChange((value: string[]) => void) | undefined
Callback when the expanded item values change.
refJSX.HTMLElementTags["div"] extends { ref?: infer Ref; } ? Ref : never | undefined
styleJSX.CSSProperties | undefined
stylesAccordionT.Styles | undefined
trailingIconT.Nameicon-chevron-down
Trailing icon name for all accordion items.
unmountOnHideboolean | undefinedtrue
Whether to unmount accordion content when hidden.
valuestring[] | undefined
Controlled list of expanded item values.

Items#

PropTypeDefaultDescription
contentJSX.Element
Content to display when the accordion item is expanded.
disabledboolean | undefinedfalse
Whether the accordion item is disabled.
labelJSX.Element
Header label for the accordion item.
leadingIconT.Name
Leading icon name for the accordion item.
valuestring | undefined
Unique value for the accordion item.