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(spin): Adds fullscreen property to <Spin /> component #44986

Merged
merged 23 commits into from Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b2fa189
feat: start the implementation of the fullscreen prop in Spin
Rafael-Martins Sep 20, 2023
a1a24d9
Merge branch 'feature' into implement-spin-fullscreen
Rafael-Martins Sep 21, 2023
e033b61
docs: change main spin demo
Rafael-Martins Sep 21, 2023
3c59d35
docs: enhance demo
Rafael-Martins Sep 21, 2023
99524e9
test: update snapshot
Rafael-Martins Sep 21, 2023
1ebe3a4
fix: address pr comments
Rafael-Martins Sep 21, 2023
be24cef
fix: use logical property on fullscreen class
Rafael-Martins Sep 21, 2023
913075c
fix: address pr review
Rafael-Martins Sep 21, 2023
7207911
feat: Added background color token
Rafael-Martins Sep 21, 2023
056a88f
fix: remove onClick and change demo
Rafael-Martins Sep 22, 2023
46e5771
Merge branch 'feature' into implement-spin-fullscreen
li-jia-nan Oct 7, 2023
7bef1c4
feat: change spin to white when fullcreen
Rafael-Martins Oct 9, 2023
439e339
fix: unused import
Rafael-Martins Oct 9, 2023
9915301
test: update snapshot
Rafael-Martins Oct 9, 2023
209b968
Update components/spin/style/index.tsx
li-jia-nan Oct 10, 2023
3bfc920
fix: use white color from token
Rafael-Martins Oct 10, 2023
e86a959
fix: not needed interpolation and version
Rafael-Martins Oct 10, 2023
df87baf
fix: address pr review
Rafael-Martins Oct 11, 2023
e7ea080
fix: tip prop was not working
Rafael-Martins Oct 11, 2023
5d972f1
test: cover tip & fullscreen case
Rafael-Martins Oct 11, 2023
e652fb1
Merge branch 'feature' into implement-spin-fullscreen
Rafael-Martins Oct 17, 2023
c14b4e6
fix: addrress pr coments
Rafael-Martins Oct 17, 2023
d52779a
Merge branch 'feature' into implement-spin-fullscreen
MadCcc Oct 19, 2023
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
13 changes: 13 additions & 0 deletions components/spin/__tests__/__snapshots__/demo-extend.test.ts.snap
Expand Up @@ -118,6 +118,19 @@ exports[`renders components/spin/demo/delayAndDebounce.tsx extend context correc

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

exports[`renders components/spin/demo/fullscreen.tsx extend context correctly 1`] = `
<button
class="ant-btn ant-btn-default"
type="button"
>
<span>
Show fullscreen for 2s
</span>
</button>
`;

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

exports[`renders components/spin/demo/inside.tsx extend context correctly 1`] = `
<div
class="example"
Expand Down
11 changes: 11 additions & 0 deletions components/spin/__tests__/__snapshots__/demo.test.ts.snap
Expand Up @@ -112,6 +112,17 @@ exports[`renders components/spin/demo/delayAndDebounce.tsx correctly 1`] = `
</div>
`;

exports[`renders components/spin/demo/fullscreen.tsx correctly 1`] = `
<button
class="ant-btn ant-btn-default"
type="button"
>
<span>
Show fullscreen for 2s
</span>
</button>
`;

exports[`renders components/spin/demo/inside.tsx correctly 1`] = `
<div
class="example"
Expand Down
12 changes: 11 additions & 1 deletion components/spin/__tests__/index.test.tsx
@@ -1,5 +1,6 @@
import { render } from '@testing-library/react';
import React from 'react';
import { render } from '@testing-library/react';

import Spin from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
Expand All @@ -19,6 +20,15 @@ describe('Spin', () => {
expect(container.querySelector<HTMLElement>('.ant-spin')?.style.background).toBe('red');
});

it('should not apply nested styles when full screen', () => {
const { container } = render(
<Spin fullscreen>
<div>content</div>
</Spin>,
);
expect(container.querySelector<HTMLElement>('ant-spin-nested-loading')).toBeNull();
});

it("should render custom indicator when it's set", () => {
const customIndicator = <div className="custom-indicator" />;
const { asFragment } = render(<Spin indicator={customIndicator} />);
Expand Down
7 changes: 7 additions & 0 deletions components/spin/demo/fullscreen.md
@@ -0,0 +1,7 @@
## zh-CN

`fullscreen` 属性非常适合创建流畅的页面加载器。它添加了半透明覆盖层,并在其中心放置了一个旋转加载符号。

## en-US

The `fullscreen` mode is perfect for creating page loaders. It adds a dimmed overlay with a centered spinner.
23 changes: 23 additions & 0 deletions components/spin/demo/fullscreen.tsx
@@ -0,0 +1,23 @@
import React, { useState } from 'react';
import { Button, Spin } from 'antd';

const App: React.FC = () => {
const [show, setShow] = useState(false);

const showLoader = () => {
setShow(true);

setTimeout(() => {
setShow(false);
}, 2000);
};

return (
<>
<Button onClick={showLoader}>Show fullscreen for 2s</Button>
{show && <Spin fullscreen size="large" />}
</>
);
};

export default App;
10 changes: 6 additions & 4 deletions components/spin/index.en-US.md
Expand Up @@ -17,26 +17,28 @@ When part of the page is waiting for asynchronous data or during a rendering pro
## Examples

<!-- prettier-ignore -->
<code src="./demo/basic.tsx">basic Usage</code>
<code src="./demo/basic.tsx">Basic Usage</code>
<code src="./demo/size.tsx">Size</code>
<code src="./demo/inside.tsx">Inside a container</code>
<code src="./demo/nested.tsx">Embedded mode</code>
<code src="./demo/tip.tsx">Customized description</code>
<code src="./demo/delayAndDebounce.tsx">delay</code>
<code src="./demo/delayAndDebounce.tsx">Delay</code>
<code src="./demo/custom-indicator.tsx">Custom spinning indicator</code>
<code src="./demo/fullscreen.tsx">Fullscreen</code>

## API

Common props ref:[Common props](/docs/react/common-props)

| Property | Description | Type | Default |
| --- | --- | --- | --- |
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| delay | Specifies a delay in milliseconds for loading state (prevent flush) | number (milliseconds) | - |
| indicator | React node of the spinning indicator | ReactNode | - |
| size | The size of Spin, options: `small`, `default` and `large` | string | `default` |
| spinning | Whether Spin is visible | boolean | true |
| tip | Customize description content when Spin has children | ReactNode | - |
| wrapperClassName | The className of wrapper when Spin has children | string | - |
| fullscreen | Display a backdrop with the `Spin` component | boolean | false | 5.11.0 |

### Static Method

Expand Down
12 changes: 10 additions & 2 deletions components/spin/index.tsx
Expand Up @@ -25,6 +25,7 @@ export interface SpinProps {
wrapperClassName?: string;
indicator?: SpinIndicator;
children?: React.ReactNode;
fullscreen?: boolean;
}

export interface SpinClassProps extends SpinProps {
Expand Down Expand Up @@ -87,6 +88,7 @@ const Spin: React.FC<SpinClassProps> = (props) => {
style,
children,
hashId,
fullscreen,
...restProps
} = props;

Expand All @@ -108,7 +110,10 @@ const Spin: React.FC<SpinClassProps> = (props) => {
setSpinning(false);
}, [delay, customSpinning]);

const isNestedPattern = React.useMemo<boolean>(() => typeof children !== 'undefined', [children]);
const isNestedPattern = React.useMemo<boolean>(
() => typeof children !== 'undefined' && !fullscreen,
[children, fullscreen],
);

if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning('Spin');
Expand All @@ -126,6 +131,7 @@ const Spin: React.FC<SpinClassProps> = (props) => {
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-spinning`]: spinning,
[`${prefixCls}-show-text`]: !!tip,
[`${prefixCls}-fullscreen`]: fullscreen,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
Expand All @@ -151,7 +157,9 @@ const Spin: React.FC<SpinClassProps> = (props) => {
aria-busy={spinning}
>
{renderIndicator(prefixCls, props)}
{tip && isNestedPattern ? <div className={`${prefixCls}-text`}>{tip}</div> : null}
{tip && (isNestedPattern || fullscreen) ? (
<div className={`${prefixCls}-text`}>{tip}</div>
) : null}
</div>
);

