@@ -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'
2222import { getTransition , getHeight , getAutoDuration , isReducedOrDisaled } from ' ./utils'
2323
24- type TransitionState = ' expanding' | ' expanded' | ' collapsing' | ' collapsed'
24+ export type TransitionState = ' expanding' | ' expanded' | ' collapsing' | ' collapsed'
2525
2626const props = withDefaults (
2727 defineProps <{
@@ -61,19 +61,11 @@ const collapsedStyles = computed(() => ({
6161const collapseRef = ref <HTMLElement | null >(null )
6262
6363const 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 )
6767const 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-
7769function 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
9391watch (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
186173function onTransitionEnd(event : TransitionEvent ) {
187174 if (event .target === collapseRef .value && event .propertyName === ' height' ) {
0 commit comments