Naive UI Collapse Component
Collapse component for creating expandable/collapsible content panels, commonly used in sidebars, FAQs, and settings panels.
When to Use
Use this component when:
- FAQ sections: Expandable question and answer sections
- Sidebar navigation: Collapsible menu items
- Settings panels: Grouped configuration options
- Content organization: Hide/show detailed information
When to Invoke
Invoke this skill when:
- User needs to implement an accordion or expandable panels
- User wants nested collapsible content
- User needs controlled or uncontrolled expansion state
- User wants to customize header, arrow, or trigger areas
- User asks about disabled items or display directives
- User needs accordion mode (single panel open)
Features
- Accordion Mode: Only one panel open at a time
- Nested Support: Collapses can be nested within each other
- Arrow Placement: Left or right arrow positioning
- Custom Headers: Full header customization via slots
- Disabled Items: Individual items can be disabled
- Trigger Areas: Configurable expansion trigger areas
- Display Directive: Control DOM rendering with v-if or v-show
API Reference
Collapse Props
| Name | Type | Default | Description |
|---|---|---|---|
| accordion | boolean |
false |
Only allow one panel open at a time. |
| arrow-placement | 'left' | 'right' |
'left' |
Arrow placement side of text. |
| default-expanded-names | string | number | Array<string | number> | null |
null |
Pre-expanded panels (uncontrolled). |
| display-directive | 'if' | 'show' |
'if' |
Display directive (v-if or v-show). |
| expanded-names | string | number | Array<string | number> | null |
undefined |
Expanded panels (controlled). |
| trigger-areas | Array<'main' | 'arrow' | 'extra'> |
['main', 'arrow', 'extra'] |
Expansion trigger areas. |
| on-item-header-click | (data: { name, expanded, event }) => void |
undefined |
Callback when title is clicked. |
| on-update:expanded-names | (expandedNames) => void |
undefined |
Callback when expanded names change. |
CollapseItem Props
| Name | Type | Default | Description |
|---|---|---|---|
| disabled | boolean |
false |
Whether the item is disabled. |
| display-directive | 'if' | 'show' |
undefined |
Display directive (overrides parent). |
| name | string | number |
random string | Item identifier (should be unique). |
| title | string |
undefined |
Title. |
Collapse Slots
| Name | Parameters | Description |
|---|---|---|
| arrow | { collapsed } |
Custom icons for folding panels. |
| default | () |
The contents of the collapsible panel. |
| header | { collapsed } |
The content of the header. |
CollapseItem Slots
| Name | Parameters | Description |
|---|---|---|
| arrow | { collapsed } |
Custom icon for the item. |
| default | () |
The contents of the panel node. |
| header | { collapsed } |
The content of the header. |
| header-extra | { collapsed } |
Extra content on the right side. |
Basic Usage
Basic Collapse
<template>
<n-collapse>
<n-collapse-item title="Introduction" name="1">
<div>Naive UI is a Vue 3 component library.</div>
</n-collapse-item>
<n-collapse-item title="Features" name="2">
<div>Rich components, TypeScript support, and more.</div>
</n-collapse-item>
<n-collapse-item title="Installation" name="3">
<div>npm install naive-ui</div>
</n-collapse-item>
</n-collapse>
</template>
Accordion Mode
<template>
<n-collapse accordion>
<n-collapse-item title="Question 1" name="1">
<div>Answer to question 1.</div>
</n-collapse-item>
<n-collapse-item title="Question 2" name="2">
<div>Answer to question 2.</div>
</n-collapse-item>
<n-collapse-item title="Question 3" name="3">
<div>Answer to question 3.</div>
</n-collapse-item>
</n-collapse>
</template>
Arrow Placement Right
<template>
<n-collapse arrow-placement="right">
<n-collapse-item title="Settings" name="1">
<div>Configuration options here.</div>
</n-collapse-item>
<n-collapse-item title="Advanced" name="2">
<div>Advanced settings here.</div>
</n-collapse-item>
</n-collapse>
</template>
Common Patterns
Nested Collapse
<template>
<n-collapse>
<n-collapse-item title="Category 1" name="1">
<n-collapse>
<n-collapse-item title="Sub-item 1" name="1-1">
<div>Content for sub-item 1</div>
</n-collapse-item>
<n-collapse-item title="Sub-item 2" name="1-2">
<div>Content for sub-item 2</div>
</n-collapse-item>
</n-collapse>
</n-collapse-item>
<n-collapse-item title="Category 2" name="2">
<div>Content for category 2</div>
</n-collapse-item>
</n-collapse>
</template>
Default Expanded
<template>
<n-collapse :default-expanded-names="['2', '3']">
<n-collapse-item title="Panel 1" name="1">
<div>Content 1</div>
</n-collapse-item>
<n-collapse-item title="Panel 2" name="2">
<div>Content 2 (expanded by default)</div>
</n-collapse-item>
<n-collapse-item title="Panel 3" name="3">
<div>Content 3 (expanded by default)</div>
</n-collapse-item>
</n-collapse>
</template>
Controlled Collapse
<template>
<n-space vertical>
<n-button @click="expandedNames = ['1']">Open First</n-button>
<n-button @click="expandedNames = ['2']">Open Second</n-button>
<n-button @click="expandedNames = []">Close All</n-button>
<n-collapse v-model:expanded-names="expandedNames">
<n-collapse-item title="Panel 1" name="1">
<div>Content 1</div>
</n-collapse-item>
<n-collapse-item title="Panel 2" name="2">
<div>Content 2</div>
</n-collapse-item>
</n-collapse>
</n-space>
</template>
<script setup>
import { ref } from 'vue'
const expandedNames = ref([])
</script>
Custom Header and Extra
<template>
<n-collapse>
<n-collapse-item name="1">
<template #header>
<n-text strong>Custom Header</n-text>
</template>
<template #header-extra>
<n-tag size="small" type="success">New</n-tag>
</template>
<div>Content goes here</div>
</n-collapse-item>
<n-collapse-item name="2">
<template #header>
<n-space align="center">
<n-icon><SettingsIcon /></n-icon>
<span>Settings</span>
</n-space>
</template>
<template #header-extra>
<n-badge :value="5" />
</template>
<div>Settings content</div>
</n-collapse-item>
</n-collapse>
</template>
Custom Arrow Icon
<template>
<n-collapse>
<template #arrow="{ collapsed }">
<n-icon :component="collapsed ? ChevronRight : ChevronDown" />
</template>
<n-collapse-item title="Panel 1" name="1">
<div>Content 1</div>
</n-collapse-item>
<n-collapse-item title="Panel 2" name="2">
<div>Content 2</div>
</n-collapse-item>
</n-collapse>
</template>
Disabled Item
<template>
<n-collapse>
<n-collapse-item title="Available" name="1">
<div>This panel can be expanded.</div>
</n-collapse-item>
<n-collapse-item title="Disabled" name="2" disabled>
<div>This panel cannot be expanded.</div>
</n-collapse-item>
<n-collapse-item title="Available" name="3">
<div>This panel can be expanded.</div>
</n-collapse-item>
</n-collapse>
</template>
Trigger Areas
<template>
<n-collapse :trigger-areas="['main', 'arrow']">
<n-collapse-item title="Click header or arrow" name="1">
<template #header-extra>
<n-tag>Extra area won't trigger</n-tag>
</template>
<div>Content here</div>
</n-collapse-item>
</n-collapse>
</template>
Display Directive (Keep DOM)
<template>
<n-collapse display-directive="show">
<n-collapse-item title="Preserved Content" name="1">
<div>This content stays in DOM when collapsed.</div>
</n-collapse-item>
</n-collapse>
</template>
Item Header Click Event
<template>
<n-collapse @item-header-click="handleHeaderClick">
<n-collapse-item title="Panel 1" name="1">
<div>Content 1</div>
</n-collapse-item>
<n-collapse-item title="Panel 2" name="2">
<div>Content 2</div>
</n-collapse-item>
</n-collapse>
</template>
<script setup>
const handleHeaderClick = ({ name, expanded, event }) => {
console.log(`Panel ${name} is now ${expanded ? 'expanded' : 'collapsed'}`)
}
</script>
Best Practices
Use unique names: Each
n-collapse-itemshould have a uniquenameprop<n-collapse-item name="unique-id" title="Title">Accordion for single selection: Use accordion mode when only one panel should be open
<n-collapse accordion>Use display-directive wisely: Use
showto preserve DOM state (like form inputs)<n-collapse display-directive="show">Default expanded in accordion: In accordion mode, use a single value (not array)
<n-collapse accordion default-expanded-names="1">Controlled vs uncontrolled: Use
expanded-namesfor controlled,default-expanded-namesfor uncontrolledAccessibility: Provide meaningful titles for screen readers
Nested structure: Be careful with deeply nested collapses for UX