Skip to content

Commit 51502dc

Browse files
authored
1.3.4 (#30)
* trigger a new transition if children height changed while expanding * suppress some demo prop warning * Fix #31 - Update default transition value since Chromium 128 * Tests - Update to match Chrome v128 default transition computation * Pkg - Bump v1.3.4 * Core - Improve comment
1 parent 5f3d783 commit 51502dc

File tree

8 files changed

+35
-34
lines changed

8 files changed

+35
-34
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ dist
66
/cypress/screenshots/
77
.vscode/*
88
!.vscode/extensions.json
9+
.idea
910
*.tgz

packages/vue-collapsed/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-collapsed",
3-
"version": "1.3.3",
3+
"version": "1.3.4",
44
"private": false,
55
"description": "Dynamic CSS height transition from any to auto and vice versa for Vue 3. Accordion ready.",
66
"keywords": [

packages/vue-collapsed/src/Collapse.vue

+25-9
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,7 @@ import {
1111
} from 'vue'
1212
1313
import { SAFE_STYLES, VISUALLY_HIDDEN, AUTO_DUR_VAR, FALLBACK_DURATION } from './constants'
14-
import {
15-
getTransitionProp,
16-
getComputedHeight,
17-
getHeightProp,
18-
getAutoDuration,
19-
isReducedOrDisabled,
20-
} from './utils'
14+
import { getTransitionProp, getComputedHeight, getAutoDuration, isReducedOrDisabled } from './utils'
2115
2216
export type TransitionState = 'expanding' | 'expanded' | 'collapsing' | 'collapsed'
2317
@@ -104,6 +98,15 @@ const setAutoDuration = (newDuration: number) => (autoDuration.value = newDurati
10498
10599
const autoDurationVar = computed(() => ({ [AUTO_DUR_VAR]: `${autoDuration.value}ms` }))
106100
101+
/**
102+
* In some edge cases, Collapse may have children elements that also expand
103+
* their height while expanding.
104+
*
105+
* When this occurs, the 'scrollHeight' obtained on transition start will be lower than
106+
* the same 'scrollHeight' obtained on transition end.
107+
*/
108+
let transitionStartScrollHeight = NaN
109+
107110
function onExpanded() {
108111
replaceStyles(SAFE_STYLES)
109112
setState('expanded')
@@ -139,6 +142,8 @@ onMounted(() => {
139142
watch(isExpanded, (isExpanding) => {
140143
if (!collapseRef.value) return
141144
145+
transitionStartScrollHeight = NaN
146+
142147
if (isExpanding) {
143148
if (isReducedOrDisabled(collapseRef)) return onExpanded()
144149
@@ -168,9 +173,11 @@ watch(isExpanded, (isExpanding) => {
168173
169174
/** Set height to scrollHeight and trigger the transition. */
170175
176+
transitionStartScrollHeight = collapseRef.value!.scrollHeight
177+
171178
addStyles({
172-
...getHeightProp(collapseRef),
173179
...getTransitionProp(collapseRef),
180+
height: `${transitionStartScrollHeight}px`,
174181
willChange: 'height',
175182
})
176183
})
@@ -189,7 +196,7 @@ watch(isExpanded, (isExpanding) => {
189196
190197
addStyles({
191198
...autoDurationVar.value,
192-
...getHeightProp(collapseRef),
199+
height: `${collapseRef.value!.scrollHeight}px`,
193200
})
194201
195202
/** Same as for expand, abort transition and force collapse */
@@ -230,6 +237,15 @@ function onTransitionEnd(e: TransitionEvent) {
230237
if (isExpanded.value) {
231238
if (Math.abs(collapseRef.value.scrollHeight - getComputedHeight(collapseRef)) < 1) {
232239
onExpanded()
240+
} else if (transitionStartScrollHeight < collapseRef.value.scrollHeight) {
241+
/**
242+
* A child element expanded its height while Collapse
243+
* is transitioning, update the height and trigger
244+
* the transition again.
245+
*/
246+
addStyles({
247+
height: `${collapseRef.value.scrollHeight}px`,
248+
})
233249
}
234250
} else {
235251
if (Math.abs(baseHeight.value - getComputedHeight(collapseRef)) < 1) {

packages/vue-collapsed/src/utils.ts

+3-14
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,21 @@ import type { Ref } from 'vue'
44

55
type RefEl = Ref<HTMLElement | null>
66

7-
const isFirefox = () => typeof navigator !== 'undefined' && navigator.userAgent.includes('Firefox')
8-
97
export function getComputedHeight(el: RefEl) {
108
if (!el.value) return 0
119
return parseFloat(getComputedStyle(el.value).height)
1210
}
1311

14-
export function getHeightProp(el: RefEl) {
15-
return {
16-
height: `${el.value?.scrollHeight || 0}px`,
17-
}
18-
}
19-
2012
export function getTransitionProp(el: RefEl) {
2113
if (!el.value) return {}
2214

2315
const { transition } = getComputedStyle(el.value)
2416

2517
// If transition is not defined via CSS, return the default one referencing the auto duration
26-
if (
27-
transition === 'all 0s ease 0s' ||
28-
(isFirefox() &&
29-
transition ===
30-
'all') /* Since Firefox v124, Gecko returns transition 'all' instead of 'all 0s ease 0s' */
31-
)
18+
if (transition === 'all 0s ease 0s' || transition === 'all') {
19+
/* Since Firefox v124 and Chromium v128, their rendering engines compute 'all' instead of 'all 0s ease 0s' as default transition */
3220
return { transition: DEFAULT_TRANSITION }
21+
}
3322

3423
return { transition }
3524
}

packages/vue-collapsed/tests/Collapse.cy.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import App from './App.vue'
2+
23
import { getRandomIntInclusive, isFirefox } from '../cypress/support/component'
34

45
describe('Collapse', () => {
@@ -275,13 +276,7 @@ describe('Collapse', () => {
275276

276277
const transition = 'height 0.3s cubic-bezier(0.33, 1, 0.68, 1)'
277278

278-
cy.get('#Collapse').should(
279-
'have.css',
280-
'transition',
281-
isFirefox
282-
? transition // Firefox >= 124 doesn't include '0s' by default anymore
283-
: `${transition} 0s`
284-
)
279+
cy.get('#Collapse').should('have.css', 'transition', transition)
285280

286281
cy.get('#Collapse').and('have.attr', 'style').and('include', '--vc-auto-duration: 300ms')
287282
})

playground/components/AdvancedControl.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Collapse } from 'vue-collapsed'
44
// Used for demo purposes only...
55
const props = withDefaults(
66
defineProps<{
7-
initialState: boolean
7+
initialState?: boolean
88
}>(),
99
{ initialState: true }
1010
)

playground/components/DisplayHide.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Collapse } from 'vue-collapsed'
33
44
const props = withDefaults(
55
defineProps<{
6-
initialState: boolean
6+
initialState?: boolean
77
}>(),
88
{ initialState: true }
99
)

playground/components/MountUnmount.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Collapse } from 'vue-collapsed'
33
44
const props = withDefaults(
55
defineProps<{
6-
initialState: boolean
6+
initialState?: boolean
77
}>(),
88
{ initialState: true }
99
)

0 commit comments

Comments
 (0)