Skip to content

Commit 7295ab8

Browse files
committed
refactor(v1-components): Render function of UiModalSidebar replaced with a regular template
1 parent e33fce2 commit 7295ab8

File tree

1 file changed

+108
-120
lines changed

1 file changed

+108
-120
lines changed

packages/v1-components/src/host/components/modal-sidebar/UiModalSidebar.vue

Lines changed: 108 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,119 @@
1+
<template>
2+
<Teleport v-if="state.attached" :to="globals?.container || 'body'">
3+
<UiTransition
4+
name="fade-2"
5+
@before-enter="visibilityOfOverlay = 'showing'"
6+
@after-enter="visibilityOfOverlay = 'shown'"
7+
@before-leave="visibilityOfOverlay = 'hiding'"
8+
@after-leave="visibilityOfOverlay = 'hidden'"
9+
>
10+
<div
11+
v-show="state.shown"
12+
:id="id"
13+
:aria-hidden="visibility !== 'shown' ? 'true' : 'false'"
14+
:class="[$attrs.class, {
15+
['ui-v1-modal']: true,
16+
['ui-v1-modal_overlapped']: state.overlapped,
17+
['ui-v1-modal-sidebar-overlay']: true,
18+
['ui-v1-modal-sidebar-overlay_fixed']: fixed,
19+
[`ui-v1-modal-sidebar-overlay_${direction}`]: fixed,
20+
}]"
21+
aria-modal="true"
22+
v-bind="$attrs"
23+
@click="onBackdropClick"
24+
>
25+
<UiTransition
26+
:name="`slide-${direction}`"
27+
@before-enter="visibilityOfSidebar = 'showing'"
28+
@after-enter="visibilityOfSidebar = 'shown'"
29+
@before-leave="visibilityOfSidebar = 'hiding'"
30+
@after-leave="visibilityOfSidebar = 'hidden'"
31+
>
32+
<aside
33+
v-if="state.shown"
34+
:id="id + '-sidebar'"
35+
:class="{
36+
'ui-v1-modal-sidebar': true,
37+
'ui-v1-modal-sidebar_left': direction === DIRECTION.LEFT,
38+
'ui-v1-modal-sidebar_size_sm': size === SIZE.SM,
39+
'ui-v1-modal-sidebar_size_lg': size === SIZE.LG,
40+
}"
41+
>
42+
<header class="ui-v1-modal-sidebar__header">
43+
<div class="ui-v1-modal-sidebar__header-inner">
44+
<div
45+
aria-level="1"
46+
class="ui-v1-modal-sidebar__title"
47+
role="heading"
48+
>
49+
<slot name="title" :overlapped="state.overlapped" />
50+
</div>
51+
</div>
52+
53+
<div
54+
ref="closer"
55+
aria-label="Esc"
56+
class="ui-v1-modal-sidebar__close"
57+
role="button"
58+
@click="onCloserClick"
59+
>
60+
<IconClear aria-hidden="true" width="32" />
61+
62+
<UiTooltip :target="closerTarget" :offset-main-axis="0">
63+
Esc
64+
</UiTooltip>
65+
</div>
66+
</header>
67+
68+
<div v-if="scrolling === SCROLLING.NONE" class="ui-v1-modal-sidebar__body-fixed">
69+
<slot :overlapped="state.overlapped" />
70+
</div>
71+
72+
<UiScrollBox
73+
v-else
74+
:native="scrolling === SCROLLING.NATIVE"
75+
class="ui-v1-modal-sidebar__body"
76+
show-on-mac
77+
@ps-y-reach-end="$emit('scroll:y:end')"
78+
>
79+
<slot :overlapped="state.overlapped" />
80+
</UiScrollBox>
81+
82+
<footer
83+
v-if="'footer' in $slots"
84+
class="ui-v1-modal-sidebar__footer"
85+
>
86+
<slot name="footer" :overlapped="state.overlapped" />
87+
</footer>
88+
</aside>
89+
</UiTransition>
90+
</div>
91+
</UiTransition>
92+
</Teleport>
93+
</template>
94+
195
<script lang="ts" setup>
2-
import type { PropType, VNode } from 'vue'
96+
import type { PropType } from 'vue'
397
498
import type { Layer } from '@/host/components/modal/layer'
599
import type { EmbedModal } from '@/host/components/modal/plugin'
6100
7101
import UiScrollBox from '@/host/components/scroll-box/UiScrollBox.vue'
8102
import UiTransition from '@/host/components/transition/UiTransition.vue'
103+
import UiTooltip from '@/host/components/tooltip/UiTooltip.vue'
9104
10105
import IconClear from '~assets/sprites/actions/clear.svg'
11106
12107
import {
13-
Teleport,
14108
computed,
15-
h,
16109
inject,
17110
onActivated,
18111
onBeforeUnmount,
19112
onDeactivated,
20113
onMounted,
21114
reactive,
22115
ref,
23-
useAttrs,
24-
useSlots,
25-
vShow,
26116
watch,
27-
withDirectives,
28117
} from 'vue'
29118
30119
import { ModalInjectKey } from '@/host/components/modal/plugin'
@@ -119,7 +208,7 @@ const emit = defineEmits([
119208
'scroll:y:end',
120209
])
121210
122-
const globals = inject<EmbedModal|null>(ModalInjectKey, null)
211+
const globals = inject<EmbedModal | null>(ModalInjectKey, null)
123212
124213
const state = reactive({
125214
attached: false,
@@ -129,6 +218,9 @@ const state = reactive({
129218
overlapped: false,
130219
})
131220
221+
const closer = ref<HTMLElement | null>(null)
222+
const closerTarget = computed(() => closer)
223+
132224
const layer = computed<Layer>(() => ({
133225
id: props.id,
134226
isBlocker: () => !props.fixed,
@@ -270,121 +362,17 @@ onBeforeUnmount(() => {
270362
detach()
271363
})
272364
273-
const attrs = useAttrs()
274-
const slots = useSlots()
275-
276-
const hasSlot = (slotName: string): boolean => slotName in slots
277-
const renderSlot = (slotName: string) => {
278-
const fn = slots[slotName]
279-
return fn ? fn({ overlapped: state.overlapped }) : []
280-
}
281-
const normalizeSlot = (slotName: string) => () => renderSlot(slotName)
282-
283-
const renderHeader = (): VNode => {
284-
return h('header', { class: 'ui-v1-modal-sidebar__header' }, [
285-
h('div', { class: 'ui-v1-modal-sidebar__header-inner' }, h('div', {
286-
role: 'heading',
287-
'aria-level': '1',
288-
class: 'ui-v1-modal-sidebar__title',
289-
}, renderSlot('title'))),
290-
h('div', {
291-
role: 'button',
292-
'aria-label': 'Esc',
293-
class: 'ui-v1-modal-sidebar__close',
294-
onClick: () => {
295-
if (!state.overlapped) {
296-
close(CLOSE_METHOD.CLICK_CROSS)
297-
}
298-
},
299-
}, h(IconClear, {
300-
width: 32,
301-
title: 'Esc',
302-
})),
303-
])
304-
}
305-
306-
const renderBody = (): VNode => props.scrolling === SCROLLING.NONE
307-
? h('div', { class: 'ui-v1-modal-sidebar__body-fixed' }, renderSlot('default'))
308-
: h(UiScrollBox, {
309-
class: 'ui-v1-modal-sidebar__body',
310-
native: props.scrolling === SCROLLING.NATIVE,
311-
showOnMac: true,
312-
onPsYReachEnd: () => emit('scroll:y:end'),
313-
}, {
314-
default: normalizeSlot('default'),
315-
})
316-
317-
const renderFooter = (): VNode[] => hasSlot('footer')
318-
? [h('footer', { class: 'ui-v1-modal-sidebar__footer' }, renderSlot('footer'))]
319-
: []
320-
321-
const renderSidebar = (): VNode => {
322-
const direction = props.direction
323-
const size = props.size
324-
325-
const setVisibility = (visibility: Visibility) => () => visibilityOfSidebar.value = visibility
326-
327-
return h(UiTransition, {
328-
name: `slide-${direction}`,
329-
onBeforeEnter: setVisibility('showing'),
330-
onAfterEnter: setVisibility('shown'),
331-
onBeforeLeave: setVisibility('hiding'),
332-
onAfterLeave: setVisibility('hidden'),
333-
}, {
334-
default: () => state.shown ? [
335-
h('aside', {
336-
id: props.id + '-sidebar',
337-
class: {
338-
'ui-v1-modal-sidebar': true,
339-
'ui-v1-modal-sidebar_left': direction === DIRECTION.LEFT,
340-
'ui-v1-modal-sidebar_size_sm': size === SIZE.SM,
341-
'ui-v1-modal-sidebar_size_lg': size === SIZE.LG,
342-
},
343-
}, [
344-
renderHeader(),
345-
renderBody(),
346-
...renderFooter(),
347-
]),
348-
] : [],
349-
})
365+
const onBackdropClick = (event: Event) => {
366+
if (event.target === event.currentTarget && !state.overlapped) {
367+
close(CLOSE_METHOD.CLICK_OUTSIDE)
368+
}
350369
}
351370
352-
const EmbedModalSidebar = () => {
353-
const setVisibility = (visibility: Visibility) => () => visibilityOfOverlay.value = visibility
354-
355-
return !state.attached ? undefined : h(Teleport, {
356-
to: globals?.container ?? document.body,
357-
}, h(UiTransition, {
358-
name: 'fade-2',
359-
onBeforeEnter: setVisibility('showing'),
360-
onAfterEnter: setVisibility('shown'),
361-
onBeforeLeave: setVisibility('hiding'),
362-
onAfterLeave: setVisibility('hidden'),
363-
}, {
364-
default: () => withDirectives(h('div', {
365-
id: props.id,
366-
'aria-hidden': visibility.value !== 'shown' ? 'true' : 'false',
367-
'aria-modal': 'true',
368-
...attrs,
369-
class: [attrs.class, {
370-
'ui-v1-modal': true,
371-
'ui-v1-modal_overlapped': state.overlapped,
372-
'ui-v1-modal-sidebar-overlay': true,
373-
'ui-v1-modal-sidebar-overlay_fixed': props.fixed,
374-
[`ui-v1-modal-sidebar-overlay_${props.direction}`]: props.fixed,
375-
}],
376-
onClick: (event: Event) => {
377-
if (event.target === event.currentTarget && !state.overlapped) {
378-
close(CLOSE_METHOD.CLICK_OUTSIDE)
379-
}
380-
},
381-
}, renderSidebar()), [[vShow, state.shown]]),
382-
}))
371+
const onCloserClick = () => {
372+
if (!state.overlapped) {
373+
close(CLOSE_METHOD.CLICK_CROSS)
374+
}
383375
}
384376
</script>
385377

386-
<template>
387-
<EmbedModalSidebar />
388-
</template>
389-
390378
<style lang="less" src="./modal-sidebar.less" />

0 commit comments

Comments
 (0)