feat(components): [message-box] MessageBox can drag overflow the viewport (#15674)

feat(components): [message-box] can drag overflow the viewport
This commit is contained in:
kooriookami
2024-01-26 10:20:08 +08:00
committed by GitHub
parent 1f6537af4c
commit ee7a21f670
15 changed files with 83 additions and 81 deletions

View File

@ -113,7 +113,7 @@ message-box/customized-icon
MessageBox can be draggable. MessageBox can be draggable.
:::demo Setting `draggable` to `true` allows user to drag MessageBox. :::demo Setting `draggable` to `true` allows user to drag MessageBox. Set `overflow` ^(2.5.4) to `true` can drag overflow the viewport.
message-box/draggable message-box/draggable
@ -159,7 +159,7 @@ The corresponding methods are: `ElMessageBox`, `ElMessageBox.alert`, `ElMessageB
### Options ### Options
| Name | Description | Type | Default | | Name | Description | Type | Default |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------ | |------------------------------|------------------------------------------------------------------------------------------------------------------------------------------| ---------------------------------------------------------------------------------- | ------------------------------------------------ |
| autofocus | auto focus when open MessageBox | ^[boolean] | true | | autofocus | auto focus when open MessageBox | ^[boolean] | true |
| title | title of the MessageBox | ^[string] | '' | | title | title of the MessageBox | ^[string] | '' |
| message | content of the MessageBox | ^[string] / ^[VNode] / ^[Function]`() => VNode` ^(2.2.17) | — | | message | content of the MessageBox | ^[string] / ^[VNode] / ^[Function]`() => VNode` ^(2.2.17) | — |
@ -191,6 +191,7 @@ The corresponding methods are: `ElMessageBox`, `ElMessageBox.alert`, `ElMessageB
| input-error-message | error message when validation fails | ^[string] | Illegal input | | input-error-message | error message when validation fails | ^[string] | Illegal input |
| center | whether to align the content in center | ^[boolean] | false | | center | whether to align the content in center | ^[boolean] | false |
| draggable | whether MessageBox is draggable | ^[boolean] | false | | draggable | whether MessageBox is draggable | ^[boolean] | false |
| overflow ^(2.5.4) | draggable MessageBox can overflow the viewport | ^[boolean] | false |
| round-button | whether to use round button | ^[boolean] | false | | round-button | whether to use round button | ^[boolean] | false |
| button-size | custom size of confirm and cancel buttons | ^[string]`'small' \| 'default' \| 'large'` | default | | button-size | custom size of confirm and cancel buttons | ^[string]`'small' \| 'default' \| 'large'` | default |
| append-to ^(2.2.19) | set the root element for the message box | ^[string] / ^[HTMLElement] | — | | append-to ^(2.2.19) | set the root element for the message box | ^[string] / ^[HTMLElement] | — |

View File

@ -1,5 +1,5 @@
<template> <template>
<el-button text @click="open">Click to open the Message Box</el-button> <el-button plain @click="open">Click to open the Message Box</el-button>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-button text @click="open">Click to open Message Box</el-button> <el-button plain @click="open">Click to open Message Box</el-button>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-button text @click="open">Click to open the Message Box</el-button> <el-button plain @click="open">Click to open the Message Box</el-button>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-button text @click="open">Click to open Message Box</el-button> <el-button plain @click="open">Click to open Message Box</el-button>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-button text @click="open">Click to open Message Box</el-button> <el-button plain @click="open">Click to open Message Box</el-button>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-button text @click="open">Click to open Message Box</el-button> <el-button plain @click="open">Click to open Message Box</el-button>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -1,5 +1,8 @@
<template> <template>
<el-button text @click="open">Click to open Message Box</el-button> <el-button plain @click="open">Open a draggable Message Box</el-button>
<el-button plain @click="open2">
Open a overflow draggable Message Box
</el-button>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -29,4 +32,30 @@ const open = () => {
}) })
}) })
} }
const open2 = () => {
ElMessageBox.confirm(
'proxy will permanently delete the file. Continue?',
'Warning',
{
confirmButtonText: 'OK',
cancelButtonText: 'Cancel',
type: 'warning',
draggable: true,
overflow: true,
}
)
.then(() => {
ElMessage({
type: 'success',
message: 'Delete completed',
})
})
.catch(() => {
ElMessage({
type: 'info',
message: 'Delete canceled',
})
})
}
</script> </script>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-button text @click="open">Click to open Message Box</el-button> <el-button plain @click="open">Click to open Message Box</el-button>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-button text @click="open">Click to open Message Box</el-button> <el-button plain @click="open">Click to open Message Box</el-button>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -38,7 +38,7 @@
<div <div
v-if="title !== null && title !== undefined" v-if="title !== null && title !== undefined"
ref="headerRef" ref="headerRef"
:class="ns.e('header')" :class="[ns.e('header'), { 'show-close': showClose }]"
> >
<div :class="ns.e('title')"> <div :class="ns.e('title')">
<el-icon <el-icon
@ -178,7 +178,7 @@ import { ElIcon } from '@element-plus/components/icon'
import ElFocusTrap from '@element-plus/components/focus-trap' import ElFocusTrap from '@element-plus/components/focus-trap'
import { useGlobalComponentSettings } from '@element-plus/components/config-provider' import { useGlobalComponentSettings } from '@element-plus/components/config-provider'
import type { ComponentPublicInstance, DefineComponent, PropType } from 'vue' import type { ComponentPublicInstance, PropType } from 'vue'
import type { ComponentSize } from '@element-plus/constants' import type { ComponentSize } from '@element-plus/constants'
import type { import type {
Action, Action,
@ -231,6 +231,7 @@ export default defineComponent({
}, },
center: Boolean, center: Boolean,
draggable: Boolean, draggable: Boolean,
overflow: Boolean,
roundButton: { roundButton: {
default: false, default: false,
type: Boolean, type: Boolean,
@ -365,7 +366,8 @@ export default defineComponent({
) )
const draggable = computed(() => props.draggable) const draggable = computed(() => props.draggable)
useDraggable(rootRef, headerRef, draggable) const overflow = computed(() => props.overflow)
useDraggable(rootRef, headerRef, draggable, overflow)
onMounted(async () => { onMounted(async () => {
await nextTick() await nextTick()
@ -499,5 +501,5 @@ export default defineComponent({
t, t,
} }
}, },
}) as DefineComponent })
</script> </script>

View File

@ -102,6 +102,9 @@ export interface ElMessageBoxOptions {
/** Whether MessageBox can be drag */ /** Whether MessageBox can be drag */
draggable?: boolean draggable?: boolean
/** Draggable MessageBox can overflow the viewport */
overflow?: boolean
/** Content of the MessageBox */ /** Content of the MessageBox */
message?: string | VNode | (() => VNode) message?: string | VNode | (() => VNode)

View File

@ -516,11 +516,13 @@ $messagebox: map.merge(
'title-color': getCssVar('text-color-primary'), 'title-color': getCssVar('text-color-primary'),
'width': 420px, 'width': 420px,
'border-radius': 4px, 'border-radius': 4px,
'box-shadow': getCssVar('box-shadow'),
'font-size': getCssVar('font-size-large'), 'font-size': getCssVar('font-size-large'),
'content-font-size': getCssVar('font-size-base'), 'content-font-size': getCssVar('font-size-base'),
'content-color': getCssVar('text-color-regular'), 'content-color': getCssVar('text-color-regular'),
'error-font-size': 12px, 'error-font-size': 12px,
'padding-primary': 15px, 'padding-primary': 12px,
'font-line-height': getCssVar('font-line-height-primary'),
), ),
$messagebox $messagebox
); );

