-
Notifications
You must be signed in to change notification settings - Fork 3
/
Modal.vue
156 lines (132 loc) · 4.03 KB
/
Modal.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<script lang="ts">
export enum ModalName {
CryptoMap = 'crypto-map',
Report = 'report',
FAQ = 'faq',
Candidate = 'candidate',
}
</script>
<script setup lang="ts">
const props = withDefaults(defineProps<{ name: ModalName, nested?: boolean }>(), { nested: false })
const emit = defineEmits<{ close: [] }>()
const open = defineModel<boolean>('open')
// Keep state in the URL
const route = useRoute()
const router = useRouter()
const queryName = props.nested ? 'nested' : 'modal'
open.value = route.query[queryName] === props.name
watch(open, (v) => {
requestAnimationFrame(() => router.replace({ query: { ...route.query, [queryName]: v ? props.name : undefined } }))
if (!v)
emit('close')
})
onUnmounted(() => router.replace({ query: { ...route.query, [queryName]: undefined } }))
</script>
<template>
<DialogRoot v-model:open="open">
<DialogTrigger v-bind="$attrs">
<slot name="trigger" />
</DialogTrigger>
<DialogPortal>
<Transition name="backdrop">
<DialogOverlay v-if="!nested" fixed inset-0 z-200 bg-darkblue op-60 />
</Transition>
<Transition :name="nested ? 'nested' : 'modal'">
<DialogContent
:key="name" desktop="top-1/2 left-1/2 translate--1/2" rounded="t-8 desktop:8"
data-modal fixed bottom-0 z-200 h-max max-h-85dvh w-full transform of-y-auto outline-none shadow-lg desktop:max-w-500
:data-nested="nested ? '' : undefined" @open-auto-focus.prevent
>
<div relative bg-neutral-0 py-32 ring="1.5 neutral/3" class="modal-container">
<DialogTitle mb-12 px-24 text="24 center neutral lh-24" font-bold lh-none desktop:px-40 as="h2">
<slot name="title" />
</DialogTitle>
<DialogDescription block px-24 text="center neutral" desktop:px-40>
<slot name="description" />
</DialogDescription>
<div mt-12 px-24 desktop:px-40>
<slot name="content" />
</div>
<DialogClose :aria-label="$t('Close')" absolute right-16 top-16 text-28 close-btn />
</div>
</DialogContent>
</Transition>
</DialogPortal>
</DialogRoot>
</template>
<style scoped>
/* https://github.com/nimiq/wallet/blob/a88d34bfa16930adbfd52baaa5b0809c38c5c365/src/components/modals/Modal.vue */
.backdrop-enter-active {
transition: opacity 650ms cubic-bezier(.3, 1, .2, 1);
}
.backdrop-leave-active {
transition: opacity 650ms cubic-bezier(.3, 0, 0, 1);
}
.backdrop-enter-from,
.backdrop-leave-to {
opacity: 0;
}
@screen lt-desktop {
.modal-enter-active,
.modal-leave-active {
transition: transform 200ms ease-out;
}
.modal-enter-from,
.modal-leave-to {
--un-translate-y: 100%;
}
}
@screen desktop {
.modal-enter-active,
.modal-leave-active {
transition:
opacity 250ms cubic-bezier(.4, 0, .2, 1),
transform 100ms var(--nq-ease);
}
.modal-enter-from,
.modal-leave-to {
opacity: 0;
--un-scale-x: 0.96;
--un-scale-y: 0.96;
--un-translate-y: calc(-50% - 0.5rem);
}
}
/*
Radix will set all the modals in the root of the body. So we check if a sibling contains [data-nested]
Only apply when the Vue Transition classes are not applied
*/
[data-modal]:not([data-nested]):not([class*="modal-"]) {
transition:
transform 400ms ease-out,
filter 450ms cubic-bezier(.3, 0, 0, 1);
&:has(~ [data-nested][data-state="open"]) {
--un-scale-x: 0.94;
--un-scale-y: 0.94;
filter: brightness(0.8) blur(0.5px);
}
}
@screen desktop {
.nested-enter-active {
transition: transform 650ms cubic-bezier(.3, 1, 0.2, 1);
}
.nested-leave-active {
transition: transform 450ms cubic-bezier(0.3, 0, 0, 1);
}
.nested-enter-from,
.nested-leave-to {
--un-translate-y: calc(-1.1 * (100vh / 2) - 100%);
}
}
@screen lt-desktop {
.nested-enter-active {
transition: transform 350ms cubic-bezier(.3, 1, 0.2, 1);
}
.nested-leave-active {
transition: transform 250ms cubic-bezier(0.3, 0, 0, 1);
}
.nested-enter-from,
.nested-leave-to {
--un-translate-y: 100%;
}
}
</style>