Collapsible component with CSS transition for elements with variable and dynamic height.
vue-collapse
| Codesandbox simple Vue 3 | View | Edit |
| name | size | gzip |
|---|---|---|
| vue-collapse.css | 0.43 kB | 0.21 kB |
| vue-collapse.js | 2.11 kB | 0.91 kB |
| vue-collapse.umd.cjs | 1.71 kB | 0.86 kB |
import '@kunukn/vue-collapse/style' // this imports the vue-collapse.css file.or CDN
<link
rel="stylesheet"
href="https://unpkg.com/@kunukn/vue-collapse/dist/vue-collapse.css"
/>or manually copy the content from the vue-collapse.css file to your app.
To alter the timing, you can use the transition prop. Or add custom CSS.
<style>
[data-vue-collapse-transition] {
transition-duration: 200ms;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
</style>Vue 3
npm install @kunukn/vue-collapseimport '@kunukn/vue-collapse/style'
import { VueCollapse } from '@kunukn/vue-collapse'There are four possible states: collapsed, collapsing, expanded, expanding.
Click: to see the attributes
| Attribute | Type | Default | About |
|---|---|---|---|
| :when | boolean | falsy | should component collapse? |
| :as | string | div | element type to render |
| transition | string | falsy | apply custom CSS transition, see demo example below |
| @collapse() | function | event emitted with component in this state | |
| @collapsing() | function | event emitted with component in this state | |
| @expanded() | function | event emitted with component in this state | |
| @expanding() | function | event emitted with component in this state | |
| @event(state) | function | event emitted with one of the 4 states | |
| @init(state) | function | component mount event emitted with current state |
Click: Simple version using ARIA
<template>
<div class="app">
<button
@click="isCollapsed = !isCollapsed"
:aria-expanded="!isCollapsed"
aria-controls="my-description"
>
{{ display }}
</button>
<VueCollapse
id="my-description"
:when="isCollapsed"
@event="onEvent"
v-slot="{ state }"
>
<p class="long-text">
I know the state: {{ state }}. Lorem Ipsum is simply dummy text of the
printing and typesetting industry.
</p>
</VueCollapse>
</div>
</template>
<script setup>
import { VueCollapse } from '@kunukn/vue-collapse'
import { ref } from 'vue'
const isCollapsed = ref(false)
const display = ref('')
const onEvent = (state) => {
display.value = 'event ' + state
}
</script>
<style>
/* Custom easing */
.vue-collapse[data-vue-collapse-transition] {
transition-duration: 200ms;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
</style>https://unpkg.com/@kunukn/vue-collapse/
You can use the library directly in the browser with ES modules and import maps:
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Import the CSS -->
<link
rel="stylesheet"
href="https://unpkg.com/@kunukn/vue-collapse/dist/vue-collapse.css"
/>
<!-- Import map for dependencies -->
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js",
"vue-collapse": "https://unpkg.com/@kunukn/vue-collapse/dist/vue-collapse.js"
}
}
</script>
</head>
<body>
<div id="app"></div>
<script type="module">
import { createApp, ref } from 'vue'
import { VueCollapse } from 'vue-collapse'
createApp({
components: { VueCollapse },
setup() {
const isCollapsed = ref(false)
return { isCollapsed }
},
template: `
<div>
<button @click="isCollapsed = !isCollapsed">
{{ isCollapsed ? 'Expand' : 'Collapse' }}
</button>
<VueCollapse :when="isCollapsed" transition="300ms ease-in-out">
<div>
<p>This content.</p>
<p>Can be collapsed!</p>
</div>
</VueCollapse>
</div>
`,
}).mount('#app')
</script>
</body>
</html>Modern browsers that can CSS transition on grid-template-rows.
Click: to see design goals
- Minimal in file size
- Let the browser handle the animation using CSS transition
- Minimalistic API
- Flexible - provide your own markup, styling and easing
- Interruptible - can be reversed during movement
- Inert - when collapsed you should tab over the collapsed component
- Availability - from CDN or npm install
- Collapsible on height only