Skip to content

Commit

Permalink
feat: Drawer add loading prop to show spinner
Browse files Browse the repository at this point in the history
  • Loading branch information
Enigama authored and EnigamaE committed Apr 20, 2024
1 parent ed127e9 commit f70bd86
Show file tree
Hide file tree
Showing 9 changed files with 314 additions and 2 deletions.
36 changes: 34 additions & 2 deletions components/drawer/DrawerPanel.tsx
Expand Up @@ -5,6 +5,23 @@ 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';

interface PanelNodeProps {
children: React.ReactNode;
spinProps?: SpinProps;
}
const PanelNode: React.FC<PanelNodeProps> = ({ children, spinProps }) => {
if (!spinProps) {
return children;
}
return (
<Spin spinning={false} {...spinProps}>
{children}
</Spin>
);
};

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

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

// >>>>>>>>> Spinning
let spinProps: SpinProps | undefined;
if (typeof loading === 'boolean') {
spinProps = {
spinning: loading,
};
} else if (typeof loading === 'object') {
spinProps = {
spinning: true,
...loading,
};
}

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

return (
<>
<PanelNode spinProps={spinProps}>
{headerNode}
<div
className={classNames(
Expand All @@ -157,7 +189,7 @@ const DrawerPanel: React.FC<DrawerPanelProps> = (props) => {
{children}
</div>
{footerNode}
</>
</PanelNode>
);
};

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

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('support closeIcon', () => {
const { container: wrapper } = render(
<Drawer open closable closeIcon={<span>close</span>} width={400} getContainer={false}>
Expand Down
105 changes: 105 additions & 0 deletions components/drawer/__tests__/__snapshots__/Drawer.test.tsx.snap
Expand Up @@ -269,6 +269,111 @@ exports[`Drawer have a footer 1`] = `
</div>
`;

exports[`Drawer 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
class="ant-spin-nested-loading"
>
<div>
<div
aria-busy="true"
aria-live="polite"
class="ant-spin ant-spin-spinning"
>
<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
class="ant-spin-container ant-spin-blur"
>
<div
class="ant-drawer-header ant-drawer-header-close-only"
>
<div
class="ant-drawer-header-title"
>
<button
aria-label="Close"
class="ant-drawer-close"
type="button"
>
<span
aria-label="close"
class="anticon anticon-close"
role="img"
>
<svg
aria-hidden="true"
data-icon="close"
fill="currentColor"
fill-rule="evenodd"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M799.86 166.31c.02 0 .04.02.08.06l57.69 57.7c.04.03.05.05.06.08a.12.12 0 010 .06c0 .03-.02.05-.06.09L569.93 512l287.7 287.7c.04.04.05.06.06.09a.12.12 0 010 .07c0 .02-.02.04-.06.08l-57.7 57.69c-.03.04-.05.05-.07.06a.12.12 0 01-.07 0c-.03 0-.05-.02-.09-.06L512 569.93l-287.7 287.7c-.04.04-.06.05-.09.06a.12.12 0 01-.07 0c-.02 0-.04-.02-.08-.06l-57.69-57.7c-.04-.03-.05-.05-.06-.07a.12.12 0 010-.07c0-.03.02-.05.06-.09L454.07 512l-287.7-287.7c-.04-.04-.05-.06-.06-.09a.12.12 0 010-.07c0-.02.02-.04.06-.08l57.7-57.69c.03-.04.05-.05.07-.06a.12.12 0 01.07 0c.03 0 .05.02.09.06L512 454.07l287.7-287.7c.04-.04.06-.05.09-.06a.12.12 0 01.07 0z"
/>
</svg>
</span>
</button>
</div>
</div>
<div
class="ant-drawer-body"
>
Here is content of Drawer
</div>
</div>
</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 have a title 1`] = `
<div
class="ant-drawer ant-drawer-right ant-drawer-open ant-drawer-inline"
Expand Down
104 changes: 104 additions & 0 deletions components/drawer/__tests__/__snapshots__/demo-extend.test.tsx.snap
Expand Up @@ -2781,6 +2781,110 @@ 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
class="ant-spin-nested-loading"
>
<div>
<div
aria-busy="true"
aria-live="polite"
class="ant-spin ant-spin-spinning"
>
<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
class="ant-spin-container ant-spin-blur"
>
<div
class="ant-drawer-header"
>
<div
class="ant-drawer-header-title"
>
<div
class="ant-drawer-title"
>
Basic Drawer
</div>
</div>
</div>
<div
class="ant-drawer-body"
>
<p>
Some contents...
</p>
<p>
Some contents...
</p>
<p>
Some contents...
</p>
</div>
</div>
</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.
38 changes: 38 additions & 0 deletions components/drawer/demo/loading.tsx
@@ -0,0 +1,38 @@
import React, { useState } from 'react';
import type { DrawerProps } from 'antd';
import { Button, Drawer } from 'antd';

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

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

const onClose = () => {
setOpen(false);
};

return (
<>
<Button type="primary" onClick={showDrawer}>
Open
</Button>
<Drawer
title="Basic Drawer"
placement="right"
closable={false}
onClose={onClose}
open={open}
loading={loading}
>
<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'>` | false | 5.2.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

0 comments on commit f70bd86

Please sign in to comment.