Skip to content
This repository was archived by the owner on Sep 20, 2024. It is now read-only.

Commit 24c1f4a

Browse files
committed
fix: create modal transitions
1 parent ef58bfe commit 24c1f4a

File tree

8 files changed

+222
-128
lines changed

8 files changed

+222
-128
lines changed

packages/c-modal/examples/simple-modal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<c-button color-scheme="blue" @click="isOpen = true">Open modal</c-button>
1010
<c-button ref="finalFocus" ml="3">Other button</c-button>
1111
<!-- eslint-disable-next-line -->
12-
<c-modal v-model:is-open="isOpen" :initial-focus-ref="'#initialFocus'" :final-focus-ref="() => $refs.finalFocus">
12+
<c-modal v-model:is-open="isOpen" motion-preset="slideInRight" :initial-focus-ref="'#initialFocus'" :final-focus-ref="() => $refs.finalFocus">
1313
<c-modal-overlay />
1414
<c-modal-content>
1515
<c-modal-header>Modal header</c-modal-header>

packages/c-modal/src/c-modal.ts

Lines changed: 42 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,7 @@ import {
2121
UnwrapRef,
2222
watch,
2323
unref,
24-
getCurrentInstance,
25-
Transition,
26-
ref,
27-
nextTick,
28-
onMounted,
2924
withDirectives,
30-
WatchStopHandle,
3125
} from 'vue'
3226
import {
3327
chakra,
@@ -36,23 +30,16 @@ import {
3630
useMultiStyleConfig,
3731
useStyles,
3832
} from '@chakra-ui/vue-system'
39-
import {
40-
createContext,
41-
getSelector,
42-
TemplateRef,
43-
useRef,
44-
} from '@chakra-ui/vue-utils'
33+
import { createContext, TemplateRef, useRef } from '@chakra-ui/vue-utils'
4534
import { CPortal } from '@chakra-ui/c-portal'
4635
import { FocusLockProps } from '@chakra-ui/c-focus-lock'
4736
import { CMotion } from '@chakra-ui/c-motion'
4837
import { CCloseButton } from '@chakra-ui/c-close-button'
49-
import { MotionDirective, useMotion } from '@vueuse/motion'
50-
38+
import { MotionDirective, useMotions } from '@vueuse/motion'
5139
import { useModal, UseModalOptions, UseModalReturn } from './use-modal'
52-
import { useDialogTransition, useDialogTransitions } from './modal-transitions'
40+
import { DialogMotionPreset, dialogMotionPresets } from './modal-transitions'
5341

5442
type ScrollBehavior = 'inside' | 'outside'
55-
type MotionPreset = 'slideInBottom' | 'slideInRight' | 'scale' | 'none'
5643

5744
export interface ModalOptions
5845
extends Omit<
@@ -126,7 +113,7 @@ export interface CModalProps extends UnwrapRef<UseModalOptions>, ModalOptions {
126113
/**
127114
* The transition that should be used for the modal
128115
*/
129-
motionPreset?: MotionPreset
116+
motionPreset: DialogMotionPreset
130117
}
131118

132119
type IUseModalOptions = ToRefs<
@@ -136,15 +123,12 @@ type IUseModalOptions = ToRefs<
136123
| 'handleEscape'
137124
| 'preserveScrollBarGap'
138125
| 'allowPinchZoom'
139-
| 'motionPreset'
140126
| 'trapFocus'
141127
| 'autoFocus'
142128
>
143129
>
144130

145131
interface CModalContext extends IUseModalOptions, UseModalReturn {
146-
// /** The transition to be used for the CModal */
147-
// motionPreset?: MotionPreset
148132
dialogRef: (el: TemplateRef) => void
149133
overlayRef: (el: TemplateRef) => void
150134
closeModal: () => void
@@ -216,24 +200,13 @@ export const CModal = defineComponent({
216200
},
217201
motionPreset: {
218202
type: String as PropType<CModalProps['motionPreset']>,
219-
default: 'scale',
203+
default: 'slideInBottom',
220204
},
221205
},
222206
emits: ['update:is-open', 'escape', 'close'],
223207
setup(props, { slots, attrs, emit }) {
224-
const isOpen = computed(() => props.isOpen)
225-
const { localIsOpen, transitionsExited } = useDialogTransitions(isOpen, {
226-
onChildrenEntered: () => {
227-
console.log('========= TRANSITIONS ENTER ================')
228-
},
229-
onChildrenLeft: () => {
230-
console.log('========= TRANSITIONS LEFT ================')
231-
emit('update:is-open', false)
232-
},
233-
})
234-
235208
const closeModal = () => {
236-
localIsOpen.value = false
209+
emit('update:is-open', false)
237210
}
238211

239212
const handleEscape = (event: KeyboardEvent) => {
@@ -276,13 +249,26 @@ export const CModalContent = defineComponent({
276249
inheritAttrs: false,
277250
emits: ['click', 'mousedown', 'keydown'],
278251
setup(_, { attrs, slots, emit }) {
279-
const { dialogContainerProps, dialogProps, dialogRefEl } = unref(
252+
const { dialogContainerProps, dialogProps, isOpen, motionPreset } = unref(
280253
useModalContext()
281254
)
282255
const styles = useStyles()
256+
const transitionId = 'modal-content'
257+
258+
/** Handles exit transition */
259+
const leave = (done: VoidFunction) => {
260+
const motions = useMotions()
261+
const instance = motions[transitionId]
262+
instance?.leave(() => {
263+
done()
264+
})
265+
}
283266

284-
const { localIsOpen, register } = unref(useDialogTransition())
285-
const modalContentTransition = register('modal-content')
267+
watch(isOpen, (newVal) => {
268+
if (!newVal) {
269+
leave(() => null)
270+
}
271+
})
286272

287273
const dialogContainerStyles = computed<SystemStyleObject>(() => ({
288274
display: 'flex',
@@ -303,17 +289,6 @@ export const CModalContent = defineComponent({
303289
...styles.value.dialog,
304290
}))
305291

306-
watch(
307-
modalContentTransition,
308-
(content) => {
309-
console.log('modalContentTransition state changed to:', content.status)
310-
},
311-
{
312-
immediate: true,
313-
deep: true,
314-
}
315-
)
316-
317292
return () => {
318293
return h(
319294
chakra('div', {
@@ -322,66 +297,26 @@ export const CModalContent = defineComponent({
322297
}),
323298
dialogContainerProps.value({ emit }),
324299
() => [
325-
h(
326-
Transition,
327-
{
328-
css: false,
329-
onBeforeEnter: () => {
330-
modalContentTransition.value.status = 'active'
331-
console.log('onBeforeEnter', 'active')
332-
},
333-
onAfterEnter: () => {
334-
modalContentTransition.value.status = 'entered'
335-
console.log('onAfterEnter', 'entered')
336-
},
337-
onBeforeLeave: () => {
338-
modalContentTransition.value.status = 'active'
339-
console.log('onAfterLeave', 'active')
340-
},
341-
onLeave: (el, done) => {
342-
modalContentTransition.value.status = 'exited'
343-
console.log('onAfterLeave', 'exited')
344-
done()
345-
},
346-
},
347-
() => [
348-
localIsOpen.value &&
349-
withDirectives(
350-
h(
351-
chakra('section', {
352-
__css: dialogStyles.value,
353-
label: 'modal__content',
354-
}),
355-
{
356-
...attrs,
357-
...dialogProps.value({ emit }),
358-
},
359-
slots
360-
),
361-
[
362-
[
363-
MotionDirective({
364-
initial: {
365-
scale: 0.8,
366-
opacity: 0,
367-
translateY: 10,
368-
},
369-
enter: {
370-
scale: 1,
371-
opacity: 1,
372-
translateY: 0,
373-
},
374-
leave: {
375-
scale: 0.8,
376-
opacity: 0,
377-
translateY: 10,
378-
},
379-
}),
380-
],
381-
]
382-
),
383-
]
384-
),
300+
isOpen.value &&
301+
withDirectives(
302+
h(
303+
chakra('section', {
304+
__css: dialogStyles.value,
305+
label: 'modal__content',
306+
}),
307+
{
308+
...attrs,
309+
...dialogProps.value({ emit }),
310+
},
311+
slots
312+
),
313+
[
314+
[
315+
MotionDirective(dialogMotionPresets[motionPreset?.value]),
316+
transitionId,
317+
],
318+
]
319+
),
385320
]
386321
)
387322
}

0 commit comments

Comments
 (0)