https://github.com/smastrom/vue-collapsed
ποΈββοΈ CSS height transition from any to auto and vice versa for Vue and Nuxt. Accordion ready.
https://github.com/smastrom/vue-collapsed
accordion accordion-component collapse collapse-component dynamic-height vue vue-accordion vue-collapse vue3
Last synced: about 2 months ago
JSON representation
ποΈββοΈ CSS height transition from any to auto and vice versa for Vue and Nuxt. Accordion ready.
- Host: GitHub
- URL: https://github.com/smastrom/vue-collapsed
- Owner: smastrom
- License: mit
- Created: 2022-11-18T20:14:18.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-08-05T16:01:45.000Z (10 months ago)
- Last Synced: 2025-03-29T07:07:06.640Z (about 2 months ago)
- Topics: accordion, accordion-component, collapse, collapse-component, dynamic-height, vue, vue-accordion, vue-collapse, vue3
- Language: Vue
- Homepage: https://vue-collapsed.pages.dev
- Size: 210 KB
- Stars: 152
- Watchers: 2
- Forks: 7
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
    
# Vue Collapsed
Dynamic CSS height transition from _any to auto_ and vice versa. Accordion ready.
[Examples and Demo](https://vue-collapsed.pages.dev) - [Stackblitz](https://stackblitz.com/edit/vue-dmjqey?file=src/App.vue)
Check out my other packages for Vue and Nuxt:
> π **Notivue**
> _Fully-featured notification system for Vue and Nuxt._
> [Visit repo β ](https://github.com/smastrom/notivue)> π **Vue Global Loader**
> _Global loaders made easy for Vue and Nuxt._
> [Visit repo β ](https://github.com/smastrom/vue-global-loader)> π **Vue Use Active Scroll**
> _Accurate TOC/sidebar links without compromises._
> [Visit repo β ](https://github.com/smastrom/vue-use-active-scroll)> π₯ **Vue Use Fixed Header**
> _Turn your boring fixed header into a smart one with three lines of code._
> [Visit repo β ](https://github.com/smastrom/vue-use-fixed-header)
## Installation
```shell
npm i vue-collapsed
#Β yarn add vue-collapsed
# pnpm add vue-collapsed
# bun add vue-collapsed
```## Props
| Name | Description | Type | Required |
| ------------ | ---------------------------------------- | ----------------------------- | ------------------ |
| `when` | Value to control collapse | boolean | :white_check_mark: |
| `baseHeight` | Collapsed height in px, defaults to `0`. | number | :x: |
| `as` | Tag to use instead of `div` | _keyof_ HTMLElementTagNameMap | :x: |## Emits
| Name | Description | Type |
| ------------ | ----------------------------- | ---------- |
| `@expand` | Expand transition start | () => void |
| `@expanded` | Expand transition completed | () => void |
| `@collapse` | Collapse transition start | () => void |
| `@collapsed` | Collapse transition completed | () => void |## Usage
```vue
import { ref } from 'vue'
import { Collapse } from 'vue-collapsed'const isExpanded = ref(false)
Trigger
{{ 'Collapsed '.repeat(100) }}
```
## Automatic transition (default behavior)
By default, if no height transition is specified the following one is automatically added to the Collapse element:
`height var(--vc-auto-duration) cubic-bezier(0.33, 1, 0.68, 1)`
`--vc-auto-duration` is calculated in background and corresponds to an optimal transition duration based on your content height.
This is the recommended way to use this package unless you want to customize the transition.
## Custom transition
If you prefer to use a custom duration or easing, add a class to Collapse that transitions the `height` property:
```vue
{{ 'Collapsed '.repeat(100) }}
```
```css
.v-collapse {
transition: height 300ms ease-out;
/* or transition: height var(--vc-auto-duration) ease-in-out */
}
```### Multiple transitions
To transition other properties use the attribute `data-collapse`:
| Transition | From | Enter | Leave |
| ---------- | ----------- | ------------ | ----------- |
| Expand | `collapsed` | `expanding` | `expanded` |
| Collapse | `expanded` | `collapsing` | `collapsed` |```css
.v-collapse {
--dur-easing: var(--vc-auto-duration) cubic-bezier(0.33, 1, 0.68, 1);
transition:
height var(--dur-easing),
opacity var(--dur-easing);
}.v-collapse[data-collapse='expanded'],
.v-collapse[data-collapse='expanding'] {
opacity: 1;
}.v-collapse[data-collapse='collapsed'],
.v-collapse[data-collapse='collapsing'] {
opacity: 0;
}
```Or to use different easings/durations for expand and collapse:
```css
.v-collapse[data-collapse='expanding'] {
transition: height 600ms ease-in-out;
}.v-collapse[data-collapse='collapsing'] {
transition: height 300ms ease-out;
}
```Above values can also be accessed using `v-slot`:
```vue
{{ state === 'collapsing' ? 'Collapsing content...' : null }}
```
## Example - Accordion
```vue
import { reactive } from 'vue'
import { Collapse } from 'vue-collapsed'const questions = reactive([
{
title: 'Question one',
answer: 'Answer one',
isExpanded: false // Initial value
},
{
title: 'Question two',
answer: 'Answer two',
isExpanded: false
},
{
title: 'Question three',
answer: 'Answer three',
isExpanded: false
}
])function handleAccordion(selectedIndex) {
questions.forEach((_, index) => {
questions[index].isExpanded = index === selectedIndex ? !questions[index].isExpanded : false
})
}/**
* For individual control you might use:
*
* function handleMultiple(index) {
* questions[index].isExpanded = !questions[index].isExpanded
* }
*/
{{ question.title }}
{{ question.answer }}
```
## Accessibility
`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).
You should only add `aria` attributes to the Collapse element according to your use case.
```vue
import { ref, computed } from 'vue'
import { Collapse } from 'vue-collapsed'const isExpanded = ref(false)
const TOGGLE_ID = 'toggle-id'
const COLLAPSE_ID = 'collapse-id'const toggleAttrs = computed(() => ({
id: TOGGLE_ID,
'aria-controls': COLLAPSE_ID,
'aria-expanded': isExpanded.value
}))const collapseAttrs = {
role: 'region',
id: COLLAPSE_ID,
'aria-labelledby': TOGGLE_ID
}function handleCollapse() {
isExpanded.value = !isExpanded.value
}
This a panel.
{{ 'Collapsed '.repeat(100) }}
```
## Manually disabling transitions
```vue
{{ 'Collapsed '.repeat(100) }}
.instant-collapse {
transition: none;
}```
## License
MIT