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: Drawer add loading prop to show spinner #48563

Merged
merged 6 commits into from Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 32 additions & 0 deletions components/drawer/DrawerPanel.tsx
Expand Up @@ -5,6 +5,8 @@ import type { DrawerProps as RCDrawerProps } from 'rc-drawer';
import useClosable, { pickClosable } from '../_util/hooks/useClosable';
import type { ClosableType } from '../_util/hooks/useClosable';
import { ConfigContext } from '../config-provider';
import Spin from '../spin';
import type { SpinProps } from '../spin';

export interface DrawerClassNames extends NonNullable<RCDrawerProps['classNames']> {
header?: string;
Expand Down Expand Up @@ -38,6 +40,7 @@ export interface DrawerPanelProps {
children?: React.ReactNode;
classNames?: DrawerClassNames;
styles?: DrawerStyles;
loading?: boolean | Omit<SpinProps, 'fullscreen' | 'tip'>;

/** @deprecated Please use `styles.header` instead */
headerStyle?: React.CSSProperties;
Expand All @@ -59,6 +62,7 @@ const DrawerPanel: React.FC<DrawerPanelProps> = (props) => {
title,
footer,
extra,
loading,
onClose,
headerStyle,
bodyStyle,
Expand Down Expand Up @@ -87,6 +91,19 @@ const DrawerPanel: React.FC<DrawerPanelProps> = (props) => {
},
);

// >>>>>>>>> Spinning
let spinProps: SpinProps | undefined;
if (typeof loading === 'boolean') {
spinProps = {
spinning: loading,
};
} else if (typeof loading === 'object') {
Enigama marked this conversation as resolved.
Show resolved Hide resolved
spinProps = {
spinning: true,
...loading,
};
}

const headerNode = React.useMemo<React.ReactNode>(() => {
if (!title && !mergedClosable) {
return null;
Expand Down Expand Up @@ -139,6 +156,21 @@ const DrawerPanel: React.FC<DrawerPanelProps> = (props) => {
);
}, [footer, footerStyle, prefixCls]);

if (spinProps?.spinning) {
return (
<Spin
spinning={false}
style={{
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
{...spinProps}
/>
);
}

return (
<>
{headerNode}
Expand Down
29 changes: 29 additions & 0 deletions components/drawer/__tests__/Drawer.test.tsx
Expand Up @@ -178,6 +178,35 @@ describe('Drawer', () => {
expect(baseElement.querySelectorAll('button.forceRender').length).toBe(1);
});

describe('Drawer loading', () => {
it('have a spinner', () => {
const { container: wrapper } = render(
<Drawer open loading getContainer={false}>
Here is content of Drawer
</Drawer>,
);

triggerMotion();
expect(wrapper.firstChild).toMatchSnapshot();
});
it('have a custom loading', () => {
const loadingContent = 'Custom Loading...';
const { container: wrapper } = render(
<Drawer
open
loading={{ indicator: <span>{loadingContent}</span>, spinning: true }}
getContainer={false}
>
Here is content of Drawer
</Drawer>,
);

triggerMotion();
const [loadingWrapper] = wrapper.getElementsByClassName('ant-spin-dot');
expect(loadingWrapper).toHaveTextContent(loadingContent);
});
});

it('support closeIcon', () => {
const { container: wrapper } = render(
<Drawer open closable closeIcon={<span>close</span>} width={400} getContainer={false}>
Expand Down
57 changes: 57 additions & 0 deletions components/drawer/__tests__/__snapshots__/Drawer.test.tsx.snap
@@ -1,5 +1,62 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Drawer Drawer loading have a spinner 1`] = `
<div
class="ant-drawer ant-drawer-right ant-drawer-open ant-drawer-inline"
tabindex="-1"
>
<div
class="ant-drawer-mask"
/>
<div
aria-hidden="true"
data-sentinel="start"
style="width: 0px; height: 0px; overflow: hidden; outline: none; position: absolute;"
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
aria-modal="true"
class="ant-drawer-content"
role="dialog"
>
<div
aria-busy="true"
aria-live="polite"
class="ant-spin ant-spin-spinning"
style="height: 100%; display: flex; justify-content: center; align-items: center;"
>
<span
class="ant-spin-dot ant-spin-dot-spin"
>
<i
class="ant-spin-dot-item"
/>
<i
class="ant-spin-dot-item"
/>
<i
class="ant-spin-dot-item"
/>
<i
class="ant-spin-dot-item"
/>
</span>
</div>
</div>
</div>
<div
aria-hidden="true"
data-sentinel="end"
style="width: 0px; height: 0px; overflow: hidden; outline: none; position: absolute;"
tabindex="0"
/>
</div>
`;

exports[`Drawer className is test_drawer 1`] = `
<div
class="ant-drawer ant-drawer-right test_drawer ant-drawer-open ant-drawer-inline"
Expand Down
Expand Up @@ -2781,6 +2781,75 @@ Array [

exports[`renders components/drawer/demo/form-in-drawer.tsx extend context correctly 2`] = `[]`;

exports[`renders components/drawer/demo/loading.tsx extend context correctly 1`] = `
Array [
<button
class="ant-btn ant-btn-primary"
type="button"
>
<span>
Open
</span>
</button>,
<div
class="ant-drawer ant-drawer-right ant-drawer-open ant-drawer-inline"
tabindex="-1"
>
<div
class="ant-drawer-mask"
/>
<div
aria-hidden="true"
data-sentinel="start"
style="width: 0px; height: 0px; overflow: hidden; outline: none; position: absolute;"
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
aria-modal="true"
class="ant-drawer-content"
role="dialog"
>
<div
aria-busy="true"
aria-live="polite"
class="ant-spin ant-spin-spinning"
style="height: 100%; display: flex; justify-content: center; align-items: center;"
>
<span
class="ant-spin-dot ant-spin-dot-spin"
>
<i
class="ant-spin-dot-item"
/>
<i
class="ant-spin-dot-item"
/>
<i
class="ant-spin-dot-item"
/>
<i
class="ant-spin-dot-item"
/>
</span>
</div>
</div>
</div>
<div
aria-hidden="true"
data-sentinel="end"
style="width: 0px; height: 0px; overflow: hidden; outline: none; position: absolute;"
tabindex="0"
/>
</div>,
]
`;

exports[`renders components/drawer/demo/loading.tsx extend context correctly 2`] = `[]`;

exports[`renders components/drawer/demo/multi-level-drawer.tsx extend context correctly 1`] = `
Array [
<button
Expand Down
11 changes: 11 additions & 0 deletions components/drawer/__tests__/__snapshots__/demo.test.ts.snap
Expand Up @@ -259,6 +259,17 @@ exports[`renders components/drawer/demo/form-in-drawer.tsx correctly 1`] = `
</button>
`;

exports[`renders components/drawer/demo/loading.tsx correctly 1`] = `
<button
class="ant-btn ant-btn-primary"
type="button"
>
<span>
Open
</span>
</button>
`;

exports[`renders components/drawer/demo/multi-level-drawer.tsx correctly 1`] = `
<button
class="ant-btn ant-btn-primary"
Expand Down
7 changes: 7 additions & 0 deletions components/drawer/demo/loading.md
@@ -0,0 +1,7 @@
## zh-CN

设置抽屉加载状态。

## en-US

Set the loading status of Drawer.
54 changes: 54 additions & 0 deletions components/drawer/demo/loading.tsx
@@ -0,0 +1,54 @@
import React, { useEffect, useState } from 'react';
import type { DrawerProps } from 'antd';
import { Button, Drawer } from 'antd';

const App: React.FC = () => {
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState<DrawerProps['loading']>(true);
let id: NodeJS.Timer;

const showDrawer = () => {
setOpen(true);
};

const onClose = () => {
setOpen(false);
clearTimeout(Number(id));
};

useEffect(() => {
setLoading(true);
}, []);

useEffect(() => {
if (open) {
id = setTimeout(() => {
setLoading(false);
}, 1000);
}
}, [open]);

return (
<>
<Button type="primary" onClick={showDrawer}>
Open
</Button>
<Drawer
title="Basic Drawer"
placement="right"
closable={false}
onClose={onClose}
open={open}
loading={loading}
afterOpenChange={(visible) => !visible && setLoading(true)}
>
<Button onClick={() => setLoading(true)}>set Loading true</Button>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Drawer>
</>
);
};

export default App;
2 changes: 2 additions & 0 deletions components/drawer/index.en-US.md
Expand Up @@ -22,6 +22,7 @@ A Drawer is a panel that is typically overlaid on top of a page and slides in fr
<!-- prettier-ignore -->
<code src="./demo/basic-right.tsx">Basic</code>
<code src="./demo/placement.tsx">Custom Placement</code>
<code src="./demo/loading.tsx">Loading</code>
<code src="./demo/extra.tsx">Extra Actions</code>
<code src="./demo/render-in-current.tsx">Render in current dom</code>
<code src="./demo/form-in-drawer.tsx">Submit form in drawer</code>
Expand Down Expand Up @@ -68,6 +69,7 @@ v5 use `rootClassName` & `rootStyle` to config wrapper style instead of `classNa
| styles | Semantic structure style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.10.0 |
| size | preset size of drawer, default `378px` and large `736px` | 'default' \| 'large' | 'default' | 4.17.0 |
| title | The title for Drawer | ReactNode | - | |
| loading | Show spinning indicator | boolean \| `Omit<SpinProp, 'fullScreen' \| 'tip'>` | false | 5.17.0 |
| open | Whether the Drawer dialog is visible or not | boolean | false | |
| width | Width of the Drawer dialog | string \| number | 378 | |
| zIndex | The `z-index` of the Drawer | number | 1000 | |
Expand Down
2 changes: 2 additions & 0 deletions components/drawer/index.zh-CN.md
Expand Up @@ -22,6 +22,7 @@ demo:
<!-- prettier-ignore -->
<code src="./demo/basic-right.tsx">基础抽屉</code>
<code src="./demo/placement.tsx">自定义位置</code>
<code src="./demo/loading.tsx">加载中</code>
<code src="./demo/extra.tsx">额外操作</code>
<code src="./demo/render-in-current.tsx">渲染在当前 DOM</code>
<code src="./demo/form-in-drawer.tsx">抽屉表单</code>
Expand Down Expand Up @@ -67,6 +68,7 @@ v5 使用 `rootClassName` 与 `rootStyle` 来配置最外层元素样式。原 v
| style | 设计 Drawer 容器样式,如果你只需要设置内容部分请使用 `bodyStyle` | CSSProperties | - | |
| styles | 语义化结构 style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.10.0 |
| title | 标题 | ReactNode | - | |
| loading | 显示旋转指示器 | boolean \| `Omit<SpinProp, 'fullScreen' \| 'tip'>` | false | 5.17.0 |
| open | Drawer 是否可见 | boolean | - |
| width | 宽度 | string \| number | 378 | |
| zIndex | 设置 Drawer 的 `z-index` | number | 1000 | |
Expand Down