22
33# Vue Collapsed
44
5- Dynamic CSS height transition from _ any to auto_ and vice versa. Accordion ready.
5+ Dynamic CSS height transition from _ any value to auto_ and vice versa. Accordion- ready.
66
77[ Examples and Demo] ( https://vue-collapsed.pages.dev ) - [ Stackblitz] ( https://stackblitz.com/edit/vue-dmjqey?file=src/App.vue )
88
9- <br />
10-
11- Check out my other packages for Vue and Nuxt:
12-
13- > 🔔 ** Notivue**
14- > _ Fully-featured notification system for Vue and Nuxt._
15- > [ Visit repo ➔ ] ( https://github.com/smastrom/notivue )
16-
17- > 🌀 ** Vue Global Loader**
18- > _ Global loaders made easy for Vue and Nuxt._
19- > [ Visit repo ➔ ] ( https://github.com/smastrom/vue-global-loader )
20-
21- > 👌 ** Vue Use Active Scroll**
22- > _ Accurate TOC/sidebar links without compromises._
23- > [ Visit repo ➔ ] ( https://github.com/smastrom/vue-use-active-scroll )
24-
25- > 🔥 ** Vue Use Fixed Header**
26- > _ Turn your boring fixed header into a smart one with three lines of code._
27- > [ Visit repo ➔ ] ( https://github.com/smastrom/vue-use-fixed-header )
28-
29- <br />
30-
319## Installation
3210
3311``` shell
3412npm i vue-collapsed
35- # yarn add vue-collapsed
36- # pnpm add vue-collapsed
37- # bun add vue-collapsed
3813```
3914
40- ## Props
41-
42- | Name | Description | Type | Required |
43- | ------------ | ---------------------------------------- | ----------------------------- | ------------------ |
44- | ` when ` | Value to control collapse | boolean | :white_check_mark : |
45- | ` baseHeight ` | Collapsed height in px, defaults to ` 0 ` . | number | :x : |
46- | ` as ` | Tag to use instead of ` div ` | _ keyof_ HTMLElementTagNameMap | :x : |
47-
48- ## Emits
49-
50- | Name | Description | Type |
51- | ------------ | ----------------------------- | ---------- |
52- | ` @expand ` | Expand transition start | () => void |
53- | ` @expanded ` | Expand transition completed | () => void |
54- | ` @collapse ` | Collapse transition start | () => void |
55- | ` @collapsed ` | Collapse transition completed | () => void |
56-
5715## Usage
5816
5917``` vue
6018<script setup>
6119import { ref } from 'vue'
20+
6221import { Collapse } from 'vue-collapsed'
6322
6423const isExpanded = ref(false)
6524</script>
6625
6726<template>
68- <button @click="isExpanded = !isExpanded">Trigger </button>
27+ <button @click="isExpanded = !isExpanded">Toggle </button>
6928
7029 <Collapse :when="isExpanded">
7130 <p>{{ 'Collapsed '.repeat(100) }}</p>
7231 </Collapse>
7332</template>
7433```
7534
76- ## Automatic transition (default behavior)
35+ ## Props
7736
78- By default, if no height transition is specified the following one is automatically added to the Collapse element:
37+ | Name | Type | Description | Required |
38+ | ------------ | ----------------------------- | ---------------------------------------- | ------------------ |
39+ | ` when ` | boolean | Controls the collapse/expand state | :white_check_mark : |
40+ | ` baseHeight ` | number | Collapsed height in px. Defaults to ` 0 ` . | :x : |
41+ | ` as ` | _ keyof_ HTMLElementTagNameMap | Tag to use instead of ` div ` | :x : |
7942
80- ` height var(--vc-auto-duration) cubic-bezier(0.33, 1, 0.68, 1) `
43+ ## Emits
8144
82- ` --vc-auto-duration ` is calculated in background and corresponds to an optimal transition duration based on your content height.
45+ | Name | Type | Description |
46+ | ------------ | ---------- | -------------------------------- |
47+ | ` @expand ` | () => void | Emitted when expansion starts |
48+ | ` @expanded ` | () => void | Emitted when expansion completes |
49+ | ` @collapse ` | () => void | Emitted when collapse starts |
50+ | ` @collapsed ` | () => void | Emitted when collapse completes |
8351
84- This is the recommended way to use this package unless you want to customize the transition.
52+ ## Automatic transition (default)
8553
86- ## Custom transition
54+ By default, the following transition is always added to the ` Collapse ` element:
8755
88- If you prefer to use a custom duration or easing, add a class to Collapse that transitions the ` height ` property:
89-
90- ``` vue
91- <Collapse :when="isExpanded" class="v-collapse">
92- <p>{{ 'Collapsed '.repeat(100) }}</p>
93- </Collapse>
56+ ``` css
57+ transition: height var(--vc-auto-duration) cubic-bezier(0.33 , 1, 0.68 , 1);
9458```
9559
60+ ` --vc-auto-duration ` is calculated dynamically and corresponds to the optimal transition duration based on the element's height.
61+
62+ ## Custom transition
63+
64+ To use a custom duration or easing, add a class to the ` Collapse ` component that transitions the ` height ` property:
65+
9666``` css
97- .v-collapse {
67+ .collapsed-area {
9868 transition : height 300ms ease-out ;
99- /* or transition: height var(--vc-auto-duration) ease-in-out */
10069}
10170```
10271
72+ ``` vue
73+ <Collapse :when="isExpanded" class="collapsed-area">
74+ <p>{{ 'Collapsed '.repeat(100) }}</p>
75+ </Collapse>
76+ ```
77+
10378### Multiple transitions
10479
105- To transition other properties use the attribute ` data-collapse ` :
80+ To transition other properties, use the ` data-collapse ` attribute :
10681
10782| Transition | From | Enter | Leave |
10883| ---------- | ----------- | ------------ | ----------- |
10984| Expand | ` collapsed ` | ` expanding ` | ` expanded ` |
11085| Collapse | ` expanded ` | ` collapsing ` | ` collapsed ` |
11186
11287``` css
113- .v-collapse {
114- --dur-easing : var (--vc-auto-duration ) cubic-bezier (0.33 , 1 , 0.68 , 1 );
88+ .collapsed-area {
89+ --transition-base : 300ms cubic-bezier (0.33 , 1 , 0.68 , 1 );
90+
11591 transition :
116- height var (--dur-easing ),
117- opacity var (--dur-easing );
92+ height var (--transition-base ),
93+ opacity var (--transition-base );
11894}
11995
120- .v-collapse [data-collapse = ' expanded' ],
121- .v-collapse [data-collapse = ' expanding' ] {
96+ .collapsed-area [data-collapse = ' expanded' ],
97+ .collapsed-area [data-collapse = ' expanding' ] {
12298 opacity : 1 ;
12399}
124100
125- .v-collapse [data-collapse = ' collapsed' ],
126- .v-collapse [data-collapse = ' collapsing' ] {
101+ .collapsed-area [data-collapse = ' collapsed' ],
102+ .collapsed-area [data-collapse = ' collapsing' ] {
127103 opacity : 0 ;
128104}
129105```
130106
131- Or to use different easings/ durations for expand and collapse :
107+ Alternatively, to use different easings or durations for expanding and collapsing :
132108
133109``` css
134- .v-collapse [data-collapse = ' expanding' ] {
110+ .collapsed-area [data-collapse = ' expanding' ] {
135111 transition : height 600ms ease-in-out ;
136112}
137113
138- .v-collapse [data-collapse = ' collapsing' ] {
114+ .collapsed-area [data-collapse = ' collapsing' ] {
139115 transition : height 300ms ease-out ;
140116}
141117```
142118
143- Above values can also be accessed using ` v-slot ` :
119+ The values of the ` data-collapse ` attribute can be accessed using ` v-slot ` :
144120
145121``` vue
146- <Collapse :when="isExpanded" class="v-collapse" v-slot="{ state }">
147- {{ state === 'collapsing' ? 'Collapsing content ...' : null }}
122+ <Collapse :when="isExpanded" v-slot="{ state }">
123+ {{ state === 'collapsing' ? 'Collapsing...' : null }}
148124</Collapse>
149125```
150126
@@ -173,29 +149,21 @@ const questions = reactive([
173149 }
174150])
175151
176- function handleAccordion(selectedIndex ) {
177- questions.forEach((_, index ) => {
178- questions[index ].isExpanded = index === selectedIndex ? !questions[index ].isExpanded : false
152+ function onQuestionToggle(toggleIndex ) {
153+ questions.forEach((_, i ) => {
154+ questions[i ].isExpanded = i === toggleIndex ? !questions[i ].isExpanded : false
179155 })
180156}
181-
182- /**
183- * For individual control you might use:
184- *
185- * function handleMultiple(index) {
186- * questions[index].isExpanded = !questions[index].isExpanded
187- * }
188- */
189157</script>
190158
191159<template>
192- <div v-for="(question, index ) in questions" :key="question .title">
193- <button @click="handleAccordion(index )">
194- {{ question .title }}
160+ <div v-for="(q, i ) in questions" :key="q .title">
161+ <button @click="onQuestionToggle(i )">
162+ {{ q .title }}
195163 </button>
196- <Collapse :when="questions[index] .isExpanded">
164+ <Collapse :when="q .isExpanded">
197165 <p>
198- {{ question .answer }}
166+ {{ q .answer }}
199167 </p>
200168 </Collapse>
201169 </div>
@@ -204,19 +172,19 @@ function handleAccordion(selectedIndex) {
204172
205173## Accessibility
206174
207- ` vue-collapsed ` automatically detects if users prefer reduced motion and will disable transitions accordingly while keeping the same API behavior (emitting events and post-transition styles).
175+ ` vue-collapsed ` automatically detects if users prefer reduced motion and disables transitions accordingly, while maintaining the same API behavior (emitting events and applying post-transition styles).
208176
209- You should only add ` aria ` attributes to the Collapse element according to your use case.
177+ You should add ` aria ` attributes to the ` Collapse ` element based on your specific use case.
210178
211179``` vue
212180<script setup>
213- import { ref, computed } from 'vue'
181+ import { ref, computed, useId } from 'vue'
214182import { Collapse } from 'vue-collapsed'
215183
216184const isExpanded = ref(false)
217185
218- const TOGGLE_ID = 'toggle-id'
219- const COLLAPSE_ID = 'collapse-id'
186+ const TOGGLE_ID = useId()
187+ const COLLAPSE_ID = useId()
220188
221189const toggleAttrs = computed(() => ({
222190 id: TOGGLE_ID,
@@ -237,7 +205,7 @@ function handleCollapse() {
237205
238206<template>
239207 <div>
240- <button v-bind="toggleAttrs" @click="handleCollapse">This a panel. </button>
208+ <button v-bind="toggleAttrs" @click="handleCollapse">Toggle panel</button>
241209 <Collapse v-bind="collapseAttrs" :when="isExpanded">
242210 <p>{{ 'Collapsed '.repeat(100) }}</p>
243211 </Collapse>
@@ -249,13 +217,13 @@ function handleCollapse() {
249217
250218``` vue
251219<template>
252- <Collapse :when="isExpanded" class="instant-collapse ">
220+ <Collapse :when="isExpanded" class="collapsed-area ">
253221 <p>{{ 'Collapsed '.repeat(100) }}</p>
254222 </Collapse>
255223</template>
256224
257225<style>
258- .instant-collapse {
226+ .collapsed-area {
259227 transition: none;
260228}
261229</style>
0 commit comments