feat(Breadcrumb,ConfigProvider): support dropdownIcon prop and config (#56250)

* feat(Breadcrumb,ConfigProvider): support dropdownIcon prop and config

* refactor(Breadcrumb): import order

* docs(Breadcrumb,ConfigProvider): dropdonIcon

---------

Co-authored-by: thinkasany <480968828@qq.com>
This commit is contained in:
Guo Yunhe
2025-12-29 16:03:33 +08:00
committed by GitHub
parent 886a1d19cd
commit 3d152a78fd
9 changed files with 85 additions and 8 deletions

View File

@@ -37,7 +37,7 @@ function getOffsetTop(element: HTMLElement, container: AnchorContainer): number
if (rect.width || rect.height) {
if (container === window) {
return rect.top - element.ownerDocument!.documentElement!.clientTop;
return rect.top - element.ownerDocument.documentElement!.clientTop;
}
return rect.top - (container as HTMLElement).getBoundingClientRect().top;
}

View File

@@ -1,4 +1,5 @@
import * as React from 'react';
import { DownOutlined } from '@ant-design/icons';
import { toArray } from '@rc-component/util';
import pickAttrs from '@rc-component/util/lib/pickAttrs';
import { clsx } from 'clsx';
@@ -81,6 +82,7 @@ export interface BreadcrumbProps<T extends AnyObject = AnyObject> {
prefixCls?: string;
params?: T;
separator?: React.ReactNode;
dropdownIcon?: React.ReactNode;
style?: React.CSSProperties;
className?: string;
rootClassName?: string;
@@ -121,6 +123,7 @@ const Breadcrumb = <T extends AnyObject = AnyObject>(props: BreadcrumbProps<T>)
params = {},
classNames,
styles,
dropdownIcon,
...restProps
} = props;
@@ -132,9 +135,11 @@ const Breadcrumb = <T extends AnyObject = AnyObject>(props: BreadcrumbProps<T>)
classNames: contextClassNames,
styles: contextStyles,
separator: contextSeparator,
dropdownIcon: contextDropdownIcon,
} = useComponentConfig('breadcrumb');
const mergedSeparator = separator ?? contextSeparator ?? '/';
const mergedDropdownIcon = dropdownIcon ?? contextDropdownIcon ?? <DownOutlined />;
let crumbs: React.ReactNode;
@@ -240,6 +245,7 @@ const Breadcrumb = <T extends AnyObject = AnyObject>(props: BreadcrumbProps<T>)
className={itemClassName}
style={style}
dropdownProps={dropdownProps}
dropdownIcon={mergedDropdownIcon}
href={href}
separator={isLastItem ? '' : mergedSeparator}
onClick={onClick}

View File

@@ -1,5 +1,4 @@
import * as React from 'react';
import DownOutlined from '@ant-design/icons/DownOutlined';
import { clsx } from 'clsx';
import isNonNullable from '../_util/isNonNullable';
@@ -33,6 +32,7 @@ export interface BreadcrumbItemProps extends SeparatorType {
items?: MenuItem[];
};
dropdownProps?: DropdownProps;
dropdownIcon?: React.ReactNode;
onClick?: React.MouseEventHandler<HTMLAnchorElement | HTMLSpanElement>;
className?: string;
style?: React.CSSProperties;
@@ -40,7 +40,7 @@ export interface BreadcrumbItemProps extends SeparatorType {
}
export const InternalBreadcrumbItem: React.FC<BreadcrumbItemProps> = (props) => {
const { prefixCls, separator = '/', children, menu, dropdownProps, href } = props;
const { prefixCls, separator = '/', children, menu, dropdownProps, href, dropdownIcon } = props;
const breadcrumbContext = React.useContext(BreadcrumbContext);
const { classNames: mergedClassNames, styles: mergedStyles } = breadcrumbContext;
/** If overlay is have Wrap a Dropdown */
@@ -74,7 +74,7 @@ export const InternalBreadcrumbItem: React.FC<BreadcrumbItemProps> = (props) =>
<Dropdown placement="bottom" {...mergeDropDownProps}>
<span className={`${prefixCls}-overlay-link`}>
{breadcrumbItem}
<DownOutlined />
{dropdownIcon}
</span>
</Dropdown>
);

View File

