Accordion
npx @vyui/cli add accordionOverview
VyAccordion renders a collection of expandable items on top of the @vyui/core accordion primitives. It supports controlled and uncontrolled state, single or multiple selection, disabled items, static content, and per-item named slots.
Usage
Import the component from @vyui/kit and pass an items array. Each example below renders the real component live.
Multiple open items
Set type="multiple" and bind an array with v-model.
Disabled items
Set disabled on an item to prevent it from opening.
Controlled value
Bind v-model to drive the open item from outside the component.
Custom item content
Use item.slot to select a named slot for one item. Every item slot receives item, index, and open.
<script setup lang="ts">
import { VyAccordion } from '@vyui/kit'
const items = [
{ value: 'profile', label: 'Profile', slot: 'profile' },
{ value: 'help', label: 'Help', content: 'Contact [email protected].' },
]
</script>
<template>
<VyAccordion :items="items">
<template #profile="{ open }">
<view class="p-4">
<text>{{ open ? 'Profile settings are open.' : '' }}</text>
</view>
</template>
</VyAccordion>
</template>
Features and behavior
type="single"allows one open item and is the default.type="multiple"allows several.- In single mode,
collapsibledefaults totrue, so the current item can be closed. modelValuecontrols the open item or items;defaultValueinitializes uncontrolled state.- An item uses its
valueas its identity, falling back to its zero-based index converted to a string. item.trailingIconoverrides the component-leveltrailingIcon. The final fallback isappConfig.ui.icons.chevronDown, theni-lucide-chevron-down.- Content is only created when an item has
content, a matching named slot, thecontentslot, or thebodyslot. unmountOnHidedefaults totrue, removing closed content from the rendered tree.
Accordion item
| Field | Type | Default | Description |
|---|---|---|---|
label | string | — | Text displayed in the trigger. |
icon | string | — | Leading Iconify icon name. |
trailingIcon | string | Inherited | Per-item toggle icon. |
slot | string | 'content' | Named slot used for this item's panel. |
content | string | — | Static panel text used when no slot replaces it. |
value | string | Item index | Unique open-state value. |
disabled | boolean | false | Prevents interaction with this item. |
[key: string] | any | — | Additional application data forwarded in slot props. |
API
These tables are generated directly from the component source.
Props
| Prop | Default | Type |
|---|---|---|
collapsible | true | boolean | undefined`single`-only: lets the user close the currently open item. |
defaultValue | — | string | string[] | undefinedOpen value(s) at mount time when uncontrolled. |
disabled | — | boolean | undefined |
items | — | AccordionItem[] | undefined |
modelValue | — | string | string[] | undefinedControlled open value(s). |
trailingIcon | — | string | undefinedDefault trailing icon. Defaults to `appConfig.ui.icons.chevronDown`. |
type | "single" | "single" | "multiple" | undefined`'single'` allows one open item; `'multiple'` allows many. |
ui | — | Partial<Record<"trailingIcon" | "root" | "item" | "header" | "trigger" | "content" | "body" | "bodyText" | "leadingIcon" | "label", any>> | undefined |
unmountOnHide | true | boolean | undefinedWhether closed item content should unmount. |
Emits
| Event | Payload |
|---|---|
update:modelValue | [value: string | string[] | undefined] |
Slots
All item slots receive { item: AccordionItem, index: number, open: boolean }.
| Slot | Bindings |
|---|---|
leading | { item: AccordionItem; index: number; open: boolean; } |
default | { item: AccordionItem; index: number; open: boolean; } |
trailing | { item: AccordionItem; index: number; open: boolean; } |
content | { item: AccordionItem; index: number; open: boolean; } |
body | { item: AccordionItem; index: number; open: boolean; } |
Built on @vyui/core
VyAccordion composes the headless @vyui/core accordion primitives. Use them directly when you need full control over markup and styling.
The primitive anatomy is:
<AccordionRoot>
<AccordionItem value="...">
<AccordionHeader>
<AccordionTrigger />
</AccordionHeader>
<AccordionContent />
</AccordionItem>
</AccordionRoot>
AccordionRoot props
| Prop | Default | Type |
|---|---|---|
as | — | AsTag | Component | undefinedThe element or component this component should render as. Can be overwritten by `asChild`. |
asChild | — | boolean | undefinedChange the default rendered element for the one passed as a child, merging their props and behavior. Use this when you need a component to render through a child element while keeping the primitive's props and behavior. |
collapsible | false | boolean | undefinedWhen type is "single", allows closing content when clicking trigger for an open item. When type is "multiple", this prop has no effect. |
defaultValue | — | T | undefinedThe default active value of the item(s). Use when you do not need to control the state of the item(s). |
dir | — | Direction | undefinedThe reading direction of the accordion when applicable. If omitted, assumes LTR (left-to-right) reading mode. |
disabled | false | boolean | undefinedWhen `true`, prevents the user from interacting with the accordion and all its items |
modelValue | — | T | undefinedThe controlled value of the active item(s). Use this when you need to control the state of the items. Can be bound with `v-model` |
orientation | "vertical" | DataOrientation | undefinedThe orientation of the accordion. |
type | — | SingleOrMultipleType | undefinedDetermines whether a "single" or "multiple" items can be selected at a time. This prop will overwrite the inferred type from `modelValue` and `defaultValue`. |
unmountOnHide | true | boolean | undefinedWhen `true`, the element will be unmounted on closed state. |
AccordionItem props
| Prop | Default | Type |
|---|---|---|
as | — | AsTag | Component | undefinedThe element or component this component should render as. Can be overwritten by `asChild`. |
asChild | — | boolean | undefinedChange the default rendered element for the one passed as a child, merging their props and behavior. Use this when you need a component to render through a child element while keeping the primitive's props and behavior. |
disabled | — | boolean | undefinedWhether or not an accordion item is disabled from user interaction. When `true`, prevents the user from interacting with the item. |
unmountOnHide | undefined | boolean | undefinedWhen `true`, the element will be unmounted on closed state. |
value* | — | stringA string value for the accordion item. All items within an accordion should use a unique value. |
Styling and theming
Override the component globally through appConfig.ui.accordion or locally with ui. The actual theme slots are:
| UI slot | Purpose |
|---|---|
root | Accordion root container. |
item | Item wrapper and divider. |
header | Header layout around the trigger. |
trigger | Interactive trigger row. |
content | Collapsible panel wrapper. |
body | Inner body layout. |
bodyText | Static item.content text. |
leadingIcon | Built-in leading icon. |
trailingIcon | Toggle icon, including open-state rotation. |
label | Trigger label text. |
The only theme variant is disabled, which dims the trigger and applies a disabled cursor style. The default theme uses vyui's semantic tokens, so it adapts automatically under dark mode (see Theming → Dark Mode), and uses a simple transition instead of named web accordion keyframes.
Accessibility
The core trigger exposes native Lynx button semantics and announces collapsed or expanded. Disabled triggers are announced as disabled. Keep each label or custom default slot descriptive, and do not put unrelated interactive controls inside a trigger.
Platform notes
- Built for Vue on Lynx; use native
accessibility-*behavior rather than web-onlyaria-*assumptions. - The trailing icon rotates through the
group-ui-openstate class. - When CSS inheritance is disabled, static content color is applied directly to the nested
bodyTextelement.
Related components
ActionSheetfor a temporary list of actions.Collapsiblein@vyui/corefor one headless disclosure region.Tabsfor switching between persistent peer panels.