fix: improve the display of modal and drawer on mobile (#4237)

This commit is contained in:
Vben
2024-08-26 20:54:20 +08:00
committed by GitHub
parent 577cc85851
commit fd7b3479b4
19 changed files with 99 additions and 34 deletions

View File

@@ -30,6 +30,8 @@ export class DrawerApi {
const defaultState: DrawerState = {
cancelText: '取消',
closable: true,
closeOnClickModal: true,
closeOnPressEscape: true,
confirmLoading: false,
confirmText: '确定',
footer: true,

View File

@@ -7,12 +7,21 @@ export interface DrawerProps {
* 取消按钮文字
*/
cancelText?: string;
/**
* 是否显示右上角的关闭按钮
* @default true
*/
closable?: boolean;
/**
* 点击弹窗遮罩是否关闭弹窗
* @default true
*/
closeOnClickModal?: boolean;
/**
* 按下 ESC 键是否关闭弹窗
* @default true
*/
closeOnPressEscape?: boolean;
/**
* 确定按钮 loading
* @default false

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { DrawerProps, ExtendedDrawerApi } from './drawer';
import { usePriorityValue } from '@vben-core/composables';
import { useIsMobile, usePriorityValue } from '@vben-core/composables';
import { Info, X } from '@vben-core/icons';
import {
Sheet,
@@ -31,6 +31,7 @@ const props = withDefaults(defineProps<Props>(), {
drawerApi: undefined,
});
const { isMobile } = useIsMobile();
const state = props.drawerApi?.useStore?.();
const title = usePriorityValue('title', props, state);
@@ -43,6 +44,27 @@ const modal = usePriorityValue('modal', props, state);
const confirmLoading = usePriorityValue('confirmLoading', props, state);
const cancelText = usePriorityValue('cancelText', props, state);
const confirmText = usePriorityValue('confirmText', props, state);
const closeOnClickModal = usePriorityValue('closeOnClickModal', props, state);
const closeOnPressEscape = usePriorityValue('closeOnPressEscape', props, state);
function interactOutside(e: Event) {
if (!closeOnClickModal.value) {
e.preventDefault();
}
}
function escapeKeyDown(e: KeyboardEvent) {
if (!closeOnPressEscape.value) {
e.preventDefault();
}
}
// pointer-down-outside
function pointerDownOutside(e: Event) {
const target = e.target as HTMLElement;
const isDismissableModal = !!target?.dataset.dismissableModal;
if (!closeOnClickModal.value || !isDismissableModal) {
e.preventDefault();
}
}
</script>
<template>
<Sheet
@@ -50,7 +72,16 @@ const confirmText = usePriorityValue('confirmText', props, state);
:open="state?.isOpen"
@update:open="() => drawerApi?.close()"
>
<SheetContent :class="cn('flex w-[520px] flex-col', props.class, {})">
<SheetContent
:class="
cn('flex w-[520px] flex-col', props.class, {
'!w-full': isMobile,
})
"
@escape-key-down="escapeKeyDown"
@interact-outside="interactOutside"
@pointer-down-outside="pointerDownOutside"
>
<SheetHeader
:class="
cn('!flex flex-row items-center justify-between border-b px-6 py-5', {
@@ -59,7 +90,7 @@ const confirmText = usePriorityValue('confirmText', props, state);
"
>
<div>
<SheetTitle v-if="title">
<SheetTitle v-if="title" class="text-left">
<slot name="title">
{{ title }}
@@ -111,22 +142,17 @@ const confirmText = usePriorityValue('confirmText', props, state);
<SheetFooter
v-if="showFooter"
class="w-full items-center border-t p-2 px-3"
class="w-full flex-row items-center justify-end border-t p-2 px-3"
>
<slot name="prepend-footer"></slot>
<slot name="footer">
<VbenButton
size="sm"
variant="ghost"
@click="() => drawerApi?.onCancel()"
>
<VbenButton variant="ghost" @click="() => drawerApi?.onCancel()">
<slot name="cancelText">
{{ cancelText }}
</slot>
</VbenButton>
<VbenButton
:loading="confirmLoading"
size="sm"
@click="() => drawerApi?.onConfirm()"
>
<slot name="confirmText">