Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dialog): add showInAttachedElement API #711

Merged
merged 7 commits into from
Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "src/_common"]
path = src/_common
url = [email protected]:Tencent/tdesign-common.git
url=[email protected]:zhaodanchun/tdesign-common.git
36 changes: 30 additions & 6 deletions examples/dialog/demos/attach.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
<template>
<div>
<div class="dialog-attach-wrap">
<!-- attach挂载 -->
<t-button theme="primary" @click="visibleBody = true">挂载在body</t-button>
<t-button theme="primary" @click="visibleIdAttach = true">挂载特定元素</t-button>
<t-button theme="primary" @click="visibleFunctionAttach = true">挂载函数返回节点</t-button>
<t-button theme="primary" @click="visibleShowInAttachedElement = true">展示在挂载元素区域</t-button>

<t-dialog
:visible.sync="visibleBody"
attach="body"
header="挂载在body"
destroyOnClose
:onConfirm="()=>this.visibleBody = false"
:onConfirm="() => (this.visibleBody = false)"
>
<div slot="body">
<div>被挂载到 body 元素的对话框</div>
Expand All @@ -22,7 +23,7 @@
attach="#app"
header="挂载到id为app的元素"
destroyOnClose
:onConfirm="()=>this.visibleIdAttach = false"
:onConfirm="() => (this.visibleIdAttach = false)"
>
<div slot="body">
<div>通过querySelect指定元素挂载</div>
Expand All @@ -36,14 +37,26 @@
:attach="getAttach"
header="函数返回挂载节点"
destroyOnClose
:onConfirm="()=>this.visibleFunctionAttach = false"
:onConfirm="() => (this.visibleFunctionAttach = false)"
>
<div slot="body">
<div>指定函数返回的节点为挂载点</div>
<div>函数返回为DOM节点对象</div>
</div>
</t-dialog>

