Skip to content

Commit 2327089

Browse files
authored
Merge pull request #1631 from sheinsight/feat/modal-mask-blur
feat(modal): add mask prop with blur support
2 parents 04188f4 + e8c19c2 commit 2327089

File tree

9 files changed

+123
-8
lines changed

9 files changed

+123
-8
lines changed

docs/api/shineout/modal.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "sheinx",
33
"private": true,
4-
"version": "3.9.9",
4+
"version": "3.9.10-beta.1",
55
"description": "A react library developed with sheinx",
66
"module": "dist/index.js",
77
"types": "dist/index.d.ts",

packages/base/src/config/index.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ type TooltipConfig = {
1717
persistent?: boolean;
1818
}
1919

20+
/**
21+
* @en Global configuration for Modal component
22+
* @cn Modal组件的全局配置
23+
* @version 3.9.10
24+
*/
25+
export type ModalConfig = {
26+
/**
27+
* @en Global default mask setting for Modal component. false to hide mask, { blur: true } to show blurred mask
28+
* @cn Modal组件的全局默认遮罩设置。false 隐藏遮罩,{ blur: true } 显示模糊遮罩
29+
*/
30+
mask?: boolean | { blur?: boolean };
31+
}
32+
2033
/**
2134
* @en Global configuration for Popover component
2235
* @cn Popover组件的全局配置
@@ -56,6 +69,12 @@ export interface ConfigOption {
5669
spin?: SpinConfig;
5770
tooltip?: TooltipConfig;
5871
popover?: PopoverConfig;
72+
/**
73+
* @en Global configuration for Modal component
74+
* @cn Modal组件的全局配置
75+
* @version 3.9.10
76+
*/
77+
modal?: ModalConfig;
5978
/**
6079
* @en Global configuration for Empty component
6180
* @cn Empty组件的全局配置
@@ -76,6 +95,7 @@ export const defaultConfig: ConfigOption = {
7695
spin: 'ring',
7796
tooltip: undefined,
7897
popover: {},
98+
modal: {},
7999
empty: {},
80100
direction: 'ltr',
81101
popupContainer: null,

packages/base/src/modal/modal-content.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,12 @@ const Modal = (props: ModalContentProps) => {
271271
}
272272
})
273273

274+
const maskProp = props.mask ?? globalConfig.modal?.mask;
275+
const hideMask = props.hideMask || maskProp === false;
276+
const maskBlur = typeof maskProp === 'object' && maskProp?.blur;
277+
274278
useEffect(() => {
275-
if (!props.hideMask) {
279+
if (!hideMask) {
276280
if (visible) {
277281
setDocumentOverflow();
278282
} else {
@@ -308,6 +312,7 @@ const Modal = (props: ModalContentProps) => {
308312
if (props.setInnerClose) {
309313
props.setInnerClose(() => {
310314
setVisible(false);
315+
setAnimation(true);
311316
});
312317
}
313318
}, [props.setInnerClose]);
@@ -500,7 +505,8 @@ const Modal = (props: ModalContentProps) => {
500505
showMask && modalClasses?.wrapperIsMask,
501506
props.fullScreen && modalClasses?.wrapperFullScreen,
502507
props.moveable && modalClasses?.wrapperMoveable,
503-
props.hideMask && modalClasses?.wrapperHideMask,
508+
hideMask && modalClasses?.wrapperHideMask,
509+
maskBlur && modalClasses?.wrapperMaskBlur,
504510
props.zoom && !props.moveable && modalClasses?.wrapperZoom,
505511
(isPositionX || isPositionY) && modalClasses?.wrapperDrawer,
506512
props.position === 'left' && modalClasses?.wrapperDrawerLeft,

packages/base/src/modal/modal-func.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,17 @@ const method =
9191
(type: MethodType, jssStyle: ModalJssStyle) => (options: Omit<ModalOptions, 'jssStyle'>) => {
9292
const id = util.getUidStr();
9393
let innerClose: () => void;
94+
let destroyed = false;
9495
const root = getRoot({ container: options.container });
9596
if (!root) return;
97+
const doDestroy = () => {
98+
if (destroyed) return;
99+
destroyed = true;
100+
destroy(root);
101+
};
96102
const destroyModal = () => {
97103
if (innerClose) innerClose();
98-
setTimeout(() => {
99-
destroy(root);
100-
}, 300);
104+
setTimeout(doDestroy, 300);
101105
};
102106
modals.add(root);
103107
const btnOptions = {
@@ -130,7 +134,7 @@ const method =
130134
type={type as any}
131135
footer={footer}
132136
shouldDestroy={(can) => {
133-
if (can) destroyModal();
137+
if (can) doDestroy();
134138
}}
135139
setInnerClose={(close) => {
136140
innerClose = close;

packages/base/src/modal/modal.type.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface ModalClasses {
1717
wrapperZoom: string;
1818
wrapperIsMask: string;
1919
wrapperHideMask: string;
20+
wrapperMaskBlur: string;
2021
wrapperDrawer: string;
2122
wrapperDrawerLeft: string;
2223
wrapperDrawerRight: string;
@@ -51,8 +52,16 @@ export interface ModalProps extends Pick<CommonType, 'className' | 'style'> {
5152
* @en Whether to hide mask
5253
* @cn 是否隐藏遮罩
5354
* @default false
55+
* @deprecated 推荐使用 mask={false} 来隐藏遮罩
5456
*/
5557
hideMask?: boolean;
58+
59+
/**
60+
* @en Control mask display. false to hide mask, { blur: true } to show blurred mask
61+
* @cn 控制遮罩显示。false 隐藏遮罩,{ blur: true } 显示模糊遮罩
62+
* @version 3.9.10
63+
*/
64+
mask?: boolean | { blur?: boolean };
5665
/**
5766
* @en Whether to force the mask transparency (in multi-layer Modal, the transparency of other Modal masks except the first layer will be adjusted to 0.01)
5867
* @cn 是否强制设置遮罩透明度(多层Modal中,除第一层外的其他弹出层遮罩透明度会被调整为0.01)

packages/shineout-style/src/modal/modal.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ const modalStyle: JsStyles<ModalClassType> = {
183183
pointerEvents: 'none',
184184
},
185185
},
186+
wrapperMaskBlur: {
187+
backdropFilter: 'blur(4px)',
188+
WebkitBackdropFilter: 'blur(4px)',
189+
},
186190
wrapperMoveable: {
187191
'& $header': {
188192
cursor: 'move',

packages/shineout/src/modal/__doc__/changelog.cn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 3.9.10-beta.1
2+
2026-02-25
3+
### 🆕 Feature
4+
- `Modal` 新增 `mask` 属性支持设置为 `{ blur: true }` 来启用模糊遮罩效果 ([#1631](https://github.com/sheinsight/shineout-next/pull/1631))
5+
16
## 3.9.8-beta.11
27
2026-01-21
38
### 🐞 BugFix
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* cn - 遮罩
3+
* -- 通过 `mask` 属性控制遮罩的显示。设置 `mask={false}` 隐藏遮罩,设置 `mask={{ blur: true }}` 显示模糊遮罩
4+
* en - Mask
5+
* -- Use the `mask` prop to control the mask display. Set `mask={false}` to hide the mask, set `mask={{ blur: true }}` to show a blurred mask
6+
*/
7+
import React, { useState } from 'react';
8+
import { Modal, Button } from 'shineout';
9+
10+
const App: React.FC = () => {
11+
const [visible1, setVisible1] = useState(false);
12+
const [visible2, setVisible2] = useState(false);
13+
14+
const info1 = () => {
15+
Modal.info({
16+
title: 'This is a info message',
17+
content: 'this is some information that user must know',
18+
mask: { blur: true },
19+
});
20+
};
21+
22+
const info2 = () => {
23+
Modal.info({
24+
title: 'This is a success message',
25+
content: 'this is some information that user successful operation',
26+
mask: false,
27+
});
28+
};
29+
30+
return (
31+
<div style={{ display: 'flex', gap: '16px' }}>
32+
<Button mode='outline' onClick={() => setVisible1(true)}>
33+
mask blur
34+
</Button>
35+
<Button mode='outline' onClick={() => setVisible2(true)}>
36+
mask=false
37+
</Button>
38+
<Modal
39+
title='Modal with blur mask'
40+
visible={visible1}
41+
onClose={() => setVisible1(false)}
42+
mask={{ blur: true }}
43+
footer={<Button type="primary" onClick={() => setVisible1(false)}>Close</Button>}
44+
>
45+
This modal has a blurred mask
46+
</Modal>
47+
<Modal
48+
title='Modal without mask'
49+
visible={visible2}
50+
onClose={() => setVisible2(false)}
51+
mask={false}
52+
footer={<Button type="primary" onClick={() => setVisible2(false)}>Close</Button>}
53+
>
54+
This modal has no mask
55+
</Modal>
56+
57+
<Button type='primary' onClick={info1}>
58+
info (blur)
59+
</Button>
60+
<Button type='primary' onClick={info2}>
61+
info (no mask)
62+
</Button>
63+
</div>
64+
);
65+
};
66+
67+
export default App;

0 commit comments

Comments
 (0)