Expand Down
18 changes: 10 additions & 8 deletions components/spin/index.zh-CN.md
Expand Up @@ -25,19 +25,21 @@ demo:
<code src="./demo/tip.tsx">自定义描述文案</code>
<code src="./demo/delayAndDebounce.tsx">延迟</code>
<code src="./demo/custom-indicator.tsx">自定义指示符</code>
<code src="./demo/fullscreen.tsx">全屏</code>

## API

通用属性参考:[通用属性](/docs/react/common-props)

| 参数 | 说明 | 类型 | 默认值 |
| ---------------- | -------------------------------------------- | ------------- | --------- |
| delay | 延迟显示加载效果的时间(防止闪烁) | number (毫秒) | - |
| indicator | 加载指示符 | ReactNode | - |
| size | 组件大小,可选值为 `small` `default` `large` | string | `default` |
| spinning | 是否为加载中状态 | boolean | true |
| tip | 当作为包裹元素时,可以自定义描述文案 | ReactNode | - |
| wrapperClassName | 包装器的类属性 | string | - |
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| delay | 延迟显示加载效果的时间(防止闪烁) | number (毫秒) | - |
| indicator | 加载指示符 | ReactNode | - |
| size | 组件大小,可选值为 `small` `default` `large` | string | `default` |
| spinning | 是否为加载中状态 | boolean | true |
| tip | 当作为包裹元素时,可以自定义描述文案 | ReactNode | - |
| wrapperClassName | 包装器的类属性 | string | - |
| fullscreen | 显示带有 `Spin` 组件的背景 | boolean | false | 5.11.0 |

