Skip to content

Commit

Permalink
feat: Button support autoInsertSpace prop (#48348)
Browse files Browse the repository at this point in the history
* feat: Button support autoInsertSpaceInButton prop

* demo: update demo

* fix: fix

* test: add test case

* docs: update docs

* chore: deprecated autoInsertSpaceInButton prop

* Update components/button/button.tsx

Co-authored-by: MadCcc <madccc@foxmail.com>
Signed-off-by: lijianan <574980606@qq.com>

* fix: fix

* fix: fix

* Update components/button/button.tsx

Co-authored-by: MadCcc <madccc@foxmail.com>
Signed-off-by: lijianan <574980606@qq.com>

* fix: fix

* Update components/button/button.tsx

Signed-off-by: lijianan <574980606@qq.com>

* fix: fix

* fix: fix

---------

Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: MadCcc <madccc@foxmail.com>
  • Loading branch information
li-jia-nan and MadCcc committed Apr 11, 2024
1 parent 4cba8b8 commit 6a7945d
Show file tree
Hide file tree
Showing 14 changed files with 140 additions and 39 deletions.
25 changes: 25 additions & 0 deletions components/button/__tests__/__snapshots__/demo-extend.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2776,6 +2776,31 @@ exports[`renders components/button/demo/multiple.tsx extend context correctly 1`

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

exports[`renders components/button/demo/noSpace.tsx extend context correctly 1`] = `
<div
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-middle"
>
<button
class="ant-btn ant-btn-primary"
type="button"
>
<span>
确定
</span>
</button>
<button
class="ant-btn ant-btn-primary"
type="button"
>
<span>
确 定
</span>
</button>
</div>
`;

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

exports[`renders components/button/demo/size.tsx extend context correctly 1`] = `
Array [
<div
Expand Down
23 changes: 23 additions & 0 deletions components/button/__tests__/__snapshots__/demo.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2243,6 +2243,29 @@ exports[`renders components/button/demo/multiple.tsx correctly 1`] = `
</div>
`;

exports[`renders components/button/demo/noSpace.tsx correctly 1`] = `
<div
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-middle"
>
<button
class="ant-btn ant-btn-primary"
type="button"
>
<span>
确定
</span>
</button>
<button
class="ant-btn ant-btn-primary"
type="button"
>
<span>
确 定
</span>
</button>
</div>
`;

exports[`renders components/button/demo/size.tsx correctly 1`] = `
Array [
<div
Expand Down
6 changes: 6 additions & 0 deletions components/button/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -442,4 +442,10 @@ describe('Button', () => {
const { container } = render(<Button type={'' as any} />);
expect(container.querySelector('.ant-btn-default')).toBeTruthy();
});

it('should support autoInsertSpace', () => {
const text = '确定';
const { container } = render(<Button autoInsertSpace={false}>{text}</Button>);
expect(container.querySelector<HTMLButtonElement>('button')?.textContent).toBe(text);
});
});
15 changes: 9 additions & 6 deletions components/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type MergedHTMLAttributes = Omit<
export interface ButtonProps extends BaseButtonProps, MergedHTMLAttributes {
href?: string;
htmlType?: ButtonHTMLType;
autoInsertSpace?: boolean;
}

type LoadingConfigType = {
Expand Down Expand Up @@ -98,14 +99,18 @@ const InternalCompoundedButton = React.forwardRef<
htmlType = 'button',
classNames: customClassNames,
style: customStyle = {},
autoInsertSpace,
...rest
} = props;

// https://github.com/ant-design/ant-design/issues/47605
// Compatible with original `type` behavior
const mergedType = type || 'default';

const { getPrefixCls, autoInsertSpaceInButton, direction, button } = useContext(ConfigContext);
const { getPrefixCls, direction, button } = useContext(ConfigContext);

const mergedInsertSpace = autoInsertSpace ?? button?.autoInsertSpace ?? true;

const prefixCls = getPrefixCls('btn', customizePrefixCls);

const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
Expand Down Expand Up @@ -151,7 +156,7 @@ const InternalCompoundedButton = React.forwardRef<

useEffect(() => {
// FIXME: for HOC usage like <FormatMessage />
if (!buttonRef || !(buttonRef as any).current || autoInsertSpaceInButton === false) {
if (!buttonRef || !(buttonRef as any).current || !mergedInsertSpace) {
return;
}
const buttonText = (buttonRef as any).current.textContent;
Expand Down Expand Up @@ -190,7 +195,6 @@ const InternalCompoundedButton = React.forwardRef<
);
}

const autoInsertSpace = autoInsertSpaceInButton !== false;
const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction);

const sizeClassNameMap = { large: 'lg', small: 'sm', middle: undefined };
Expand All @@ -214,7 +218,7 @@ const InternalCompoundedButton = React.forwardRef<
[`${prefixCls}-icon-only`]: !children && children !== 0 && !!iconType,
[`${prefixCls}-background-ghost`]: ghost && !isUnBorderedButtonType(mergedType),
[`${prefixCls}-loading`]: innerLoading,
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar && autoInsertSpace && !innerLoading,
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar && mergedInsertSpace && !innerLoading,
[`${prefixCls}-block`]: block,
[`${prefixCls}-dangerous`]: !!danger,
[`${prefixCls}-rtl`]: direction === 'rtl',
Expand Down Expand Up @@ -252,12 +256,11 @@ const InternalCompoundedButton = React.forwardRef<
);

