Skip to content

Commit a414978

Browse files
committed
trigger a new transition if children height changed while expanding
1 parent 5f3d783 commit a414978

File tree

2 files changed

+25
-15
lines changed

2 files changed

+25
-15
lines changed

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

-6
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ export function getComputedHeight(el: RefEl) {
1111
return parseFloat(getComputedStyle(el.value).height)
1212
}
1313

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

0 commit comments

Comments
 (0)