Components

Accordion

Source
Display collapsible sections with single or multiple open items.
Install with the CLI
npx @vyui/cli add accordion

Overview

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, collapsible defaults to true, so the current item can be closed.
  • modelValue controls the open item or items; defaultValue initializes uncontrolled state.
  • An item uses its value as its identity, falling back to its zero-based index converted to a string.
  • item.trailingIcon overrides the component-level trailingIcon. The final fallback is appConfig.ui.icons.chevronDown, then i-lucide-chevron-down.
  • Content is only created when an item has content, a matching named slot, the content slot, or the body slot.
  • unmountOnHide defaults to true, removing closed content from the rendered tree.

Accordion item

FieldTypeDefaultDescription
labelstringText displayed in the trigger.
iconstringLeading Iconify icon name.
trailingIconstringInheritedPer-item toggle icon.
slotstring'content'Named slot used for this item's panel.
contentstringStatic panel text used when no slot replaces it.
valuestringItem indexUnique open-state value.
disabledbooleanfalsePrevents interaction with this item.
[key: string]anyAdditional application data forwarded in slot props.

API

These tables are generated directly from the component source.

Props

PropDefaultType
collapsibletrueboolean | undefined

`single`-only: lets the user close the currently open item.

defaultValuestring | string[] | undefined

Open value(s) at mount time when uncontrolled.

disabledboolean | undefined
itemsAccordionItem[] | undefined
modelValuestring | string[] | undefined

Controlled open value(s).

trailingIconstring | undefined

Default trailing icon. Defaults to `appConfig.ui.icons.chevronDown`.

type"single""single" | "multiple" | undefined

`'single'` allows one open item; `'multiple'` allows many.

uiPartial<Record<"trailingIcon" | "root" | "item" | "header" | "trigger" | "content" | "body" | "bodyText" | "leadingIcon" | "label", any>> | undefined
unmountOnHidetrueboolean | undefined

Whether closed item content should unmount.

Emits

EventPayload
update:modelValue[value: string | string[] | undefined]

Slots

All item slots receive { item: AccordionItem, index: number, open: boolean }.

SlotBindings
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

PropDefaultType
asAsTag | Component | undefined

The element or component this component should render as. Can be overwritten by `asChild`.

asChildboolean | undefined

Change 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.

collapsiblefalseboolean | undefined

When type is "single", allows closing content when clicking trigger for an open item. When type is "multiple", this prop has no effect.

defaultValueT | undefined

The default active value of the item(s). Use when you do not need to control the state of the item(s).

dirDirection | undefined

The reading direction of the accordion when applicable. If omitted, assumes LTR (left-to-right) reading mode.

disabledfalseboolean | undefined

When `true`, prevents the user from interacting with the accordion and all its items

modelValueT | undefined

The 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 | undefined

The orientation of the accordion.

typeSingleOrMultipleType | undefined

Determines whether a "single" or "multiple" items can be selected at a time. This prop will overwrite the inferred type from `modelValue` and `defaultValue`.

unmountOnHidetrueboolean | undefined

When `true`, the element will be unmounted on closed state.

AccordionItem props

PropDefaultType
asAsTag | Component | undefined

The element or component this component should render as. Can be overwritten by `asChild`.

asChildboolean | undefined

Change 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.

disabledboolean | undefined

Whether or not an accordion item is disabled from user interaction. When `true`, prevents the user from interacting with the item.

unmountOnHideundefinedboolean | undefined

When `true`, the element will be unmounted on closed state.

value*string

A 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 slotPurpose
rootAccordion root container.
itemItem wrapper and divider.
headerHeader layout around the trigger.
triggerInteractive trigger row.
contentCollapsible panel wrapper.
bodyInner body layout.
bodyTextStatic item.content text.
leadingIconBuilt-in leading icon.
trailingIconToggle icon, including open-state rotation.
labelTrigger 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-only aria-* assumptions.
  • The trailing icon rotates through the group-ui-open state class.
  • When CSS inheritance is disabled, static content color is applied directly to the nested bodyText element.
  • ActionSheet for a temporary list of actions.
  • Collapsible in @vyui/core for one headless disclosure region.
  • Tabs for switching between persistent peer panels.