<t-dialog
:visible.sync="visibleShowInAttachedElement"
header="对话框仅展示在挂载元素区域"
:showInAttachedElement="true"
placement="center"
:onConfirm="() => (this.visibleShowInAttachedElement = false)"
>
<div slot="body">
<div>父元素(挂载元素)需要有定位属性,如:position: relative</div>
<div>showInAttachedElement API 仅针对模态对话框有效</div>
</div>
</t-dialog>
</div>
</template>
<script>
Expand All @@ -55,18 +68,29 @@ export default Vue.extend({
visibleBody: false,
visibleIdAttach: false,
visibleFunctionAttach: false,
visibleShowInAttachedElement: false,
};
},
methods: {
getAttach() {
return this.$root.$el;
},

},
});
</script>
<style scoped>
<style>
.t-button {
margin-right: 20px;
}
.dialog-attach-wrap {
position: relative;
height: 400px;
padding: 20px;
border: 1px solid #ebedf0;
border-radius: 2px;
overflow: hidden;
}
body {
width: 3000px;
}
</style>
7 changes: 2 additions & 5 deletions examples/dialog/dialog.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ header | String / Boolean / Slot / Function | true | 头部内容。值为 true
mode | String | modal | 对话框类型,有三种:模态对话框、非模态对话框和普通对话框。弹出「模态对话框」时,只能操作对话框里面的内容,不能操作其他内容。弹出「非模态对话框」时,则可以操作页面内所有内容。「普通对话框」是指没有脱离文档流的对话框,可以在这个基础上开发更多的插件。可选项:modal/modeless/normal | N
placement | String | top | 对话框位置,内置两种:垂直水平居中显示 和 靠近顶部(top:20%)显示。可选项:top/center | N
preventScrollThrough | Boolean | true | 防止滚动穿透 | N
showInAttachedElement | Boolean | false | 仅在挂载元素中显示抽屉,默认在浏览器可视区域显示。父元素需要有定位属性,如:position: relative | N
showOverlay | Boolean | true | 是否显示遮罩层 | N
theme | String | default | 对话框风格。可选项:default/info/warning/danger/success | N
top | String / Number | - | 用于弹框具体窗口顶部的距离,优先级大于 placement | N
Expand Down Expand Up @@ -54,7 +55,7 @@ overlay-click | `(context: { e: MouseEvent })` | 如果蒙层存在,点击蒙
-- | -- | -- | -- | --
attach | String / Function | 'body' | 对话框挂载的节点。数据类型为 String 时,会被当作选择器处理,进行节点查询。示例:'body' 或 () => document.body。TS 类型:`AttachNode`。[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
className | String | - | 弹框类名,示例:'t-class-dialog-first t-class-dialog-second' | N
style | String | - | 弹框 style 属性,输入 [CSSStyleDeclaration.cssText](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/cssText) | N
style | String / Object | - | 弹框 style 属性,输入 [CSSStyleDeclaration.cssText](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/cssText)。TS 类型:`string | Styles`。[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
`Omit<DialogProps, 'attach'>` | - | - | 继承 `Omit<DialogProps, 'attach'>` 中的全部 API | N

### DialogInstance
Expand Down Expand Up @@ -84,14 +85,10 @@ options | - | - | TS 类型:`DialogOptions`
-- | -- | -- | --
options | - | - | TS 类型:`DialogOptions`

插件返回值:`DialogInstance`

### DialogPlugin.alert

同时也支持 `this.$dialog.alert`。这是一个插件函数,参数形式为顺序参数(形如:(a, b, c)),而非对象参数(形如:({ a, b, c }))。顺序参数如下,

参数名称 | 参数类型 | 参数默认值 | 参数说明
-- | -- | -- | --
options | Object | - | TS 类型:`Omit<DialogOptions, 'confirmBtn'>`

插件返回值:`DialogInstance`
22 changes: 17 additions & 5 deletions src/dialog/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ export default mixins(ActionMixin, getConfigReceiverMixins<Vue, DialogConfig>('d
const dialogClass = [`${name}`, `${name}--default`, `${name}--${this.placement}`, `${name}__modal-${this.theme}`];
if (['modeless', 'modal'].includes(this.mode)) {
dialogClass.push(`${name}--fixed`);
if (this.isModal && this.showInAttachedElement) {
dialogClass.push(`${name}--absolute`);
}
}

return dialogClass;
},
dialogStyle(): Styles {
Expand Down Expand Up @@ -101,11 +105,13 @@ export default mixins(ActionMixin, getConfigReceiverMixins<Vue, DialogConfig>('d
visible(value) {
if (value) {
const { scrollWidth } = this;
if (scrollWidth > 0) {
const bodyCssText = `position: relative;width: calc(100% - ${scrollWidth}px);`;
document.body.style.cssText = bodyCssText;
if (this.isModal && !this.showInAttachedElement) {
if (scrollWidth > 0) {
const bodyCssText = `position: relative;width: calc(100% - ${scrollWidth}px);`;
document.body.style.cssText = bodyCssText;
}
addClass(document.body, lockClass);
}
addClass(document.body, lockClass);
} else {
document.body.style.cssText = '';
removeClass(document.body, lockClass);
Expand Down Expand Up @@ -342,7 +348,13 @@ export default mixins(ActionMixin, getConfigReceiverMixins<Vue, DialogConfig>('d
const dialogView = this.renderDialog();
const view = [maskView, dialogView];
const ctxStyle: any = { zIndex: this.zIndex };
const ctxClass = [`${name}__ctx`, { [`${prefix}-dialog__ctx--fixed`]: this.mode === 'modal' }];
const ctxClass = [
`${name}__ctx`,
{
[`${prefix}-dialog__ctx--fixed`]: this.mode === 'modal',
[`${prefix}-dialog__ctx--absolute`]: this.isModal && this.showInAttachedElement,
},
];
return (
<transition
duration={300}
Expand Down
5 changes: 5 additions & 0 deletions src/dialog/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export default {
type: String as PropType<TdDialogProps['mode']>,
default: 'modal' as TdDialogProps['mode'],
validator(val: TdDialogProps['mode']): boolean {
if (!val) return true;
return ['modal', 'modeless', 'normal'].includes(val);
},
},
Expand All @@ -74,6 +75,7 @@ export default {
type: String as PropType<TdDialogProps['placement']>,
default: 'top' as TdDialogProps['placement'],
validator(val: TdDialogProps['placement']): boolean {
if (!val) return true;
return ['top', 'center'].includes(val);
},
},
Expand All @@ -82,6 +84,8 @@ export default {
type: Boolean,
default: true,
},
/** 仅在挂载元素中显示抽屉,默认在浏览器可视区域显示。父元素需要有定位属性,如:position: relative */
showInAttachedElement: Boolean,
/** 是否显示遮罩层 */
showOverlay: {
type: Boolean,
Expand All @@ -92,6 +96,7 @@ export default {
type: String as PropType<TdDialogProps['theme']>,
default: 'default' as TdDialogProps['theme'],
validator(val: TdDialogProps['theme']): boolean {
if (!val) return true;
return ['default', 'info', 'warning', 'danger', 'success'].includes(val);
},
},
Expand Down
10 changes: 7 additions & 3 deletions src/dialog/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* */

import { ButtonProps } from '../button';
import { TNode, AttachNode } from '../common';
import { TNode, Styles, AttachNode } from '../common';

export interface TdDialogProps {
/**
Expand Down Expand Up @@ -82,6 +82,11 @@ export interface TdDialogProps {
* @default true
*/
preventScrollThrough?: boolean;
/**
* 仅在挂载元素中显示抽屉,默认在浏览器可视区域显示。父元素需要有定位属性,如:position: relative
* @default false
*/
showInAttachedElement?: boolean;
/**
* 是否显示遮罩层
* @default true
Expand Down Expand Up @@ -156,9 +161,8 @@ export interface DialogOptions extends Omit<TdDialogProps, 'attach'> {
className?: string;
/**
* 弹框 style 属性,输入 [CSSStyleDeclaration.cssText](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/cssText)
* @default ''
*/
style?: string;
style?: string | Styles;
}

export interface DialogInstance {
Expand Down
3 changes: 2 additions & 1 deletion test/ssr/__snapshots__/ssr.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3415,7 +3415,8 @@ exports[`ssr snapshot test renders ./examples/dialog/demos/async.vue correctly 1
`;

exports[`ssr snapshot test renders ./examples/dialog/demos/attach.vue correctly 1`] = `
<div><button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-primary"><span class="t-button__text">挂载在body</span></button> <button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-primary"><span class="t-button__text">挂载特定元素</span></button> <button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-primary"><span class="t-button__text">挂载函数返回节点</span></button>
<div class="dialog-attach-wrap"><button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-primary"><span class="t-button__text">挂载在body</span></button> <button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-primary"><span class="t-button__text">挂载特定元素</span></button> <button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-primary"><span class="t-button__text">挂载函数返回节点</span></button> <button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-primary"><span class="t-button__text">展示在挂载元素区域</span></button>
<div duration="300" name="t-dialog-zoom__vue"></div>
<div duration="300" name="t-dialog-zoom__vue"></div>
<div duration="300" name="t-dialog-zoom__vue"></div>
<div duration="300" name="t-dialog-zoom__vue"></div>
Expand Down
94 changes: 93 additions & 1 deletion test/unit/dialog/__snapshots__/demo.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ exports[`Dialog async demo works fine 1`] = `
`;

exports[`Dialog attach demo works fine 1`] = `
<div>
<div
class="dialog-attach-wrap"
>
<button
class="t-button t-size-m t-button--variant-base t-button--theme-primary"
type="button"
Expand Down Expand Up @@ -147,6 +149,17 @@ exports[`Dialog attach demo works fine 1`] = `
</span>
</button>

<button
class="t-button t-size-m t-button--variant-base t-button--theme-primary"
type="button"
>
<span
class="t-button__text"
>
展示在挂载元素区域
</span>
</button>

<transition-stub
duration="300"
name="t-dialog-zoom__vue"
Expand All @@ -161,6 +174,85 @@ exports[`Dialog attach demo works fine 1`] = `
duration="300"
name="t-dialog-zoom__vue"
/>

<transition-stub
duration="300"
name="t-dialog-zoom__vue"
>
<div
class="t-dialog__ctx t-dialog__ctx--fixed t-dialog__ctx--absolute"
style="display: none;"
>
<div
class="t-dialog__mask"
/>
<div
class="t-dialog t-dialog--default t-dialog--center t-dialog__modal-default t-dialog--fixed t-dialog--absolute"
>
<div
class="t-dialog__header"
>
对话框仅展示在挂载元素区域
</div>
<span
class="t-dialog__close"
>
<svg
class="t-icon t-icon-close"
fill="none"
height="1em"
viewBox="0 0 16 16"
width="1em"
>
<path
d="M8 8.92L11.08 12l.92-.92L8.92 8 12 4.92 11.08 4 8 7.08 4.92 4 4 4.92 7.08 8 4 11.08l.92.92L8 8.92z"
fill="currentColor"
fill-opacity="0.9"
/>
</svg>
</span>
<div
class="t-dialog__body"
>
<div>
<div>
父元素(挂载元素)需要有定位属性,如:position: relative
</div>

<div>
showInAttachedElement API 仅针对模态对话框有效
</div>
</div>
</div>
<div
class="t-dialog__footer"
>
<div>
<button
class="t-button t-size-m t-button--variant-base t-button--theme-default t-dialog__cancel"
type="button"
>
<span
class="t-button__text"
>
取消
</span>
</button>
<button
class="t-button t-size-m t-button--variant-base t-button--theme-primary t-dialog__confirm"
type="button"
>
<span
class="t-button__text"
>
确认
</span>
</button>
</div>
</div>
</div>
</div>
</transition-stub>
</div>
`;

Expand Down