### 静态方法

Expand Down
29 changes: 27 additions & 2 deletions components/spin/style/index.tsx
@@ -1,5 +1,6 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { Keyframes } from '@ant-design/cssinjs';

import { resetComponent } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
Expand Down Expand Up @@ -39,6 +40,8 @@ const antRotate = new Keyframes('antRotate', {
to: { transform: 'rotate(405deg)' },
});

const dotPadding = (token: SpinToken) => (token.dotSize - token.fontSize) / 2 + 2;

const genSpinStyle: GenerateStyle<SpinToken> = (token: SpinToken): CSSObject => ({
[`${token.componentCls}`]: {
...resetComponent(token),
Expand All @@ -57,6 +60,30 @@ const genSpinStyle: GenerateStyle<SpinToken> = (token: SpinToken): CSSObject =>
opacity: 1,
},

[`${token.componentCls}-text`]: {
fontSize: token.fontSize,
paddingTop: dotPadding(token),
},

'&-fullscreen': {
position: 'fixed',
width: '100vw',
height: '100vh',
backgroundColor: token.colorBgMask,
zIndex: token.zIndexPopupBase,
inset: 0,
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
justifyContent: 'center',
[`${token.componentCls}-dot ${token.componentCls}-dot-item`]: {
backgroundColor: token.colorWhite,
},
[`${token.componentCls}-text`]: {
color: token.colorTextLightSolid,
},
},

'&-nested-loading': {
position: 'relative',
[`> div > ${token.componentCls}`]: {
Expand All @@ -80,9 +107,7 @@ const genSpinStyle: GenerateStyle<SpinToken> = (token: SpinToken): CSSObject =>
position: 'absolute',
top: '50%',
width: '100%',
paddingTop: (token.dotSize - token.fontSize) / 2 + 2,
textShadow: `0 1px 2px ${token.colorBgContainer}`, // FIXME: shadow
fontSize: token.fontSize,
},

[`&${token.componentCls}-show-text ${token.componentCls}-dot`]: {
Expand Down