@@ -18,10 +18,10 @@ import {
18
18
type CSSProperties as CSS ,
19
19
} from ' vue'
20
20
21
- import { SAFE_STYLES as safeStyles , AUTO_DUR_VAR } from ' ./constants'
21
+ import { SAFE_STYLES as safeStyles , VISUALLY_HIDDEN , AUTO_DUR_VAR } from ' ./constants'
22
22
import { getTransition , getHeight , getAutoDuration , isReducedOrDisaled } from ' ./utils'
23
23
24
- type TransitionState = ' expanding' | ' expanded' | ' collapsing' | ' collapsed'
24
+ export type TransitionState = ' expanding' | ' expanded' | ' collapsing' | ' collapsed'
25
25
26
26
const props = withDefaults (
27
27
defineProps <{
@@ -61,19 +61,11 @@ const collapsedStyles = computed(() => ({
61
61
const collapseRef = ref <HTMLElement | null >(null )
62
62
63
63
const state = ref <TransitionState >(isExpanded .value ? ' expanded' : ' collapsed' )
64
- const style = shallowRef <CSS >(isExpanded . value ? safeStyles : collapsedStyles . value )
64
+ const style = shallowRef <CSS >({} )
65
65
66
- const autoDuration = ref (0 )
66
+ const autoDuration = ref (300 )
67
67
const autoDurationVar = computed (() => ({ [AUTO_DUR_VAR ]: ` ${autoDuration .value }ms ` }))
68
68
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
-
77
69
function onExpanded() {
78
70
style .value = safeStyles
79
71
state .value = ' expanded'
@@ -88,7 +80,13 @@ function onCollapsed() {
88
80
89
81
// Lifecycle / Watchers
90
82
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
+ })
92
90
93
91
watch (isExpanded , (isExpanding ) => {
94
92
if (isExpanding ) {
@@ -104,28 +102,23 @@ watch(isExpanded, (isExpanding) => {
104
102
* We set the height to baseHeight as it is the 'current' height
105
103
* we are transitioning from.
106
104
*/
105
+ state .value = ' expanding'
106
+ emit (' expand' )
107
+
107
108
style .value = {
108
109
... safeStyles ,
109
110
... baseHeightStyles .value ,
111
+ ... autoDurationVar .value ,
110
112
willChange: ' height' ,
111
113
}
112
114
113
115
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
+ }
129
122
})
130
123
} else {
131
124
if (isReducedOrDisaled (collapseRef .value )) return onCollapsed ()
@@ -136,31 +129,24 @@ watch(isExpanded, (isExpanding) => {
136
129
*
137
130
* Since the element is visible we get the 'current'
138
131
* 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.
144
132
*/
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
+
145
143
requestAnimationFrame (() => {
144
+ /** Set height to baseHeight and trigger the transition. */
146
145
style .value = {
147
146
... style .value ,
148
- ... autoDurationVar .value ,
149
- ... getHeight (collapseRef .value ),
150
- willChange: ' height' ,
147
+ ... baseHeightStyles .value ,
148
+ ... getTransition (collapseRef .value ),
151
149
}
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
- })
164
150
})
165
151
}
166
152
})
@@ -175,13 +161,14 @@ watch(baseHeight, (newBaseHeight) => {
175
161
*
176
162
* Below styles are going to be replaced on next expand.
177
163
*/
178
- transitionDuration: ' 0s' ,
179
- height: ` ${newBaseHeight }px ` ,
164
+ ... (newBaseHeight === 0
165
+ ? { display: ' none' }
166
+ : { transition: ' none' , height: ` ${newBaseHeight }px ` }),
180
167
}
181
168
}
182
169
})
183
170
184
- // Callbacks
171
+ // Event handlers
185
172
186
173
function onTransitionEnd(event : TransitionEvent ) {
187
174
if (event .target === collapseRef .value && event .propertyName === ' height' ) {
0 commit comments