feat(components): [dialog] add modal-penetrable prop (#21511)

* feat(components): [dialog] add `modal-penetrable` prop

* refactor(components): [dialog] optimize code

* test(components): [dialog] update test

* test(components): [test] update test
This commit is contained in:
Zhong
2025-07-30 16:51:18 +08:00
committed by GitHub
parent 622b945993
commit 3182010562
5 changed files with 47 additions and 1 deletions

View File

@@ -173,6 +173,7 @@ dialog/events
| fullscreen | whether the Dialog takes up full screen | ^[boolean] | false |
| top | value for `margin-top` of Dialog CSS, default is 15vh | ^[string] | '' |
| modal | whether a mask is displayed | ^[boolean] | true |
| modal-penetrable ^(2.10.5) | whether the mask is penetrable. The modal attribute must be `false`. | ^[boolean] | false |
| modal-class | custom class names for mask | ^[string] | — |
| header-class ^(2.9.3) | custom class names for header wrapper | ^[string] | — |
| body-class ^(2.9.3) | custom class names for body wrapper | ^[string] | — |

View File

@@ -225,6 +225,29 @@ describe('Dialog.vue', () => {
await triggerCompositeClick(wrapper.find('.el-overlay-dialog'))
expect(wrapper.vm.visible).toBe(false)
})
test('should not click the mask to close when it is penetrable', async () => {
const onClick = vi.fn()
const wrapper = mount(() => (
<>
<Dialog modelValue={true} modal={false} modalPenetrable={true}>
{AXIOM}
</Dialog>
<button onClick={onClick}>button</button>
</>
))
const overlay = wrapper.findComponent({ name: 'ElOverlay' })
const dialog = wrapper.findComponent({ name: 'ElDialog' })
expect(overlay.exists()).toBe(true)
expect(overlay.classes()).toContain('is-penetrable')
await overlay.trigger('click')
await wrapper.find('button').trigger('click')
expect(dialog.vm.visible).toBe(true)
expect(onClick).toHaveBeenCalled()
})
})
describe('life cycles', () => {

View File

@@ -68,6 +68,10 @@ export const dialogProps = buildProps({
type: Boolean,
default: true,
},
/**
* @description whether the mask is penetrable
*/
modalPenetrable: Boolean,
/**
* @description the Time(milliseconds) before open
*/

View File

@@ -8,7 +8,11 @@
v-show="visible"
custom-mask-event
:mask="modal"
:overlay-class="modalClass"
:overlay-class="[
modalClass ?? '',
`${ns.namespace.value}-modal-dialog`,
ns.is('penetrable', penetrable),
]"
:z-index="zIndex"
>
<div
@@ -138,6 +142,10 @@ const overlayEvent = useSameTarget(onModalClick)
const draggable = computed(() => props.draggable && !props.fullscreen)
const penetrable = computed(
() => props.modalPenetrable && !props.modal && !props.fullscreen
)
const resetPosition = () => {
dialogContentRef.value?.resetPosition()
}

View File

@@ -128,6 +128,16 @@
}
}
.#{$namespace}-modal-dialog {
&.is-penetrable {
pointer-events: none;
.#{$namespace}-dialog {
pointer-events: auto;
}
}
}
.#{$namespace}-overlay-dialog {
position: fixed;
top: 0;