mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 06:03:38 +08:00
feat: config-provider support divider className and style properties (#43042)
* feat: config-provider support divider className and style properties * fix: simple ts definition * fix: merge style & className * fix: fix space className * feat: optimize type definition * feat: optimize type definition * feat: add version * test: update test * test: update test * fix: fix type * fix: fix api sort * fix: fix docs * docs: add another api table * Apply suggestions from code review --------- Co-authored-by: MadCcc <1075746765@qq.com>
This commit is contained in:
parent
1fb8fc57d3
commit
785115c580
@ -7,7 +7,6 @@ import { fireEvent, render } from '../../../tests/utils';
|
||||
import Button from '../../button';
|
||||
import Input from '../../input';
|
||||
import Select from '../../select';
|
||||
import Space from '../../space';
|
||||
import Table from '../../table';
|
||||
|
||||
describe('ConfigProvider', () => {
|
||||
@ -124,78 +123,4 @@ describe('ConfigProvider', () => {
|
||||
expect(rendered).toBeTruthy();
|
||||
expect(cacheRenderEmpty).toBeFalsy();
|
||||
});
|
||||
|
||||
it('Should Space classNames works', () => {
|
||||
const { container } = render(
|
||||
<ConfigProvider
|
||||
space={{
|
||||
classNames: {
|
||||
item: 'test-classNames',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
<span>Text1</span>
|
||||
<span>Text2</span>
|
||||
</Space>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
expect(container.querySelector('.ant-space-item.test-classNames')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Should Space className works', () => {
|
||||
const { container } = render(
|
||||
<ConfigProvider
|
||||
space={{
|
||||
className: 'test-classNames',
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
<span>Text1</span>
|
||||
<span>Text2</span>
|
||||
</Space>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
expect(container.querySelector('.ant-space.test-classNames')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Should Space styles works', () => {
|
||||
const { container } = render(
|
||||
<ConfigProvider
|
||||
space={{
|
||||
styles: {
|
||||
item: {
|
||||
color: 'red',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
<span>Text1</span>
|
||||
<span>Text2</span>
|
||||
</Space>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
expect(container.querySelector('.ant-space-item')?.getAttribute('style')).toEqual(
|
||||
'margin-right: 8px; color: red;',
|
||||
);
|
||||
});
|
||||
|
||||
it('Should Space style works', () => {
|
||||
const { container } = render(
|
||||
<ConfigProvider
|
||||
space={{
|
||||
style: {
|
||||
color: 'red',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
<span>Text1</span>
|
||||
<span>Text2</span>
|
||||
</Space>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
expect(container.querySelector('.ant-space')?.getAttribute('style')).toEqual('color: red;');
|
||||
});
|
||||
});
|
||||
|
110
components/config-provider/__tests__/style.test.tsx
Normal file
110
components/config-provider/__tests__/style.test.tsx
Normal file
@ -0,0 +1,110 @@
|
||||
import React from 'react';
|
||||
import ConfigProvider from '..';
|
||||
import { render } from '../../../tests/utils';
|
||||
import Divider from '../../divider';
|
||||
import Space from '../../space';
|
||||
|
||||
describe('ConfigProvider support style and className props', () => {
|
||||
it('Should Space classNames works', () => {
|
||||
const { container } = render(
|
||||
<ConfigProvider
|
||||
space={{
|
||||
classNames: {
|
||||
item: 'test-classNames',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
<span>Text1</span>
|
||||
<span>Text2</span>
|
||||
</Space>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
expect(container.querySelector('.ant-space-item.test-classNames')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Should Space className works', () => {
|
||||
const { container } = render(
|
||||
<ConfigProvider
|
||||
space={{
|
||||
className: 'test-classNames',
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
<span>Text1</span>
|
||||
<span>Text2</span>
|
||||
</Space>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
expect(container.querySelector('.ant-space.test-classNames')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Should Space styles works', () => {
|
||||
const { container } = render(
|
||||
<ConfigProvider
|
||||
space={{
|
||||
styles: {
|
||||
item: {
|
||||
color: 'red',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
<span>Text1</span>
|
||||
<span>Text2</span>
|
||||
</Space>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
expect(container.querySelector('.ant-space-item')?.getAttribute('style')).toEqual(
|
||||
'margin-right: 8px; color: red;',
|
||||
);
|
||||
});
|
||||
|
||||
it('Should Space style works', () => {
|
||||
const { container } = render(
|
||||
<ConfigProvider
|
||||
space={{
|
||||
style: {
|
||||
color: 'red',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
<span>Text1</span>
|
||||
<span>Text2</span>
|
||||
</Space>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
expect(container.querySelector('.ant-space')?.getAttribute('style')).toEqual('color: red;');
|
||||
});
|
||||
|
||||
it('Should Divider className works', () => {
|
||||
const { container } = render(
|
||||
<ConfigProvider
|
||||
divider={{
|
||||
className: 'config-provider-className',
|
||||
}}
|
||||
>
|
||||
<Divider />
|
||||
</ConfigProvider>,
|
||||
);
|
||||
expect(container.querySelector('.ant-divider')).toHaveClass('config-provider-className');
|
||||
});
|
||||
|
||||
it('Should Divider style works', () => {
|
||||
const { container } = render(
|
||||
<ConfigProvider
|
||||
divider={{
|
||||
style: {
|
||||
color: 'red',
|
||||
height: 80,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Divider />
|
||||
</ConfigProvider>,
|
||||
);
|
||||
expect(container.querySelector('.ant-divider'))?.toHaveStyle({ color: 'red', height: '80px' });
|
||||
});
|
||||
});
|
@ -36,15 +36,16 @@ export interface ThemeConfig {
|
||||
inherit?: boolean;
|
||||
}
|
||||
|
||||
interface componentStyleConfig {
|
||||
export interface componentStyleConfig {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export interface ButtonConfig extends componentStyleConfig {
|
||||
classNames?: ButtonProps['classNames'];
|
||||
styles?: ButtonProps['styles'];
|
||||
}
|
||||
|
||||
export interface ButtonConfig extends componentStyleConfig {}
|
||||
|
||||
export type PopupOverflow = 'viewport' | 'scroll';
|
||||
|
||||
export interface ConfigConsumerProps {
|
||||
@ -87,6 +88,7 @@ export interface ConfigConsumerProps {
|
||||
showSearch?: boolean;
|
||||
};
|
||||
button?: ButtonConfig;
|
||||
divider?: componentStyleConfig;
|
||||
}
|
||||
|
||||
const defaultGetPrefixCls = (suffixCls?: string, customizePrefixCls?: string) => {
|
||||
|
@ -55,19 +55,14 @@ Some components use dynamic style to support wave effect. You can config `csp` p
|
||||
| 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 } | - | |
|
||||
| direction | Set direction of layout. See [demo](#components-config-provider-demo-direction) | `ltr` \| `rtl` | `ltr` | |
|
||||
| popupMatchSelectWidth | Determine whether the dropdown menu and the select input are the same width. Default set `min-width` same as input. Will ignore when value less than select width. `false` will disable virtual scroll | boolean \| number | - | 5.5.0 |
|
||||
| popupOverflow | Select like component popup logic. Can set to show in viewport or follow window scroll | 'viewport' \| 'scroll' <InlinePopover previewURL="https://user-images.githubusercontent.com/5378891/230344474-5b9f7e09-0a5d-49e8-bae8-7d2abed6c837.png"></InlinePopover> | 'viewport' | 5.5.0 |
|
||||
| form | Set Form common props | { validateMessages?: [ValidateMessages](/components/form/#validatemessages), requiredMark?: boolean \| `optional`, scrollToFirstError?: boolean \| [Options](https://github.com/stipsan/scroll-into-view-if-needed/tree/ece40bd9143f48caf4b99503425ecb16b0ad8249#options) } | - | requiredMark: 4.8.0; colon: 4.18.0; scrollToFirstError: 5.2.0 |
|
||||
| getPopupContainer | To set the container of the popup element. The default is to create a `div` element in `body` | function(triggerNode) | () => document.body | |
|
||||
| getTargetContainer | Config Affix, Anchor scroll target container | () => HTMLElement | () => window | 4.2.0 |
|
||||
| iconPrefixCls | Set icon prefix className | string | `anticon` | 4.11.0 |
|
||||
| input | Set Input common props | { autoComplete?: string } | - | 4.2.0 |
|
||||
| select | Set Select common props | { showSearch?: boolean } | - | |
|
||||
| button | Set Select common props | { className?: string, style?: React.CSSProperties, classNames?: { icon: string }, styles?: { icon: React.CSSProperties } } | - | 5.6.0 |
|
||||
| locale | Language package setting, you can find the packages in [antd/locale](http://unpkg.com/antd/locale/) | object | - | |
|
||||
| popupMatchSelectWidth | Determine whether the dropdown menu and the select input are the same width. Default set `min-width` same as input. Will ignore when value less than select width. `false` will disable virtual scroll | boolean \| number | - | 5.5.0 |
|
||||
| popupOverflow | Select like component popup logic. Can set to show in viewport or follow window scroll | 'viewport' \| 'scroll' <InlinePopover previewURL="https://user-images.githubusercontent.com/5378891/230344474-5b9f7e09-0a5d-49e8-bae8-7d2abed6c837.png"></InlinePopover> | 'viewport' | 5.5.0 |
|
||||
| prefixCls | Set prefix className | string | `ant` | |
|
||||
| renderEmpty | Set empty content of components. Ref [Empty](/components/empty/) | function(componentName: string): ReactNode | - | |
|
||||
| space | Set Space common props, ref [Space](/components/space) | { size: `small` \| `middle` \| `large` \| `number`, className?: string, style?: React.CSSProperties, classNames?: { item: string }, styles?: { item: React.CSSProperties } } | - | 5.6.0 |
|
||||
| theme | Set theme, ref [Customize Theme](/docs/react/customize-theme) | - | - | 5.0.0 |
|
||||
| virtual | Disable virtual scroll when set to `false` | boolean | - | 4.3.0 |
|
||||
|
||||
@ -102,6 +97,17 @@ const {
|
||||
| componentDisabled | antd component disabled state | boolean | - | 5.3.0 |
|
||||
| componentSize | antd component size state | `small` \| `middle` \| `large` | - | 5.3.0 |
|
||||
|
||||
### Component Config
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| button | Set Button common props | { className?: string, style?: React.CSSProperties, classNames?: { icon: string }, styles?: { icon: React.CSSProperties } } | - | 5.6.0 |
|
||||
| divider | Set Divider common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
|
||||
| form | Set Form common props | { validateMessages?: [ValidateMessages](/components/form/#validatemessages), requiredMark?: boolean \| `optional`, scrollToFirstError?: boolean \| [Options](https://github.com/stipsan/scroll-into-view-if-needed/tree/ece40bd9143f48caf4b99503425ecb16b0ad8249#options) } | - | requiredMark: 4.8.0; colon: 4.18.0; scrollToFirstError: 5.2.0 |
|
||||
| input | Set Input common props | { autoComplete?: string } | - | 4.2.0 |
|
||||
| select | Set Select common props | { showSearch?: boolean } | - | |
|
||||
| space | Set Space common props, ref [Space](/components/space) | { size: `small` \| `middle` \| `large` \| `number`, className?: string, style?: React.CSSProperties, classNames?: { item: string }, styles?: { item: React.CSSProperties } } | - | 5.6.0 |
|
||||
|
||||
## FAQ
|
||||
|
||||
#### How to contribute a new language?
|
||||
|
@ -19,6 +19,7 @@ import { DesignTokenContext } from '../theme/internal';
|
||||
import defaultSeedToken from '../theme/themes/seed';
|
||||
import type {
|
||||
ButtonConfig,
|
||||
componentStyleConfig,
|
||||
ConfigConsumerProps,
|
||||
CSPConfig,
|
||||
DirectionType,
|
||||
@ -38,8 +39,8 @@ import SizeContext, { SizeContextProvider } from './SizeContext';
|
||||
import useStyle from './style';
|
||||
|
||||
/**
|
||||
* Since too many feedback using static method like `Modal.confirm` not getting theme,
|
||||
* we record the theme register info here to help developer get warning info.
|
||||
* Since too many feedback using static method like `Modal.confirm` not getting theme, we record the
|
||||
* theme register info here to help developer get warning info.
|
||||
*/
|
||||
let existThemeConfig = false;
|
||||
|
||||
@ -136,6 +137,7 @@ export interface ConfigProviderProps {
|
||||
popupOverflow?: PopupOverflow;
|
||||
theme?: ThemeConfig;
|
||||
button?: ButtonConfig;
|
||||
divider?: componentStyleConfig;
|
||||
}
|
||||
|
||||
interface ProviderChildrenProps extends ConfigProviderProps {
|
||||
@ -223,6 +225,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
|
||||
iconPrefixCls: customIconPrefixCls,
|
||||
theme,
|
||||
componentDisabled,
|
||||
divider,
|
||||
} = props;
|
||||
|
||||
// =================================== Warning ===================================
|
||||
@ -272,6 +275,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
|
||||
getPrefixCls,
|
||||
iconPrefixCls,
|
||||
theme: mergedTheme,
|
||||
divider,
|
||||
};
|
||||
|
||||
const config = {
|
||||
|
@ -56,19 +56,14 @@ export default Demo;
|
||||
| componentSize | 设置 antd 组件大小 | `small` \| `middle` \| `large` | - | |
|
||||
| csp | 设置 [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) 配置 | { nonce: string } | - | |
|
||||
| direction | 设置文本展示方向。 [示例](#components-config-provider-demo-direction) | `ltr` \| `rtl` | `ltr` | |
|
||||
| popupMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`,当值小于选择框宽度时会被忽略。`false` 时会关闭虚拟滚动 | boolean \| number | - | 5.5.0 |
|
||||
| popupOverflow | Select 类组件弹层展示逻辑,默认为可视区域滚动,可配置成滚动区域滚动 | 'viewport' \| 'scroll' <InlinePopover previewURL="https://user-images.githubusercontent.com/5378891/230344474-5b9f7e09-0a5d-49e8-bae8-7d2abed6c837.png"></InlinePopover> | 'viewport' | 5.5.0 |
|
||||
| form | 设置 Form 组件的通用属性 | { validateMessages?: [ValidateMessages](/components/form-cn#validatemessages), requiredMark?: boolean \| `optional`, colon?: boolean, scrollToFirstError?: boolean \| [Options](https://github.com/stipsan/scroll-into-view-if-needed/tree/ece40bd9143f48caf4b99503425ecb16b0ad8249#options)} | - | requiredMark: 4.8.0; colon: 4.18.0; scrollToFirstError: 5.2.0 |
|
||||
| getPopupContainer | 弹出框(Select, Tooltip, Menu 等等)渲染父节点,默认渲染到 body 上。 | function(triggerNode) | () => document.body | |
|
||||
| getTargetContainer | 配置 Affix、Anchor 滚动监听容器。 | () => HTMLElement | () => window | 4.2.0 |
|
||||
| iconPrefixCls | 设置图标统一样式前缀 | string | `anticon` | 4.11.0 |
|
||||
| input | 设置 Input 组件的通用属性 | { autoComplete?: string } | - | 4.2.0 |
|
||||
| select | 设置 Select 组件的通用属性 | { showSearch?: boolean } | - | |
|
||||
| button | 设置 Button 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: { icon: string }, styles?: { icon: React.CSSProperties } } | - | 5.6.0 |
|
||||
| locale | 语言包配置,语言包可到 [antd/locale](http://unpkg.com/antd/locale/) 目录下寻找 | object | - | |
|
||||
| popupMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`,当值小于选择框宽度时会被忽略。`false` 时会关闭虚拟滚动 | boolean \| number | - | 5.5.0 |
|
||||
| popupOverflow | Select 类组件弹层展示逻辑,默认为可视区域滚动,可配置成滚动区域滚动 | 'viewport' \| 'scroll' <InlinePopover previewURL="https://user-images.githubusercontent.com/5378891/230344474-5b9f7e09-0a5d-49e8-bae8-7d2abed6c837.png"></InlinePopover> | 'viewport' | 5.5.0 |
|
||||
| prefixCls | 设置统一样式前缀 | string | `ant` | |
|
||||
| renderEmpty | 自定义组件空状态。参考 [空状态](/components/empty-cn) | function(componentName: string): ReactNode | - | |
|
||||
| space | 设置 Space 的通用属性,参考 [Space](/components/space-cn) | { size: `small` \| `middle` \| `large` \| `number`, className?: string, style?: React.CSSProperties, classNames?: { item: string }, styles?: { item: React.CSSProperties } } | - | 5.6.0 |
|
||||
| theme | 设置主题,参考 [定制主题](/docs/react/customize-theme-cn) | - | - | 5.0.0 |
|
||||
| virtual | 设置 `false` 时关闭虚拟滚动 | boolean | - | 4.3.0 |
|
||||
|
||||
@ -104,6 +99,17 @@ const {
|
||||
| componentDisabled | antd 组件禁用状态 | boolean | - | 5.3.0 |
|
||||
| componentSize | antd 组件大小状态 | `small` \| `middle` \| `large` | - | 5.3.0 |
|
||||
|
||||
### 组件配置
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| button | 设置 Button 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: { icon: string }, styles?: { icon: React.CSSProperties } } | - | 5.6.0 |
|
||||
| divider | 设置 Divider 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
|
||||
| form | 设置 Form 组件的通用属性 | { validateMessages?: [ValidateMessages](/components/form-cn#validatemessages), requiredMark?: boolean \| `optional`, colon?: boolean, scrollToFirstError?: boolean \| [Options](https://github.com/stipsan/scroll-into-view-if-needed/tree/ece40bd9143f48caf4b99503425ecb16b0ad8249#options)} | - | requiredMark: 4.8.0; colon: 4.18.0; scrollToFirstError: 5.2.0 |
|
||||
| input | 设置 Input 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
|
||||
| select | 设置 Select 组件的通用属性 | { showSearch?: boolean } | - | |
|
||||
| space | 设置 Space 的通用属性,参考 [Space](/components/space-cn) | { size: `small` \| `middle` \| `large` \| `number`, className?: string, style?: React.CSSProperties, classNames?: { item: string }, styles?: { item: React.CSSProperties } } | - | 5.6.0 |
|
||||
|
||||
## FAQ
|
||||
|
||||
#### 如何增加一个新的语言包?
|
||||
|
@ -19,7 +19,7 @@ export interface DividerProps {
|
||||
}
|
||||
|
||||
const Divider: React.FC<DividerProps> = (props) => {
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
const { getPrefixCls, direction, divider } = React.useContext(ConfigContext);
|
||||
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
@ -31,6 +31,7 @@ const Divider: React.FC<DividerProps> = (props) => {
|
||||
children,
|
||||
dashed,
|
||||
plain,
|
||||
style,
|
||||
...restProps
|
||||
} = props;
|
||||
const prefixCls = getPrefixCls('divider', customizePrefixCls);
|
||||
@ -42,6 +43,7 @@ const Divider: React.FC<DividerProps> = (props) => {
|
||||
const hasCustomMarginRight = orientation === 'right' && orientationMargin != null;
|
||||
const classString = classNames(
|
||||
prefixCls,
|
||||
divider?.className,
|
||||
hashId,
|
||||
`${prefixCls}-${type}`,
|
||||
{
|
||||
@ -82,7 +84,12 @@ const Divider: React.FC<DividerProps> = (props) => {
|
||||
}
|
||||
|
||||
return wrapSSR(
|
||||
<div className={classString} {...restProps} role="separator">
|
||||
<div
|
||||
className={classString}
|
||||
style={{ ...divider?.style, ...style }}
|
||||
{...restProps}
|
||||
role="separator"
|
||||
>
|
||||
{children && type !== 'vertical' && (
|
||||
<span className={`${prefixCls}-inner-text`} style={innerStyle}>
|
||||
{children}
|
||||
|
@ -76,13 +76,14 @@ const Space = React.forwardRef<HTMLDivElement, SpaceProps>((props, ref) => {
|
||||
|
||||
const cn = classNames(
|
||||
prefixCls,
|
||||
space?.className,
|
||||
hashId,
|
||||
`${prefixCls}-${direction}`,
|
||||
{
|
||||
[`${prefixCls}-rtl`]: directionConfig === 'rtl',
|
||||
[`${prefixCls}-align-${mergedAlign}`]: mergedAlign,
|
||||
},
|
||||
className ?? space?.className,
|
||||
className,
|
||||
rootClassName,
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user