const kids =
children || children === 0 ? spaceChildren(children, needInserted && autoInsertSpace) : null;
children || children === 0 ? spaceChildren(children, needInserted && mergedInsertSpace) : null;

const genButtonContent = (iconComponent: React.ReactNode, kidsComponent: React.ReactNode) => {
const isRTL = direction === 'rtl';
const iconFirst = (iconPosition === 'start' && !isRTL) || (iconPosition === 'end' && isRTL);

return (
<>
{iconFirst ? iconComponent : kidsComponent}
Expand Down
7 changes: 7 additions & 0 deletions components/button/demo/noSpace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## zh-CN

我们默认在两个汉字之间添加空格,可以通过设置 `autoInsertSpace``false` 关闭。

## en-US

We add a space between two Chinese characters by default, which can be removed by setting `autoInsertSpace` to `false`.
15 changes: 15 additions & 0 deletions components/button/demo/noSpace.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { Button, Flex } from 'antd';

const App: React.FC = () => (
<Flex gap="middle" wrap="wrap">
<Button type="primary" autoInsertSpace={false}>
确定
</Button>
<Button type="primary" autoInsertSpace>
确定
</Button>
</Flex>
);

export default App;
15 changes: 2 additions & 13 deletions components/button/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Different button styles can be generated by setting Button properties. The recom

| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| autoInsertSpace | We add a space between two Chinese characters by default, which can be removed by setting `autoInsertSpace` to `false`. | boolean | `true` | 5.17.0 |
| block | Option to fit button width to its parent width | boolean | false | |
| classNames | Semantic DOM class | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.4.0 |
| danger | Set the danger status of button | boolean | false | |
Expand All @@ -73,7 +74,7 @@ Different button styles can be generated by setting Button properties. The recom
| styles | Semantic DOM style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.4.0 |
| target | Same as target attribute of a, works when href is specified | string | - | |
| type | Set button type | `primary` \| `dashed` \| `link` \| `text` \| `default` | `default` | |
| onClick | Set the handler to handle `click` event | (event: MouseEvent) => void | - | |
| onClick | Set the handler to handle `click` event | (event: React.MouseEvent<HTMLElement, MouseEvent>) => void | - | |

It accepts all props which native buttons support.

Expand All @@ -97,18 +98,6 @@ If you don't need this feature, you can set `disabled` of `wave` in [ConfigProvi
</ConfigProvider>
```

### How to remove space between 2 chinese characters?

Following the Ant Design specification, we will add one space between if Button (exclude Text button and Link button) contains two Chinese characters only. If you don't need that, you can use [ConfigProvider](/components/config-provider/#api) to set `autoInsertSpaceInButton` as `false`.

```jsx
<ConfigProvider autoInsertSpaceInButton={false}>
<Button>按钮</Button>
</ConfigProvider>
```

<img src="https://gw.alipayobjects.com/zos/antfincdn/MY%26THAPZrW/38f06cb9-293a-4b42-b183-9f443e79ffea.png" width="100px" height="64px" style="box-shadow: none; margin: 0;" alt="Button with two Chinese characters" />

<style>
.site-button-ghost-wrapper {
padding: 16px;
Expand Down
16 changes: 3 additions & 13 deletions components/button/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ group:
<code src="./demo/chinese-chars-loading.tsx" debug>加载中状态 bug 还原</code>
<code src="./demo/component-token.tsx" debug>组件 Token</code>
<code src="./demo/linear-gradient.tsx">渐变按钮</code>
<code src="./demo/noSpace.tsx" version="5.17.0">移除两个汉字之间的空格</code>

## API

Expand All @@ -63,6 +64,7 @@ group:

| 属性 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| autoInsertSpace | 我们默认提供两个汉字之间的空格,可以设置 `autoInsertSpace``false` 关闭 | boolean | `true` | 5.17.0 |
| block | 将按钮宽度调整为其父宽度的选项 | boolean | false | |
| classNames | 语义化结构 class | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.4.0 |
| danger | 设置危险按钮 | boolean | false | |
Expand All @@ -78,7 +80,7 @@ group:
| styles | 语义化结构 style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.4.0 |
| target | 相当于 a 链接的 target 属性,href 存在时生效 | string | - | |
| type | 设置按钮类型 | `primary` \| `dashed` \| `link` \| `text` \| `default` | `default` | |
| onClick | 点击按钮时的回调 | (event: MouseEvent) => void | - | |
| onClick | 点击按钮时的回调 | (event: React.MouseEvent<HTMLElement, MouseEvent>) => void | - | |

支持原生 button 的其他所有属性。

Expand All @@ -102,18 +104,6 @@ group:
</ConfigProvider>
```

### 如何移除两个汉字之间的空格?

根据 Ant Design 设计规范要求,我们会在按钮内(文本按钮和链接按钮除外)只有两个汉字时自动添加空格,如果你不需要这个特性,可以设置 [ConfigProvider](/components/config-provider-cn#api)`autoInsertSpaceInButton``false`

```jsx
<ConfigProvider autoInsertSpaceInButton={false}>
<Button>按钮</Button>
</ConfigProvider>
```

<img src="https://gw.alipayobjects.com/zos/antfincdn/MY%26THAPZrW/38f06cb9-293a-4b42-b183-9f443e79ffea.png" style="box-shadow: none; margin: 0" width="100px" height="64px" alt="移除两个汉字之间的空格" />

<style>
.site-button-ghost-wrapper {
padding: 16px;
Expand Down
12 changes: 11 additions & 1 deletion components/config-provider/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,17 @@ describe('ConfigProvider', () => {
<Button>{text}</Button>
</ConfigProvider>,
);
expect(container.querySelector('span')?.innerHTML).toBe(text);
expect(container.querySelector<HTMLSpanElement>('span')?.innerHTML).toBe(text);
});

it('button.autoInsertSpace', () => {
const text = '确定';
const { container } = render(
<ConfigProvider button={{ autoInsertSpace: false }}>
<Button>{text}</Button>
</ConfigProvider>,
);
expect(container.querySelector<HTMLSpanElement>('span')?.innerHTML).toBe(text);
});

it('renderEmpty', () => {
Expand Down
15 changes: 15 additions & 0 deletions components/config-provider/__tests__/useConfig.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { Button } from 'antd';

import ConfigProvider from '..';
import { resetWarned } from '../../_util/warning';
Expand Down Expand Up @@ -61,4 +62,18 @@ describe('ConfigProvider.useConfig', () => {
);
errSpy.mockRestore();
});

it('deprecated autoInsertSpaceInButton', () => {
resetWarned();
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
render(
<ConfigProvider autoInsertSpaceInButton={false}>
<Button>测试</Button>
</ConfigProvider>,
);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: ConfigProvider] `autoInsertSpaceInButton` is deprecated. Please use `{ button: { autoInsertSpace: boolean }}` instead.',
);
errSpy.mockRestore();
});
});
4 changes: 3 additions & 1 deletion components/config-provider/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ export type InputConfig = ComponentStyleConfig &
export type TextAreaConfig = ComponentStyleConfig &
Pick<TextAreaProps, 'autoComplete' | 'classNames' | 'styles' | 'allowClear'>;