@@ -3,7 +3,7 @@ import React from 'react';
import { accessibilityTest } from '../../../tests/shared/accessibilityTest';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { render } from '../../../tests/utils';
import { render, screen } from '../../../tests/utils';
import ConfigProvider from '../../config-provider';
import type { ItemType } from '../Breadcrumb';
import Breadcrumb from '../index';
@@ -311,6 +311,75 @@ describe('Breadcrumb', () => {
expect(document.querySelector('.ant-dropdown')).toBeTruthy();
});
it('should support custom dropdownIcon', () => {
render(
<Breadcrumb
items={[
{
title: 'test',
menu: {
items: [
{
key: '1',
label: 'label',
},
],
},
},
]}
dropdownIcon={<span>foobar</span>}
/>,
);
expect(screen.getByText('foobar')).toBeTruthy();
});
it('should support custom dropdownIcon in ConfigProvider', () => {
render(
<ConfigProvider breadcrumb={{ dropdownIcon: <span>foobar</span> }}>
<Breadcrumb
items={[
{
title: 'test',
menu: {
items: [
{
key: '1',
label: 'label',
},
],
},
},
]}
/>
</ConfigProvider>,
);
expect(screen.getByText('foobar')).toBeTruthy();
});
it('should prefer custom dropdownIcon prop than ConfigProvider', () => {
render(
<ConfigProvider breadcrumb={{ dropdownIcon: <span>foobar</span> }}>
<Breadcrumb
items={[
{
title: 'test',
menu: {
items: [
{
key: '1',
label: 'label',
},
],
},
},
]}
dropdownIcon={<span>bamboo</span>}
/>
</ConfigProvider>,
);
expect(screen.getByText('bamboo')).toBeTruthy();
});
it('Breadcrumb params type test', () => {
interface Params {
key1?: number;

View File

@@ -53,6 +53,7 @@ Common props ref[Common props](/docs/react/common-props)
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| classNames | Customize class for each semantic structure inside the component. Supports object or function. | Record<[SemanticDOM](#semantic-dom), string> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), string> | - | |
| dropdownIcon | Custom dropdown icon | ReactNode | `<DownOutlined />` | 6.2.0 |
| itemRender | Custom item renderer | (route, params, routes, paths) => ReactNode | - | |
| params | Routing parameters | object | - | |
| items | The routing stack information of router | [ItemType\[\]](#itemtype) | - | 5.3.0 |

View File

@@ -54,6 +54,7 @@ return <Breadcrumb routes={[{ breadcrumbName: 'sample' }]} />;
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| classNames | 用于自定义组件内部各语义化结构的 class支持对象或函数 | Record<[SemanticDOM](#semantic-dom), string> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), string> | - | |
| dropdownIcon | 自定义下拉图标 | ReactNode | `<DownOutlined />` | 6.2.0 |
| itemRender | 自定义链接函数,和 react-router 配置使用 | (route, params, routes, paths) => ReactNode | - | |
| params | 路由的参数 | object | - | |
| items | 路由栈信息 | [items\[\]](#itemtype) | - | 5.3.0 |

View File

@@ -242,7 +242,7 @@ export type AlertConfig = ComponentStyleConfig &
export type BadgeConfig = ComponentStyleConfig & Pick<BadgeProps, 'classNames' | 'styles'>;
export type BreadcrumbConfig = ComponentStyleConfig &
Pick<BreadcrumbProps, 'classNames' | 'styles' | 'separator'>;
Pick<BreadcrumbProps, 'classNames' | 'styles' | 'separator' | 'dropdownIcon'>;
export type InputConfig = ComponentStyleConfig &
Pick<InputProps, 'autoComplete' | 'classNames' | 'styles' | 'allowClear' | 'variant'>;

View File

@@ -113,7 +113,7 @@ const {
| anchor | Set Anchor common props | { className?: string, style?: React.CSSProperties, classNames?: [AnchorStyleConfig\["classNames"\]](/components/anchor#semantic-dom), styles?: [AnchorStyleConfig\["styles"\]](/components/anchor#semantic-dom), successIcon?: React.ReactNode, infoIcon?: React.ReactNode, warningIcon?: React.ReactNode, errorIcon?: React.ReactNode } | - | 5.7.0 , `classNames` and `styles`: 6.0.0, `successIcon`, `infoIcon`, `warningIcon` and `errorIcon`: 6.2.0 |
| avatar | Set Avatar common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| badge | Set Badge common props | { className?: string, style?: React.CSSProperties, classNames?: [BadgeProps\["classNames"\]](/components/badge#semantic-dom), styles?: [BadgeProps\["styles"\]](/components/badge#semantic-dom) } | - | 5.7.0 |
| breadcrumb | Set Breadcrumb common props | { className?: string, style?: React.CSSProperties, classNames?: [BreadcrumbConfig\["classNames"\]](/components/breadcrumb#semantic-dom), styles?: [BreadcrumbConfig\["styles"\]](/components/breadcrumb#semantic-dom), separator?: ReactNode } | - | 5.7.0, `classNames`, `separator` and `styles`: 6.0.0 |
| breadcrumb | Set Breadcrumb common props | { className?: string, style?: React.CSSProperties, classNames?: [BreadcrumbConfig\["classNames"\]](/components/breadcrumb#semantic-dom), styles?: [BreadcrumbConfig\["styles"\]](/components/breadcrumb#semantic-dom), separator?: ReactNode, dropdownIcon?: ReactNode } | - | 5.7.0, `classNames`, `separator` and `styles`: 6.0.0, `dropdownIcon`: 6.2.0 |
| button | Set Button common props | { className?: string, style?: React.CSSProperties, classNames?: [ButtonProps\["classNames"\]](/components/button#semantic-dom), styles?: [ButtonProps\["styles"\]](/components/button#semantic-dom), autoInsertSpace?: boolean, variant?: ButtonVariantType, color?: ButtonColorType, shape?: [ButtonProps\["shape"\]](/components/button#api) } | - | 5.6.0, `autoInsertSpace`: 5.17.0, `variant` and `color`: 5.25.0, `shape`: 5.27.0 |
| card | Set Card common props | { className?: string, style?: React.CSSProperties, classNames?: [CardProps\["classNames"\]](/components/card#semantic-dom), styles?: [CardProps\["styles"\]](/components/card#semantic-dom) } | - | 5.7.0, `classNames` and `styles`: 5.14.0 |
| cardMeta | Set Card.Meta common props | { className?: string, style?: React.CSSProperties, classNames?: [CardMetaProps\["classNames"\]](/components/card#semantic-dom), styles?: [CardMetaProps\["styles"\]](/components/card#semantic-dom) } | - | 6.0.0 |

View File

@@ -115,7 +115,7 @@ const {
| anchor | 设置 Anchor 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [AnchorStyleConfig\["classNames"\]](/components/anchor-cn#semantic-dom), styles?: [AnchorStyleConfig\["styles"\]](/components/anchor-cn#semantic-dom), successIcon?: React.ReactNode, infoIcon?: React.ReactNode, warningIcon?: React.ReactNode, errorIcon?: React.ReactNode } | - | 5.7.0, `classNames``styles`: 6.0.0, `successIcon`, `infoIcon`, `warningIcon``errorIcon`: 6.2.0 |
| avatar | 设置 Avatar 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| badge | 设置 Badge 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [BadgeProps\["classNames"\]](/components/badge-cn#semantic-dom), styles?: [BadgeProps\["styles"\]](/components/badge-cn#semantic-dom) } | - | 5.7.0 |
| breadcrumb | 设置 Breadcrumb 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [BreadcrumbConfig\["classNames"\]](/components/breadcrumb-cn#semantic-dom), styles?: [BreadcrumbConfig\["styles"\]](/components/breadcrumb-cn#semantic-dom), separator?: ReactNode } | - | 5.7.0, `classNames`, `separator``styles`: 6.0.0 |
| breadcrumb | 设置 Breadcrumb 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [BreadcrumbConfig\["classNames"\]](/components/breadcrumb-cn#semantic-dom), styles?: [BreadcrumbConfig\["styles"\]](/components/breadcrumb-cn#semantic-dom), separator?: ReactNode, dropdownIcon?: ReactNode } | - | 5.7.0, `classNames`, `separator``styles`: 6.0.0, `dropdownIcon`: 6.2.0 |
| button | 设置 Button 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [ButtonProps\["classNames"\]](/components/button-cn#semantic-dom), styles?: [ButtonProps\["styles"\]](/components/button-cn#semantic-dom), autoInsertSpace?: boolean, variant?: ButtonVariantType, color?: ButtonColorType, shape?: [ButtonProps\["shape"\]](/components/button#api) } | - | 5.6.0, `autoInsertSpace`: 5.17.0, `variant``color`: 5.25.0, `shape`: 5.27.0 |
| calendar | 设置 Calendar 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [CalendarConfig\["classNames"\]](/components/calendar-cn#semantic-dom), styles?: [CalendarConfig\["styles"\]](/components/calendar-cn#semantic-dom) } | - | 5.7.0, `classNames``styles`: 6.0.0 |
| card | 设置 Card 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [CardProps\["classNames"\]](/components/card-cn#semantic-dom), styles?: [CardProps\["styles"\]](/components/card-cn#semantic-dom) } | - | 5.7.0, `classNames``styles`: 5.14.0 |