feat: ConfigProvider support popover (#52110)

* feat: ConfigProvider support popover

* remove tooltip debug demo
This commit is contained in:
thinkasany 2024-12-25 10:41:58 +08:00 committed by GitHub
parent ce87c614e1
commit 42f9789669
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 124 additions and 36 deletions

View File

@ -35,6 +35,7 @@ import type { TransferProps } from '../transfer';
import type { TreeSelectProps } from '../tree-select';
import type { RenderEmptyHandler } from './defaultRenderEmpty';
import type { TooltipProps } from '../tooltip';
import type { PopoverProps } from '../popover';
export const defaultPrefixCls = 'ant';
export const defaultIconPrefixCls = 'anticon';
@ -179,6 +180,8 @@ export type SpaceConfig = ComponentStyleConfig & Pick<SpaceProps, 'size' | 'clas
export type TooltipConfig = Pick<TooltipProps, 'className' | 'style' | 'styles' | 'classNames'>;
export type PopoverConfig = Pick<PopoverProps, 'className' | 'style' | 'styles' | 'classNames'>;
export type SpinConfig = ComponentStyleConfig & Pick<SpinProps, 'indicator'>;
export type InputNumberConfig = ComponentStyleConfig & Pick<InputNumberProps, 'variant'>;
@ -293,6 +296,7 @@ export interface ConfigConsumerProps {
timePicker?: TimePickerConfig;
tour?: TourConfig;
tooltip?: TooltipConfig;
popover?: PopoverConfig;
upload?: ComponentStyleConfig;
notification?: NotificationConfig;
tree?: ComponentStyleConfig;

View File

@ -162,7 +162,8 @@ const {
| timeline | Set Timeline common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| timePicker | Set TimePicker common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| tour | Set Tour common props | { closeIcon?: React.ReactNode } | - | 5.14.0 |
| tooltip | Set Tooltip common props | { className?: string, style?: React.CSSProperties, classNames?:[Tooltip\["classNames"\]](/components/tooltip-cn#api), styles?: [Tooltip\["styles"\]](/components/tooltip#api) } | - | 5.23.0 |
| tooltip | Set Tooltip common props | { className?: string, style?: React.CSSProperties, classNames?:[Tooltip\["classNames"\]](/components/tooltip#api), styles?: [Tooltip\["styles"\]](/components/tooltip#api) } | - | 5.23.0 |
| popover | Set Popover common props | { className?: string, style?: React.CSSProperties, classNames?:[Popover\["classNames"\]](/components/popover#api), styles?: [Popover\["styles"\]](/components/popover#api) } | - | 5.23.0 |
| transfer | Set Transfer common props | { className?: string, style?: React.CSSProperties, selectionsIcon?: React.ReactNode } | - | 5.7.0, selectionsIcon: 5.14.0 |
| tree | Set Tree common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| typography | Set Typography common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |

View File

@ -52,6 +52,7 @@ import type {
ThemeConfig,
TimePickerConfig,
TooltipConfig,
PopoverConfig,
TourConfig,
TransferConfig,
TreeSelectConfig,
@ -237,6 +238,7 @@ export interface ConfigProviderProps {
wave?: WaveConfig;
tour?: TourConfig;
tooltip?: TooltipConfig;
popover?: PopoverConfig;
}
interface ProviderChildrenProps extends ConfigProviderProps {
@ -392,6 +394,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
warning: warningConfig,
tour,
tooltip,
popover,
floatButtonGroup,
variant,
inputNumber,
@ -493,6 +496,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
warning: warningConfig,
tour,
tooltip,
popover,
floatButtonGroup,
variant,
inputNumber,

View File

@ -165,6 +165,7 @@ const {
| timePicker | 设置 TimePicker 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| tour | 设置 Tour 组件的通用属性 | { closeIcon?: React.ReactNode } | - | 5.14.0 |
| tooltip | 设置 Tooltip 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?:[Tooltip\["classNames"\]](/components/tooltip-cn#api), styles?: [Tooltip\["styles"\]](/components/tooltip-cn#api) } | - | 5.23.0 |
| popover | 设置 Popover 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?:[Popover\["classNames"\]](/components/popover-cn#api), styles?: [Popover\["styles"\]](/components/popover-cn#api) } | - | 5.23.0 |
| transfer | 设置 Transfer 组件的通用属性 | { className?: string, style?: React.CSSProperties, selectionsIcon?: React.ReactNode } | - | 5.7.0, selectionsIcon: 5.14.0 |
| tree | 设置 Tree 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| typography | 设置 Typography 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |

View File

@ -137,4 +137,33 @@ describe('Popover', () => {
expect(popup).toBe(null);
});
});
it('should apply custom styles to Popover', () => {
const customClassNames = {
body: 'custom-body',
root: 'custom-root',
};
const customStyles = {
body: { color: 'red' },
root: { backgroundColor: 'blue' },
};
const { container } = render(
<Popover classNames={customClassNames} overlay={<div />} styles={customStyles} open>
<button type="button">button</button>
</Popover>,
);
const popoverElement = container.querySelector('.ant-popover') as HTMLElement;
const popoverBodyElement = container.querySelector('.ant-popover-inner') as HTMLElement;
// 验证 classNames
expect(popoverElement.classList).toContain('custom-root');
expect(popoverBodyElement.classList).toContain('custom-body');
// 验证 styles
expect(popoverElement.style.backgroundColor).toBe('blue');
expect(popoverBodyElement.style.color).toBe('red');
});
});

View File

@ -0,0 +1,49 @@
import React from 'react';
import { Popover } from 'antd';
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
import useLocale from '../../../.dumi/hooks/useLocale';
const locales = {
cn: {
root: '根节点 (包含箭头、内容元素)',
body: '内容元素',
},
en: {
root: 'Root element (including arrows, content elements)',
body: 'Body element',
},
};
const BlockList: React.FC<React.PropsWithChildren> = (props: any) => {
const divRef = React.useRef<HTMLDivElement>(null);
return (
<div ref={divRef} style={{ position: 'absolute', marginTop: 60 }}>
<Popover
title="prompt text"
open
placement="top"
autoAdjustOverflow={false}
getPopupContainer={() => divRef.current}
{...props}
/>
</div>
);
};
const App: React.FC = () => {
const [locale] = useLocale(locales);
return (
<SemanticPreview
semantics={[
{ name: 'root', desc: locale.root, version: '5.23.0' },
{ name: 'body', desc: locale.body, version: '5.23.0' },
]}
>
<BlockList />
</SemanticPreview>
);
};
export default App;

View File

@ -47,6 +47,10 @@ Common props ref[Common props](/docs/react/common-props)
Please ensure that the child node of `Popover` accepts `onMouseEnter`, `onMouseLeave`, `onFocus`, `onClick` events.
## Semantic DOM
<code src="./demo/_semantic.tsx" simplify="true"></code>
## Design Token
<ComponentTokenTable component="Popover"></ComponentTokenTable>

View File

@ -36,15 +36,25 @@ const InternalPopover = React.forwardRef<TooltipRef, PopoverProps>((props, ref)
mouseLeaveDelay = 0.1,
onOpenChange,
overlayStyle = {},
styles,
classNames: popoverClassNames,
...otherProps
} = props;
const { getPrefixCls } = React.useContext(ConfigContext);
const { popover, getPrefixCls } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('popover', customizePrefixCls);
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
const rootPrefixCls = getPrefixCls();
const overlayCls = classNames(overlayClassName, hashId, cssVarCls);
const rootClassNames = classNames(
overlayClassName,
hashId,
cssVarCls,
popover?.classNames?.root,
popoverClassNames?.root,
);
const bodyClassNames = classNames(popover?.classNames?.body, popoverClassNames?.body);
const [open, setOpen] = useMergedState(false, {
value: props.open ?? props.visible,
defaultValue: props.defaultOpen ?? props.defaultVisible,
@ -77,10 +87,21 @@ const InternalPopover = React.forwardRef<TooltipRef, PopoverProps>((props, ref)
trigger={trigger}
mouseEnterDelay={mouseEnterDelay}
mouseLeaveDelay={mouseLeaveDelay}
overlayStyle={overlayStyle}
{...otherProps}
prefixCls={prefixCls}
overlayClassName={overlayCls}
classNames={{ root: rootClassNames, body: bodyClassNames }}
styles={{
root: {
...popover?.styles?.root,
...popover?.style,
...overlayStyle,
...styles?.root,
},
body: {
...popover?.styles?.body,
...styles?.body,
},
}}
ref={ref}
open={open}
onOpenChange={onInternalOpenChange}

View File

@ -48,6 +48,10 @@ demo:
请确保 `Popover` 的子元素能接受 `onMouseEnter`、`onMouseLeave`、`onFocus`、`onClick` 事件。
## Semantic DOM
<code src="./demo/_semantic.tsx" simplify="true"></code>
## 主题变量Design Token
<ComponentTokenTable component="Popover"></ComponentTokenTable>

View File

@ -1,7 +0,0 @@
## zh-CN
debug config provide
## en-US
debug config provide

View File

@ -1,21 +0,0 @@
import React from 'react';
import { ConfigProvider, Tooltip } from 'antd';
const App: React.FC = () => (
<div>
<ConfigProvider
tooltip={{
className: 'cutsom-tooltip-test',
style: { background: 'yellow' },
styles: { body: { color: 'red', borderRadius: 50 }, root: { color: 'green' } },
classNames: { root: 'custom-root', body: 'custom-body' },
}}
>
<Tooltip title="prompt text">
<span>Tooltip will show on mouse enter.</span>
</Tooltip>
</ConfigProvider>
</div>
);
export default App;

View File

@ -312,7 +312,7 @@ const InternalTooltip = React.forwardRef<TooltipRef, TooltipProps>((props, ref)
tooltipClassNames?.root,
);
const bodyClassnames = classNames(tooltip?.classNames?.body, tooltipClassNames?.body);
const bodyClassNames = classNames(tooltip?.classNames?.body, tooltipClassNames?.body);
// ============================ zIndex ============================
const [zIndex, contextZIndex] = useZIndex('Tooltip', otherProps.zIndex);
@ -326,7 +326,7 @@ const InternalTooltip = React.forwardRef<TooltipRef, TooltipProps>((props, ref)
mouseEnterDelay={mouseEnterDelay}
mouseLeaveDelay={mouseLeaveDelay}
prefixCls={prefixCls}
classNames={{ root: rootClassNames, body: bodyClassnames }}
classNames={{ root: rootClassNames, body: bodyClassNames }}
styles={{
root: {
...arrowContentStyle,

View File

@ -30,7 +30,6 @@ demo:
<code src="./demo/debug.tsx" debug>Debug</code>
<code src="./demo/disabled.tsx">禁用</code>
<code src="./demo/disabled-children.tsx" debug>禁用子元素</code>
<code src="./demo/config-debug.tsx" debug>ConfigProvider</code>
## API