export type ButtonConfig = ComponentStyleConfig & Pick<ButtonProps, 'classNames' | 'styles'>;
export type ButtonConfig = ComponentStyleConfig &
Pick<ButtonProps, 'classNames' | 'styles' | 'autoInsertSpace'>;

export type NotificationConfig = ComponentStyleConfig & Pick<ArgsProps, 'closeIcon'>;

Expand Down Expand Up @@ -194,6 +195,7 @@ export interface ConfigConsumerProps {
* @descEN Set the [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) config.
*/
csp?: CSPConfig;
/** @deprecated Please use `{ button: { autoInsertSpace: boolean }}` instead */
autoInsertSpaceInButton?: boolean;
input?: InputConfig;
textArea?: TextAreaConfig;
Expand Down
3 changes: 1 addition & 2 deletions components/config-provider/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ Some components use dynamic style to support wave effect. You can config `csp` p

| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| autoInsertSpaceInButton | Set false to remove space between 2 chinese characters on Button | boolean | true | |
| componentDisabled | Config antd component `disabled` | boolean | - | 4.21.0 |
| componentSize | Config antd component size | `small` \| `middle` \| `large` | - | |
| csp | Set [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) config | { nonce: string } | - | |
Expand Down Expand Up @@ -105,7 +104,7 @@ const {
| avatar | Set Avatar common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| badge | Set Badge common props | { className?: string, style?: React.CSSProperties, classNames?: { count?: string, indicator?: string }, styles?: { count?: React.CSSProperties, indicator?: React.CSSProperties } } | - | 5.7.0 |
| breadcrumb | Set Breadcrumb common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| button | Set Button common props | { className?: string, style?: React.CSSProperties, classNames?: { icon: string }, styles?: { icon: React.CSSProperties } } | - | 5.6.0 |
| button | Set Button common props | { className?: string, style?: React.CSSProperties, classNames?: { icon: string }, styles?: { icon: React.CSSProperties }, autoInsertSpace?: boolean } | - | 5.6.0, autoInsertSpace: 5.17.0 |
| card | Set Card common props | { className?: string, style?: React.CSSProperties, classNames?: [CardProps\["classNames"\]](/components/card#api), styles?: [CardProps\["styles"\]](/components/card#api) } | - | 5.7.0, `classNames` and `styles`: 5.14.0 |
| calendar | Set Calendar common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| carousel | Set Carousel common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
Expand Down
20 changes: 19 additions & 1 deletion components/config-provider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import IconContext from '@ant-design/icons/lib/components/Context';
import useMemo from 'rc-util/lib/hooks/useMemo';
import { merge } from 'rc-util/lib/utils/set';

import warning, { WarningContext } from '../_util/warning';
import warning, { devUseWarning, WarningContext } from '../_util/warning';
import type { WarningContextProps } from '../_util/warning';
import ValidateMessagesContext from '../form/validateMessagesContext';
import type { Locale } from '../locale';
Expand Down Expand Up @@ -122,6 +122,7 @@ export interface ConfigProviderProps {
children?: React.ReactNode;
renderEmpty?: RenderEmptyHandler;
csp?: CSPConfig;
/** @deprecated Please use `{ button: { autoInsertSpace: boolean }}` instead */
autoInsertSpaceInButton?: boolean;
form?: FormConfig;
input?: InputConfig;
Expand Down Expand Up @@ -463,6 +464,15 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
floatButtonGroup,
};

if (process.env.NODE_ENV !== 'production') {
const warningFn = devUseWarning('ConfigProvider');
warningFn(
!('autoInsertSpaceInButton' in props),
'deprecated',
'`autoInsertSpaceInButton` is deprecated. Please use `{ button: { autoInsertSpace: boolean }}` instead.',
);
}

const config: ConfigConsumerProps = {
...parentContext,
};
Expand All @@ -482,6 +492,14 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
}
});

if (typeof autoInsertSpaceInButton !== 'undefined') {
// merge deprecated api
config.button = {
autoInsertSpace: autoInsertSpaceInButton,
...config.button,
};
}

// https://github.com/ant-design/ant-design/issues/27617
const memoedConfig = useMemo(
() => config,
Expand Down
3 changes: 1 addition & 2 deletions components/config-provider/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ export default Demo;

| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| autoInsertSpaceInButton | 设置为 `false` 时,移除按钮中 2 个汉字之间的空格 | boolean | true | |
| componentDisabled | 设置 antd 组件禁用状态 | boolean | - | 4.21.0 |
| componentSize | 设置 antd 组件大小 | `small` \| `middle` \| `large` | - | |
| csp | 设置 [Content Security Policy](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP) 配置 | { nonce: string } | - | |
Expand Down Expand Up @@ -107,7 +106,7 @@ const {
| avatar | 设置 Avatar 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| badge | 设置 Badge 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: { count?: string, indicator?: string }, styles?: { count?: React.CSSProperties, indicator?: React.CSSProperties } } | - | 5.7.0 |
| breadcrumb | 设置 Breadcrumb 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| button | 设置 Button 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: { icon: string }, styles?: { icon: React.CSSProperties } } | - | 5.6.0 |
| button | 设置 Button 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: { icon: string }, styles?: { icon: React.CSSProperties }, autoInsertSpace?: boolean } | - | 5.6.0, autoInsertSpace: 5.17.0 |
| calendar | 设置 Calendar 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| card | 设置 Card 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [CardProps\["classNames"\]](/components/card-cn#api), styles?: [CardProps\["styles"\]](/components/card-cn#api) } | - | 5.7.0, `classNames``styles`: 5.14.0 |
| carousel | 设置 Carousel 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
Expand Down

0 comments on commit 6a7945d

Please sign in to comment.