Browse Source

feat: popup component support overlay blur effect (#5359)

Netfan 2 months ago
parent
commit
6719e2679f

+ 1 - 0
docs/src/components/common-ui/vben-drawer.md

@@ -101,6 +101,7 @@ const [Drawer, drawerApi] = useVbenDrawer({
 | footerClass | modal底部区域的class | `string` | - |
 | headerClass | modal顶部区域的class | `string` | - |
 | zIndex | 抽屉的ZIndex层级 | `number` | `1000` |
+| overlayBlur | 遮罩模糊度 | `number` | - |
 
 ::: info appendToMain
 

+ 1 - 0
docs/src/components/common-ui/vben-modal.md

@@ -111,6 +111,7 @@ const [Modal, modalApi] = useVbenModal({
 | headerClass | modal顶部区域的class | `string` | - |
 | bordered | 是否显示border | `boolean` | `false` |
 | zIndex | 弹窗的ZIndex层级 | `number` | `1000` |
+| overlayBlur | 遮罩模糊度 | `number` | - |
 
 ::: info appendToMain
 

+ 5 - 1
packages/@core/ui-kit/popup-ui/src/drawer/drawer.ts

@@ -85,12 +85,16 @@ export interface DrawerProps {
    * 是否自动聚焦
    */
   openAutoFocus?: boolean;
+  /**
+   * 弹窗遮罩模糊效果
+   */
+  overlayBlur?: number;
+
   /**
    * 抽屉位置
    * @default right
    */
   placement?: DrawerPlacement;
-
   /**
    * 是否显示取消按钮
    * @default true

+ 2 - 0
packages/@core/ui-kit/popup-ui/src/drawer/drawer.vue

@@ -68,6 +68,7 @@ const {
   loading: showLoading,
   modal,
   openAutoFocus,
+  overlayBlur,
   placement,
   showCancelButton,
   showConfirmButton,
@@ -140,6 +141,7 @@ const getAppendTo = computed(() => {
       :open="state?.isOpen"
       :side="placement"
       :z-index="zIndex"
+      :overlay-blur="overlayBlur"
       @close-auto-focus="handleFocusOutside"
       @closed="() => drawerApi?.onClosed()"
       @escape-key-down="escapeKeyDown"

+ 4 - 0
packages/@core/ui-kit/popup-ui/src/modal/modal.ts

@@ -99,6 +99,10 @@ export interface ModalProps {
    * 是否自动聚焦
    */
   openAutoFocus?: boolean;
+  /**
+   * 弹窗遮罩模糊效果
+   */
+  overlayBlur?: number;
   /**
    * 是否显示取消按钮
    * @default true

+ 2 - 0
packages/@core/ui-kit/popup-ui/src/modal/modal.vue

@@ -77,6 +77,7 @@ const {
   loading: showLoading,
   modal,
   openAutoFocus,
+  overlayBlur,
   showCancelButton,
   showConfirmButton,
   title,
@@ -196,6 +197,7 @@ const getAppendTo = computed(() => {
       :open="state?.isOpen"
       :show-close="closable"
       :z-index="zIndex"
+      :overlay-blur="overlayBlur"
       close-class="top-3"
       @close-auto-focus="handleFocusOutside"
       @closed="() => modalApi?.onClosed()"

+ 7 - 1
packages/@core/ui-kit/shadcn-ui/src/ui/dialog/DialogContent.vue

@@ -25,6 +25,7 @@ const props = withDefaults(
       closeClass?: ClassType;
       modal?: boolean;
       open?: boolean;
+      overlayBlur?: number;
       showClose?: boolean;
       zIndex?: number;
     }
@@ -82,7 +83,12 @@ defineExpose({
     <Transition name="fade">
       <DialogOverlay
         v-if="open && modal"
-        :style="{ zIndex, position }"
+        :style="{
+          zIndex,
+          position,
+          backdropFilter:
+            overlayBlur && overlayBlur > 0 ? `blur(${overlayBlur}px)` : 'none',
+        }"
         @click="() => emits('close')"
       />
     </Transition>

+ 14 - 2
packages/@core/ui-kit/shadcn-ui/src/ui/sheet/SheetContent.vue

@@ -17,6 +17,7 @@ interface SheetContentProps extends DialogContentProps {
   class?: any;
   modal?: boolean;
   open?: boolean;
+  overlayBlur?: number;
   side?: SheetVariants['side'];
   zIndex?: number;
 }
@@ -75,12 +76,23 @@ function onAnimationEnd(event: AnimationEvent) {
 <template>
   <DialogPortal :to="appendTo">
     <Transition name="fade">
-      <SheetOverlay v-if="open && modal" :style="{ zIndex, position }" />
+      <SheetOverlay
+        v-if="open && modal"
+        :style="{
+          zIndex,
+          position,
+          backdropFilter:
+            overlayBlur && overlayBlur > 0 ? `blur(${overlayBlur}px)` : 'none',
+        }"
+      />
     </Transition>
     <DialogContent
       ref="contentRef"
       :class="cn(sheetVariants({ side }), props.class)"
-      :style="{ zIndex, position }"
+      :style="{
+        zIndex,
+        position,
+      }"
       @animationend="onAnimationEnd"
       v-bind="{ ...forwarded, ...$attrs }"
     >

+ 3 - 0
playground/src/views/examples/drawer/base-demo.vue

@@ -7,6 +7,9 @@ const [Drawer, drawerApi] = useVbenDrawer({
   onCancel() {
     drawerApi.close();
   },
+  onClosed() {
+    drawerApi.setState({ overlayBlur: 0, placement: 'right' });
+  },
   onConfirm() {
     message.info('onConfirm');
     // drawerApi.close();

+ 7 - 0
playground/src/views/examples/drawer/index.vue

@@ -45,6 +45,10 @@ function openBaseDrawer(placement: DrawerPlacement = 'right') {
   baseDrawerApi.setState({ placement }).open();
 }
 
+function openBlurDrawer() {
+  baseDrawerApi.setState({ overlayBlur: 5 }).open();
+}
+
 function openInContentDrawer(placement: DrawerPlacement = 'right') {
   const state: Partial<DrawerState> = { class: '', placement };
   if (placement === 'top') {
@@ -124,6 +128,9 @@ function openFormDrawer() {
       <Button class="mb-2 ml-2" type="primary" @click="openBaseDrawer('top')">
         顶部打开
       </Button>
+      <Button class="mb-2 ml-2" type="primary" @click="openBlurDrawer">
+        遮罩层模糊效果
+      </Button>
     </Card>
 
     <Card class="mb-4" title="在内容区域打开">

+ 23 - 0
playground/src/views/examples/modal/blur-demo.vue

@@ -0,0 +1,23 @@
+<script lang="ts" setup>
+import { ref, watch } from 'vue';
+
+import { useVbenModal } from '@vben/common-ui';
+
+import { Slider } from 'ant-design-vue';
+
+const blur = ref(5);
+const [Modal, modalApi] = useVbenModal({
+  overlayBlur: blur.value,
+});
+watch(blur, (val) => {
+  modalApi.setState({
+    overlayBlur: val,
+  });
+});
+</script>
+<template>
+  <Modal title="遮罩层模糊">
+    <p>调整滑块来改变遮罩层模糊程度:{{ blur }}</p>
+    <Slider v-model:value="blur" :max="30" :min="0" />
+  </Modal>
+</template>

+ 17 - 0
playground/src/views/examples/modal/index.vue

@@ -6,6 +6,7 @@ import { Button, Card, Flex } from 'ant-design-vue';
 import DocButton from '../doc-button.vue';
 import AutoHeightDemo from './auto-height-demo.vue';
 import BaseDemo from './base-demo.vue';
+import BlurDemo from './blur-demo.vue';
 import DragDemo from './drag-demo.vue';
 import DynamicDemo from './dynamic-demo.vue';
 import FormModalDemo from './form-modal-demo.vue';
@@ -47,6 +48,10 @@ const [NestedModal, nestedModalApi] = useVbenModal({
   connectedComponent: NestedDemo,
 });
 
+const [BlurModal, blurModalApi] = useVbenModal({
+  connectedComponent: BlurDemo,
+});
+
 function openBaseModal() {
   baseModalApi.open();
 }
@@ -80,6 +85,10 @@ function openNestedModal() {
   nestedModalApi.open();
 }
 
+function openBlurModal() {
+  blurModalApi.open();
+}
+
 function handleUpdateTitle() {
   dynamicModalApi.setState({ title: '外部动态标题' }).open();
 }
@@ -111,6 +120,7 @@ function openFormModal() {
     <SharedDataModal />
     <FormModal />
     <NestedModal />
+    <BlurModal />
     <Flex wrap="wrap" class="w-full" gap="10">
       <Card class="w-[300px]" title="基本使用">
         <p>一个基础的弹窗示例</p>
@@ -176,6 +186,13 @@ function openFormModal() {
           <Button type="primary" @click="openNestedModal">打开嵌套弹窗</Button>
         </template>
       </Card>
+
+      <Card class="w-[300px]" title="遮罩模糊示例">
+        <p>遮罩层应用类似毛玻璃的模糊效果</p>
+        <template #actions>
+          <Button type="primary" @click="openBlurModal">打开弹窗</Button>
+        </template>
+      </Card>
     </Flex>
   </Page>
 </template>