View File

@ -17,6 +17,7 @@
box-sizing: border-box; box-sizing: border-box;
padding: getCssVar('dialog', 'padding-primary'); padding: getCssVar('dialog', 'padding-primary');
width: var(#{getCssVarName('dialog-width')}, 50%); width: var(#{getCssVarName('dialog-width')}, 50%);
overflow-wrap: break-word;
&:focus { &:focus {
outline: none !important; outline: none !important;

View File

@ -11,20 +11,21 @@
@include b(message-box) { @include b(message-box) {
display: inline-block; display: inline-block;
position: relative;
max-width: getCssVar('messagebox-width'); max-width: getCssVar('messagebox-width');
width: 100%; width: 100%;
padding-bottom: 10px; padding: getCssVar('messagebox-padding-primary');
vertical-align: middle; vertical-align: middle;
background-color: getCssVar('bg-color'); background-color: getCssVar('bg-color');
border-radius: getCssVar('messagebox-border-radius'); border-radius: getCssVar('messagebox-border-radius');
border: 1px solid getCssVar('border-color-lighter');
font-size: getCssVar('messagebox-font-size'); font-size: getCssVar('messagebox-font-size');
box-shadow: getCssVar('box-shadow-light'); box-shadow: getCssVar('messagebox-box-shadow');
text-align: left; text-align: left;
overflow: hidden; overflow: hidden;
backface-visibility: hidden; backface-visibility: hidden;
// To avoid small screen overflowing, see #11919 // To avoid small screen overflowing, see #11919
box-sizing: border-box; box-sizing: border-box;
overflow-wrap: break-word;
&:focus { &:focus {
outline: none !important; outline: none !important;
@ -59,24 +60,29 @@
} }
@include e(header) { @include e(header) {
position: relative; padding-bottom: getCssVar('messagebox-padding-primary');
padding: getCssVar('messagebox-padding-primary');
padding-bottom: 10px; &.show-close {
padding-right: calc(getCssVar('messagebox-padding-primary') + var(
#{getCssVarName('message-close-size')},
map.get($message, 'close-size')
));
}
} }
@include e(title) { @include e(title) {
padding-left: 0;
margin-bottom: 0;
font-size: getCssVar('messagebox-font-size'); font-size: getCssVar('messagebox-font-size');
line-height: 1; line-height: getCssVar('messagebox-font-line-height');
color: getCssVar('messagebox-title-color'); color: getCssVar('messagebox-title-color');
} }
@include e(headerbtn) { @include e(headerbtn) {
position: absolute; position: absolute;
top: getCssVar('messagebox-padding-primary'); top: 0;
right: getCssVar('messagebox-padding-primary'); right: 0;
padding: 0; padding: 0;
width: 40px;
height: 40px;
border: none; border: none;
outline: none; outline: none;
background: transparent; background: transparent;
@ -100,17 +106,18 @@
} }
@include e(content) { @include e(content) {
padding: 10px getCssVar('messagebox-padding-primary');
color: getCssVar('messagebox-content-color'); color: getCssVar('messagebox-content-color');
font-size: getCssVar('messagebox-content-font-size'); font-size: getCssVar('messagebox-content-font-size');
} }
@include e(container) { @include e(container) {
position: relative; display: flex;
align-items: center;
gap: 12px;
} }
@include e(input) { @include e(input) {
padding-top: 15px; padding-top: 12px;
& div.invalid > input { & div.invalid > input {
border-color: getCssVar('color-error'); border-color: getCssVar('color-error');
@ -122,26 +129,7 @@
} }
@include e(status) { @include e(status) {
position: absolute; font-size: 24px;
top: 50%;
transform: translateY(-50%);
font-size: 24px !important;
&::before {
// 防止图标切割
padding-left: 1px;
}
&.#{$namespace}-icon {
// 防止 el-icon 的position样式覆盖
position: absolute;
}
+ .#{$namespace}-message-box__message {
padding-left: 36px;
padding-right: 12px;
overflow-wrap: break-word;
}
@each $type in (success, info, warning, error) { @each $type in (success, info, warning, error) {
&.#{$namespace}-message-box-icon--#{$type} { &.#{$namespace}-message-box-icon--#{$type} {
@ -156,67 +144,43 @@
& p { & p {
margin: 0; margin: 0;
line-height: 24px; line-height: getCssVar('messagebox-font-line-height');
} }
} }
@include e(errormsg) { @include e(errormsg) {
color: getCssVar('color-error'); color: getCssVar('color-error');
font-size: getCssVar('messagebox-error-font-size'); font-size: getCssVar('messagebox-error-font-size');
min-height: 18px; line-height: getCssVar('messagebox-font-line-height');
margin-top: 2px;
} }
@include e(btns) { @include e(btns) {
padding: 5px 15px 0;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: flex-end; justify-content: flex-end;
align-items: center; align-items: center;
padding-top: getCssVar('messagebox-padding-primary');
& button:nth-child(2) {
margin-left: 10px;
}
}
@include e(btns-reverse) {
flex-direction: row-reverse;
} }
// centerAlign 布局 // centerAlign 布局
@include m(center) { @include m(center) {
@include e(title) { @include e(title) {
position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 6px;
} }
@include e(status) { @include e(status) {
position: relative; font-size: inherit;
top: auto;
padding-right: 5px;
text-align: center;
transform: translateY(-1px);
}
@include e(message) {
margin-left: 0;
} }
@include e(btns) { @include e(btns) {
justify-content: center; justify-content: center;
} }
@include e(content) { @include e(container) {
$padding-horizontal: calc( justify-content: center;
#{getCssVar('messagebox', 'padding-primary')} + 12px
);
padding-left: $padding-horizontal;
padding-right: $padding-horizontal;
text-align: center;
} }
} }
} }