Skip to content

Commit a7cf517

Browse files
committed
1.2.6 (#15)
* streamline auto duration handling and raf watcher calls * update readme * bump deps, release 1.2.6 update readme shields
1 parent 9820505 commit a7cf517

File tree

5 files changed

+75
-86
lines changed

5 files changed

+75
-86
lines changed

README.md

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
![npm](https://img.shields.io/npm/v/vue-collapsed?color=46c119) ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/smastrom/vue-collapsed/tests.yml?branch=main&label=tests) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/vue-collapsed?color=success)
2-
![dependency-count](https://img.shields.io/badge/dependency%20count-0-success)
1+
![npm](https://img.shields.io/npm/v/vue-collapsed?color=46c119) ![dependencies](https://img.shields.io/badge/dependencies-0-success) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/vue-collapsed?color=success) ![downloads](https://img.shields.io/npm/dm/vue-collapsed) ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/smastrom/vue-collapsed/tests.yml?branch=main&label=tests)
32

43
# Vue Collapsed
54

@@ -126,6 +125,18 @@ To transition other properties use the attribute `data-collapse`:
126125
}
127126
```
128127

128+
Or to use different easings/durations for expand and collapse:
129+
130+
```css
131+
.v-collapse[data-collapse='expanding'] {
132+
transition: height 600ms ease-in-out;
133+
}
134+
135+
.v-collapse[data-collapse='collapsing'] {
136+
transition: height 300ms ease-out;
137+
}
138+
```
139+
129140
Above values can also be accessed using `v-slot`:
130141

131142
```vue
@@ -188,33 +199,6 @@ function handleAccordion(selectedIndex) {
188199
</template>
189200
```
190201

191-
## Example - Callbacks
192-
193-
```vue
194-
<script setup>
195-
// ...
196-
197-
const sectionsRef = ref([])
198-
199-
function scrollIntoView(index) {
200-
sectionsRef.value[index].scrollIntoView({ behavior: 'smooth' })
201-
}
202-
</script>
203-
204-
<template>
205-
<div v-for="(question, index) in questions" :key="question.title" ref="sectionsRef">
206-
<button @click="handleAccordion(index)">
207-
{{ question.title }}
208-
</button>
209-
<Collapse :when="questions[index].isExpanded" @expanded="() => scrollIntoView(index)">
210-
<p>
211-
{{ question.answer }}
212-
</p>
213-
</Collapse>
214-
</div>
215-
</template>
216-
```
217-
218202
## Accessibility
219203

220204
`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).
@@ -255,7 +239,7 @@ function handleCollapse() {
255239
</template>
256240
```
257241

258-
## Manually disable transitions
242+
## Manually disabling transitions
259243

260244
```vue
261245
<template>

demo/NestedCollapse.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ const nested = reactive({
77
first: true, // Initial value
88
second: false,
99
third: false,
10-
fourth: false,
1110
})
1211
1312
const innerText = `

package.json

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-collapsed",
3-
"version": "1.2.5",
3+
"version": "1.2.6",
44
"private": false,
55
"description": "Dynamic CSS height transition from any to auto and vice versa for Vue 3. Accordion ready.",
66
"keywords": [
@@ -28,6 +28,13 @@
2828
"main": "dist/index.js",
2929
"module": "dist/index.mjs",
3030
"types": "dist/index.d.ts",
31+
"exports": {
32+
".": {
33+
"import": "./dist/index.mjs",
34+
"require": "./dist/index.js",
35+
"types": "./dist/index.d.ts"
36+
}
37+
},
3138
"files": [
3239
"dist/*"
3340
],
@@ -51,15 +58,15 @@
5158
"@rollup/plugin-terser": "^0.4.3",
5259
"@types/node": "^18.17.1",
5360
"@vitejs/plugin-vue": "^4.2.3",
54-
"cypress": "^12.17.2",
61+
"cypress": "^12.17.3",
5562
"cypress-wait-frames": "^0.9.4",
5663
"husky": "^8.0.3",
5764
"lint-staged": "^13.2.3",
5865
"playwright-webkit": "^1.36.2",
5966
"prettier": "^2.8.8",
6067
"rimraf": "^4.4.1",
6168
"typescript": "^4.9.5",
62-
"vite": "^4.4.7",
69+
"vite": "^4.4.8",
6370
"vite-plugin-dts": "^1.7.3",
6471
"vue": "^3.3.4",
6572
"vue-tsc": "^1.8.8"

src/Collapse.vue

Lines changed: 38 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ import {
1818
type CSSProperties as CSS,
1919
} from 'vue'
2020
21-
import { SAFE_STYLES as safeStyles, AUTO_DUR_VAR } from './constants'
21+
import { SAFE_STYLES as safeStyles, VISUALLY_HIDDEN, AUTO_DUR_VAR } from './constants'
2222
import { getTransition, getHeight, getAutoDuration, isReducedOrDisaled } from './utils'
2323
24-
type TransitionState = 'expanding' | 'expanded' | 'collapsing' | 'collapsed'
24+
export type TransitionState = 'expanding' | 'expanded' | 'collapsing' | 'collapsed'
2525
2626
const props = withDefaults(
2727
defineProps<{
@@ -61,19 +61,11 @@ const collapsedStyles = computed(() => ({
6161
const collapseRef = ref<HTMLElement | null>(null)
6262
6363
const state = ref<TransitionState>(isExpanded.value ? 'expanded' : 'collapsed')
64-
const style = shallowRef<CSS>(isExpanded.value ? safeStyles : collapsedStyles.value)
64+
const style = shallowRef<CSS>({})
6565
66-
const autoDuration = ref(0)
66+
const autoDuration = ref(300)
6767
const autoDurationVar = computed(() => ({ [AUTO_DUR_VAR]: `${autoDuration.value}ms` }))
6868
69-
function setAutoDuration() {
70-
if (!collapseRef.value) return
71-
72-
if (isExpanded.value || baseHeight.value > 0) {
73-
autoDuration.value = getAutoDuration(collapseRef.value.scrollHeight - baseHeight.value)
74-
}
75-
}
76-
7769
function onExpanded() {
7870
style.value = safeStyles
7971
state.value = 'expanded'
@@ -88,7 +80,13 @@ function onCollapsed() {
8880
8981
// Lifecycle / Watchers
9082
91-
onMounted(setAutoDuration)
83+
onMounted(() => {
84+
if (!collapseRef.value) return
85+
if (!isExpanded.value && baseHeight.value === 0) style.value = VISUALLY_HIDDEN
86+
87+
autoDuration.value = getAutoDuration(collapseRef.value.scrollHeight - baseHeight.value)
88+
style.value = isExpanded.value ? safeStyles : collapsedStyles.value
89+
})
9290
9391
watch(isExpanded, (isExpanding) => {
9492
if (isExpanding) {
@@ -104,28 +102,23 @@ watch(isExpanded, (isExpanding) => {
104102
* We set the height to baseHeight as it is the 'current' height
105103
* we are transitioning from.
106104
*/
105+
state.value = 'expanding'
106+
emit('expand')
107+
107108
style.value = {
108109
...safeStyles,
109110
...baseHeightStyles.value,
111+
...autoDurationVar.value,
110112
willChange: 'height',
111113
}
112114
113115
requestAnimationFrame(() => {
114-
/** Get auto duration in once scrollHeight is available. */
115-
setAutoDuration()
116-
style.value = { ...style.value, ...autoDurationVar.value }
117-
118-
requestAnimationFrame(() => {
119-
/** Set height to scrollHeight and trigger the transition. */
120-
style.value = {
121-
...style.value,
122-
...getHeight(collapseRef.value),
123-
...getTransition(collapseRef.value),
124-
}
125-
126-
state.value = 'expanding'
127-
emit('expand')
128-
})
116+
/** Set height to scrollHeight and trigger the transition. */
117+
style.value = {
118+
...style.value,
119+
...getHeight(collapseRef.value),
120+
...getTransition(collapseRef.value),
121+
}
129122
})
130123
} else {
131124
if (isReducedOrDisaled(collapseRef.value)) return onCollapsed()
@@ -136,31 +129,24 @@ watch(isExpanded, (isExpanding) => {
136129
*
137130
* Since the element is visible we get the 'current'
138131
* expanded height (scrollHeight) and set it as height.
139-
*
140-
* We could use only one raf call, but we must use the
141-
* same number of raf calls of the previous condition (2) to make
142-
* sure accordion transitions (collapse/expand at the same time)
143-
* are perfectly in sync.
144132
*/
133+
state.value = 'collapsing'
134+
emit('collapse')
135+
136+
style.value = {
137+
...style.value,
138+
...autoDurationVar.value,
139+
...getHeight(collapseRef.value),
140+
willChange: 'height',
141+
}
142+
145143
requestAnimationFrame(() => {
144+
/** Set height to baseHeight and trigger the transition. */
146145
style.value = {
147146
...style.value,
148-
...autoDurationVar.value,
149-
...getHeight(collapseRef.value),
150-
willChange: 'height',
147+
...baseHeightStyles.value,
148+
...getTransition(collapseRef.value),
151149
}
152-
153-
requestAnimationFrame(() => {
154-
/** Set height to baseHeight and trigger the transition. */
155-
style.value = {
156-
...style.value,
157-
...baseHeightStyles.value,
158-
...getTransition(collapseRef.value),
159-
}
160-
161-
state.value = 'collapsing'
162-
emit('collapse')
163-
})
164150
})
165151
}
166152
})
@@ -175,13 +161,14 @@ watch(baseHeight, (newBaseHeight) => {
175161
*
176162
* Below styles are going to be replaced on next expand.
177163
*/
178-
transitionDuration: '0s',
179-
height: `${newBaseHeight}px`,
164+
...(newBaseHeight === 0
165+
? { display: 'none' }
166+
: { transition: 'none', height: `${newBaseHeight}px` }),
180167
}
181168
}
182169
})
183170
184-
// Callbacks
171+
// Event handlers
185172
186173
function onTransitionEnd(event: TransitionEvent) {
187174
if (event.target === collapseRef.value && event.propertyName === 'height') {

src/constants.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,16 @@ export const AUTO_DUR_VAR = '--vc-auto-duration'
22

33
export const DEFAULT_TRANSITION = `height var(${AUTO_DUR_VAR}) cubic-bezier(0.33, 1, 0.68, 1)`
44

5-
export const SAFE_STYLES = { padding: 0, border: 0, margin: 0 } as const
5+
export const SAFE_STYLES = { padding: 0 } as const
6+
7+
export const VISUALLY_HIDDEN = {
8+
position: 'absolute',
9+
width: '1px',
10+
height: '1px',
11+
padding: '0',
12+
margin: '-1px',
13+
overflow: 'hidden',
14+
clip: 'rect(0, 0, 0, 0)',
15+
whiteSpace: 'nowrap',
16+
border: '0',
17+
} as const

0 commit comments

Comments
 (0)