chore: auto merge branches (#52227)
Some checks failed
Publish Any Commit / build (push) Has been cancelled
✅ test v6 / lint (push) Has been cancelled
✅ test v6 / test-react-legacy (18, 1/2) (push) Has been cancelled
✅ test v6 / test-react-legacy (18, 2/2) (push) Has been cancelled
✅ test v6 / test-node (push) Has been cancelled
✅ test v6 / test-react-latest (dom, 1/2) (push) Has been cancelled
✅ test v6 / test-react-latest (dom, 2/2) (push) Has been cancelled
✅ test v6 / build (push) Has been cancelled
✅ test v6 / test lib/es module (es, 1/2) (push) Has been cancelled
✅ test v6 / test lib/es module (es, 2/2) (push) Has been cancelled
✅ test v6 / test lib/es module (lib, 1/2) (push) Has been cancelled
✅ test v6 / test lib/es module (lib, 2/2) (push) Has been cancelled
👁️ Visual Regression Persist Start / test image (push) Has been cancelled
✅ test v6 / test-react-latest-dist (dist, 1/2) (push) Has been cancelled
✅ test v6 / test-react-latest-dist (dist, 2/2) (push) Has been cancelled
✅ test v6 / test-react-latest-dist (dist-min, 1/2) (push) Has been cancelled
✅ test v6 / test-react-latest-dist (dist-min, 2/2) (push) Has been cancelled
✅ test v6 / test-coverage (push) Has been cancelled

chore: sync master into next
This commit is contained in:
github-actions[bot] 2025-01-03 13:33:12 +00:00 committed by GitHub
commit 4cc31c7bc7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
281 changed files with 13372 additions and 2414 deletions

View File

@ -111,12 +111,14 @@ const SemanticPreview: React.FC<SemanticPreviewProps> = (props) => {
const targetElement = containerRef.current?.querySelector<HTMLElement>(`.${targetClassName}`);
const containerRect = containerRef.current?.getBoundingClientRect();
const targetRect = targetElement?.getBoundingClientRect();
setMarkPos([
(targetRect?.left || 0) - (containerRect?.left || 0),
(targetRect?.top || 0) - (containerRect?.top || 0),
targetRect?.width || 0,
targetRect?.height || 0,
]);
timerRef.current = setTimeout(() => {
setPositionMotion(true);
}, 10);

View File

@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import { ColorPicker, Flex, Input } from 'antd';
import { createStyles } from 'antd-style';
import type { ColorPickerProps, GetProp } from 'antd';
import { createStyles } from 'antd-style';
import { generateColor } from 'antd/es/color-picker/util';
import classNames from 'classnames';
@ -61,7 +61,7 @@ const DebouncedColorPicker: React.FC<React.PropsWithChildren<ThemeColorPickerPro
<ColorPicker
value={value}
onChange={setValue}
presets={[{ label: 'PresetColors', colors: PRESET_COLORS }]}
presets={[{ label: 'PresetColors', key: 'PresetColors', colors: PRESET_COLORS }]}
>
{children}
</ColorPicker>

View File

@ -6,7 +6,7 @@ import {
HomeOutlined,
QuestionCircleOutlined,
} from '@ant-design/icons';
import { TinyColor } from '@ctrl/tinycolor';
import { FastColor } from '@ant-design/fast-color';
import type { ColorPickerProps, GetProp, MenuProps, ThemeConfig } from 'antd';
import {
Breadcrumb,
@ -324,7 +324,7 @@ const ThemesInfo: Record<THEME, Partial<ThemeData>> = {
const normalize = (value: number) => value / 255;
function rgbToColorMatrix(color: string) {
const rgb = new TinyColor(color).toRgb();
const rgb = new FastColor(color).toRgb();
const { r, g, b } = rgb;
const invertValue = normalize(r) * 100;

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import type { ColorInput } from '@ctrl/tinycolor';
import { TinyColor } from '@ctrl/tinycolor';
import { FastColor } from '@ant-design/fast-color';
import type { ColorInput } from '@ant-design/fast-color';
import { createStyles } from 'antd-style';
const useStyle = createStyles(({ token, css }) => ({
@ -22,7 +22,7 @@ const useStyle = createStyles(({ token, css }) => ({
}));
interface ColorChunkProps {
value?: ColorInput;
value: ColorInput;
}
const ColorChunk: React.FC<React.PropsWithChildren<ColorChunkProps>> = (props) => {
@ -30,7 +30,7 @@ const ColorChunk: React.FC<React.PropsWithChildren<ColorChunkProps>> = (props) =
const { value, children } = props;
const dotColor = React.useMemo(() => {
const _color = new TinyColor(value).toHex8String();
const _color = new FastColor(value).toHexString();
return _color.endsWith('ff') ? _color.slice(0, -2) : _color;
}, [value]);

View File

@ -157,7 +157,7 @@ const SubTokenTable: React.FC<SubTokenTableProps> = (props) => {
{title}
<Popover
title={null}
overlayStyle={{ width: 400 }}
styles={{ root: { width: 400 } }}
content={
<Typography>
{/* <SourceCode lang="jsx">{code}</SourceCode> */}

View File

@ -8,6 +8,7 @@ import classNames from 'classnames';
import { FormattedMessage, useLiveDemo, useSiteData } from 'dumi';
import LZString from 'lz-string';
import RiddleButton from './RiddleButton';
import useLocation from '../../../hooks/useLocation';
import BrowserFrame from '../../common/BrowserFrame';
import ClientOnly from '../../common/ClientOnly';
@ -16,11 +17,9 @@ import EditButton from '../../common/EditButton';
import CodePenIcon from '../../icons/CodePenIcon';
import CodeSandboxIcon from '../../icons/CodeSandboxIcon';
import ExternalLinkIcon from '../../icons/ExternalLinkIcon';
import RiddleIcon from '../../icons/RiddleIcon';
import DemoContext from '../../slots/DemoContext';
import type { SiteContextProps } from '../../slots/SiteContext';
import SiteContext from '../../slots/SiteContext';
import { ping } from '../../utils';
import type { AntdPreviewerProps } from './Previewer';
const { ErrorBoundary } = Alert;
@ -39,27 +38,6 @@ const track = ({ type, demo }: { type: string; demo: string }) => {
window.gtag('event', 'demo', { event_category: type, event_label: demo });
};
let pingDeferrer: PromiseLike<boolean>;
function useShowRiddleButton() {
const [showRiddleButton, setShowRiddleButton] = useState(false);
useEffect(() => {
pingDeferrer ??= new Promise<boolean>((resolve) => {
ping((status) => {
if (status !== 'timeout' && status !== 'error') {
return resolve(true);
}
return resolve(false);
});
});
pingDeferrer.then(setShowRiddleButton);
}, []);
return showRiddleButton;
}
const useStyle = createStyles(({ token }) => {
const { borderRadius } = token;
return {
@ -98,7 +76,7 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
title,
description,
originDebug,
jsx,
jsx = '',
style,
compact,
background,
@ -117,7 +95,6 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
const entryName = 'index.tsx';
const entryCode = asset.dependencies[entryName].value;
const showRiddleButton = useShowRiddleButton();
const previewDemo = useRef<React.ReactNode>(null);
const demoContainer = useRef<HTMLElement>(null);
@ -127,11 +104,10 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
setSource: setLiveDemoSource,
} = useLiveDemo(asset.id, {
iframe: Boolean(iframe),
containerRef: demoContainer,
containerRef: demoContainer as React.RefObject<HTMLElement>,
});
const anchorRef = useRef<HTMLAnchorElement>(null);
const codeSandboxIconRef = useRef<HTMLFormElement>(null);
const riddleIconRef = useRef<HTMLFormElement>(null);
const codepenIconRef = useRef<HTMLFormElement>(null);
const [codeExpand, setCodeExpand] = useState<boolean>(false);
const { theme } = useContext<SiteContextProps>(SiteContext);
@ -277,19 +253,6 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
.join(';'),
js_pre_processor: 'typescript',
};
const riddlePrefillConfig = {
title: `${localizedTitle} - antd@${dependencies.antd}`,
js: `${
/import React(\D*)from 'react';/.test(jsx) ? '' : `import React from 'react';\n`
}import { createRoot } from 'react-dom/client';\n${jsx.replace(
/export default/,
'const ComponentDemo =',
)}\n\ncreateRoot(mountNode).render(<ComponentDemo />);\n`,
css: '',
json: JSON.stringify({ name: 'antd-demo', dependencies }, null, 2),
};
// Reorder source code
let parsedSourceCode = suffix === 'tsx' ? entryCode : jsx;
let importReactContent = "import React from 'react';";
@ -440,24 +403,13 @@ createRoot(document.getElementById('container')).render(<Demo />);
<CodeSandboxIcon className="code-box-codesandbox" />
</Tooltip>
</form>
{showRiddleButton ? (
<form
className="code-box-code-action"
action="//riddle.alibaba-inc.com/riddles/define"
method="POST"
target="_blank"
ref={riddleIconRef}
onClick={() => {
track({ type: 'riddle', demo: asset.id });
riddleIconRef.current?.submit();
}}
>
<input type="hidden" name="data" value={JSON.stringify(riddlePrefillConfig)} />
<Tooltip title={<FormattedMessage id="app.demo.riddle" />}>
<RiddleIcon className="code-box-riddle" />
</Tooltip>
</form>
) : null}
<RiddleButton
title={localizedTitle}
dependencies={dependencies}
jsx={jsx}
track={track}
asset={asset}
/>
<Tooltip title={<FormattedMessage id="app.demo.stackblitz" />}>
<span
className="code-box-code-action"

View File

@ -7,6 +7,7 @@ import DesignPreviewer from './DesignPreviewer';
export interface AntdPreviewerProps extends IPreviewerProps {
originDebug?: IPreviewerProps['debug'];
jsx?: string;
}
const Previewer: React.FC<AntdPreviewerProps> = (props) => {

View File

@ -0,0 +1,91 @@
import React, { Suspense, useEffect, useRef, useState } from 'react';
import { Tooltip } from 'antd';
import { FormattedMessage } from 'dumi';
import type { IPreviewerProps } from 'dumi';
import RiddleIcon from '../../icons/RiddleIcon';
import { ping } from '../../utils';
let pingDeferrer: PromiseLike<boolean>;
function useShowRiddleButton() {
const [showRiddleButton, setShowRiddleButton] = useState(false);
useEffect(() => {
pingDeferrer ??= new Promise<boolean>((resolve) => {
ping((status) => {
if (status !== 'timeout' && status !== 'error') {
return resolve(true);
}
return resolve(false);
});
});
pingDeferrer.then(setShowRiddleButton);
}, []);
return showRiddleButton;
}
interface RiddleButtonProps {
title?: string;
dependencies: Record<PropertyKey, string>;
jsx: string;
track: ({
type,
demo,
}: {
type: string;
demo: string;
}) => void;
asset: IPreviewerProps['asset'];
}
const RiddleButton: React.FC<RiddleButtonProps> = ({
title,
dependencies = {},
jsx,
track,
asset,
}) => {
const riddleIconRef = useRef<HTMLFormElement>(null);
const showRiddleButton = useShowRiddleButton();
const riddlePrefillConfig = {
title: `${title} - antd@${dependencies.antd}`,
js: `${
/import React(\D*)from 'react';/.test(jsx) ? '' : `import React from 'react';\n`
}import { createRoot } from 'react-dom/client';\n${jsx.replace(
/export default/,
'const ComponentDemo =',
)}\n\ncreateRoot(mountNode).render(<ComponentDemo />);\n`,
css: '',
json: JSON.stringify({ name: 'antd-demo', dependencies }, null, 2),
};
return showRiddleButton ? (
<form
className="code-box-code-action"
action="//riddle.alibaba-inc.com/riddles/define"
method="POST"
target="_blank"
ref={riddleIconRef}
onClick={() => {
track({ type: 'riddle', demo: asset.id });
riddleIconRef.current?.submit();
}}
>
<input type="hidden" name="data" value={JSON.stringify(riddlePrefillConfig)} />
<Tooltip title={<FormattedMessage id="app.demo.riddle" />}>
<RiddleIcon className="code-box-riddle" />
</Tooltip>
</form>
) : null;
};
export default (props: RiddleButtonProps) => (
<Suspense>
<RiddleButton {...props} />
</Suspense>
);

View File

@ -1,6 +1,6 @@
// 用于 color.md 中的颜色对比
import React from 'react';
import { TinyColor } from '@ctrl/tinycolor';
import { FastColor } from '@ant-design/fast-color';
import { Flex, theme } from 'antd';
import { createStyles } from 'antd-style';
import tokenMeta from 'antd/es/version/token-meta.json';
@ -55,7 +55,7 @@ const useStyle = createStyles(({ token, css }) => {
});
function color2Rgba(color: string) {
return `#${new TinyColor(color).toHex8().toUpperCase()}`;
return `#${new FastColor(color).toHexString().toUpperCase()}`;
}
interface ColorCircleProps {

View File

@ -99,7 +99,7 @@ const TokenTable: FC<TokenTableProps> = ({ type }) => {
name: token,
desc: lang === 'cn' ? meta.desc : meta.descEn,
type: meta.type,
value: defaultToken[token],
value: defaultToken[token as keyof typeof defaultToken],
})),
[type, lang],
);

View File

@ -1,5 +1,5 @@
import React from 'react';
import { TinyColor } from '@ctrl/tinycolor';
import { FastColor } from '@ant-design/fast-color';
import { css, Global } from '@emotion/react';
import { useTheme } from 'antd-style';
@ -410,7 +410,7 @@ const GlobalStyle: React.FC = () => {
background: ${demoGridColor};
&:nth-child(2n + 1) {
background: ${new TinyColor(demoGridColor).setAlpha(0.75).toHex8String()};
background: ${new FastColor(demoGridColor).setA(0.75).toHexString()};
}
}
@ -426,12 +426,12 @@ const GlobalStyle: React.FC = () => {
}
${antCls}-row .demo-col-1 {
background: ${new TinyColor(demoGridColor).setAlpha(0.75).toHexString()};
background: ${new FastColor(demoGridColor).setA(0.75).toHexString()};
}
${antCls}-row .demo-col-2,
.code-box-demo ${antCls}-row .demo-col-2 {
background: ${new TinyColor(demoGridColor).setAlpha(0.75).toHexString()};
background: ${new FastColor(demoGridColor).setA(0.75).toHexString()};
}
${antCls}-row .demo-col-3,
@ -442,7 +442,7 @@ const GlobalStyle: React.FC = () => {
${antCls}-row .demo-col-4,
.code-box-demo ${antCls}-row .demo-col-4 {
background: ${new TinyColor(demoGridColor).setAlpha(0.6).toHexString()};
background: ${new FastColor(demoGridColor).setA(0.6).toHexString()};
}
${antCls}-row .demo-col-5,

View File

@ -13,7 +13,7 @@ import {
UsergroupAddOutlined,
ZhihuOutlined,
} from '@ant-design/icons';
import { TinyColor } from '@ctrl/tinycolor';
import { FastColor } from '@ant-design/fast-color';
import { createStyles } from 'antd-style';
import getAlphaColor from 'antd/es/theme/util/getAlphaColor';
import { FormattedMessage, Link } from 'dumi';
@ -37,7 +37,7 @@ const locales = {
const useStyle = () => {
const { isMobile } = useContext(SiteContext);
return createStyles(({ token, css }) => {
const background = new TinyColor(getAlphaColor('#f0f3fa', '#fff'))
const background = new FastColor(getAlphaColor('#f0f3fa', '#fff'))
.onBackground(token.colorBgContainer)
.toHexString();

View File

@ -357,7 +357,7 @@ const Header: React.FC = () => {
<header className={headerClassName}>
{isMobile && (
<Popover
overlayClassName={styles.popoverMenu}
classNames={{ root: styles.popoverMenu }}
placement="bottomRight"
content={menu}
trigger="click"

View File

@ -74,5 +74,6 @@
"5.22.1": [
"https://github.com/ant-design/ant-design/issues/51420",
"https://github.com/ant-design/ant-design/issues/51430"
]
],
"5.22.6": ["https://github.com/ant-design/ant-design/issues/52124"]
}

View File

@ -15,6 +15,15 @@ tag: vVERSION
---
## 5.22.7
`2024-12-27`
- 🐞 Fix Button text and icon not align. [#52132](https://github.com/ant-design/ant-design/pull/52132) [@afc163](https://github.com/afc163)
- 🐞 Fix Button throws `reactRender is not a function` under React 19. [#52105](https://github.com/ant-design/ant-design/pull/52105) [@afc163](https://github.com/afc163)
- TypeScript
- 🤖 Fix Menu interface type error from external module. [#51715](https://github.com/ant-design/ant-design/pull/51715) [@msyavuz](https://github.com/msyavuz)
## 5.22.6
`2024-12-23`

View File

@ -15,6 +15,15 @@ tag: vVERSION
---
## 5.22.7
`2024-12-27`
- 🐞 修复 Button 文字和图标不对齐的问题。[#52132](https://github.com/ant-design/ant-design/pull/52132) [@afc163](https://github.com/afc163)
- 🐞 修复在 React 19 下点击 Button 时抛出 `reactRender is not a function` 错误的问题。[#52105](https://github.com/ant-design/ant-design/pull/52105) [@afc163](https://github.com/afc163)
- TypeScript
- 🤖 修复 Menu `component` 属性类型抛错。[#51715](https://github.com/ant-design/ant-design/pull/51715) [@msyavuz](https://github.com/msyavuz)
## 5.22.6
`2024-12-23`

View File

@ -20,9 +20,10 @@ export interface BaseProps {
/* istanbul ignore next */
const genPurePanel = <ComponentProps extends BaseProps = BaseProps>(
Component: any,
defaultPrefixCls?: string,
getDropdownCls?: null | ((prefixCls: string) => string),
alignPropName?: 'align' | 'dropdownAlign' | 'popupAlign',
postProps?: (props: ComponentProps) => ComponentProps,
defaultPrefixCls?: string,
getDropdownCls?: (prefixCls: string) => string,
) => {
type WrapProps = ComponentProps & AnyObject;
@ -55,7 +56,6 @@ const genPurePanel = <ComponentProps extends BaseProps = BaseProps>(
? `.${getDropdownCls(prefixCls)}`
: `.${prefixCls}-dropdown`;
const popup = holderRef.current?.querySelector(dropdownCls);
if (popup) {
clearInterval(interval);
resizeObserver.observe(popup);
@ -83,6 +83,16 @@ const genPurePanel = <ComponentProps extends BaseProps = BaseProps>(
if (postProps) {
mergedProps = postProps(mergedProps);
}
if (alignPropName) {
Object.assign(mergedProps, {
[alignPropName]: {
overflow: {
adjustX: false,
adjustY: false,
},
},
});
}
const mergedStyle: React.CSSProperties = {
paddingBottom: popupHeight,
position: 'relative',

View File

@ -69,13 +69,13 @@ export default function useResponsiveObserver() {
return React.useMemo(() => {
const subscribers = new Map<number, SubscribeFunc>();
let subUid = -1;
let screens = {};
let screens: Partial<Record<Breakpoint, boolean>> = {};
return {
matchHandlers: {} as {
[prop: string]: {
mql: MediaQueryList;
listener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | null;
listener: (this: MediaQueryList, ev: MediaQueryListEvent) => void;
};
},
dispatch(pointMap: ScreenMap) {
@ -84,7 +84,9 @@ export default function useResponsiveObserver() {
return subscribers.size >= 1;
},
subscribe(func: SubscribeFunc): number {
if (!subscribers.size) this.register();
if (!subscribers.size) {
this.register();
}
subUid += 1;
subscribers.set(subUid, func);
func(screens);
@ -92,7 +94,9 @@ export default function useResponsiveObserver() {
},
unsubscribe(paramToken: number) {
subscribers.delete(paramToken);
if (!subscribers.size) this.unregister();
if (!subscribers.size) {
this.unregister();
}
},
unregister() {
Object.keys(responsiveMap).forEach((screen) => {
@ -117,7 +121,6 @@ export default function useResponsiveObserver() {
mql,
listener,
};
listener(mql);
});
},
@ -129,7 +132,7 @@ export default function useResponsiveObserver() {
export const matchScreen = (screens: ScreenMap, screenSizes?: ScreenSizeMap) => {
if (screenSizes && typeof screenSizes === 'object') {
for (let i = 0; i < responsiveArray.length; i++) {
const breakpoint: Breakpoint = responsiveArray[i];
const breakpoint = responsiveArray[i];
if (screens[breakpoint] && screenSizes[breakpoint] !== undefined) {
return screenSizes[breakpoint];
}

View File

@ -159,7 +159,7 @@ const RefAutoComplete = React.forwardRef<RefSelectProps, AutoCompleteProps>(
// We don't care debug panel
/* istanbul ignore next */
const PurePanel = genPurePanel(RefAutoComplete, undefined, undefined, (props: any) =>
const PurePanel = genPurePanel(RefAutoComplete, 'dropdownAlign', (props: any) =>
omit(props, ['visible']),
);

View File

@ -271,8 +271,8 @@ describe('Avatar Render', () => {
count: 2,
popover: {
placement: 'bottomRight',
overlayClassName: 'wanpan-111',
overlayStyle: { background: 'red' },
classNames: { root: 'wanpan-111' },
styles: { root: { background: 'red' } },
content: 'Avatar.Group',
open: true,
},

View File

@ -121,7 +121,7 @@ const Group: React.FC<GroupProps> = (props) => {
const mergeProps = {
content: childrenHidden,
...max?.popover,
overlayClassName: classNames(`${groupPrefixCls}-popover`, max?.popover?.overlayClassName),
classNames: { root: classNames(`${groupPrefixCls}-popover`, max?.popover?.classNames?.root) },
placement: mergePopoverPlacement,
trigger: mergePopoverTrigger,
};

View File

@ -23,7 +23,7 @@ const InnerLoadingIcon = forwardRef<HTMLSpanElement, InnerLoadingIconProps>((pro
);
});
export type LoadingIconProps = {
export type DefaultLoadingIconProps = {
prefixCls: string;
existIcon: boolean;
loading?: boolean | object;
@ -44,7 +44,7 @@ const getRealWidth = (node: HTMLElement): React.CSSProperties => ({
transform: 'scale(1)',
});
const LoadingIcon: React.FC<LoadingIconProps> = (props) => {
const DefaultLoadingIcon: React.FC<DefaultLoadingIconProps> = (props) => {
const { prefixCls, loading, existIcon, className, style, mount } = props;
const visible = !!loading;
@ -84,4 +84,4 @@ const LoadingIcon: React.FC<LoadingIconProps> = (props) => {
);
};
export default LoadingIcon;
export default DefaultLoadingIcon;

View File

@ -492,6 +492,162 @@ exports[`renders components/button/demo/color-variant.tsx extend context correct
</span>
</button>
</div>
<div
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-middle"
>
<button
class="ant-btn ant-btn-default ant-btn-color-pink ant-btn-variant-solid ant-btn-sm"
type="button"
>
<span>
Solid
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-pink ant-btn-variant-outlined ant-btn-sm"
type="button"
>
<span>
Outlined
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-pink ant-btn-variant-dashed ant-btn-sm"
type="button"
>
<span>
Dashed
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-pink ant-btn-variant-filled ant-btn-sm"
type="button"
>
<span>
Filled
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-pink ant-btn-variant-text ant-btn-sm"
type="button"
>
<span>
Text
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-pink ant-btn-variant-link ant-btn-sm"
type="button"
>
<span>
Link
</span>
</button>
</div>
<div
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-middle"
>
<button
class="ant-btn ant-btn-default ant-btn-color-purple ant-btn-variant-solid ant-btn-sm"
type="button"
>
<span>
Solid
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-purple ant-btn-variant-outlined ant-btn-sm"
type="button"
>
<span>
Outlined
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-purple ant-btn-variant-dashed ant-btn-sm"
type="button"
>
<span>
Dashed
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-purple ant-btn-variant-filled ant-btn-sm"
type="button"
>
<span>
Filled
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-purple ant-btn-variant-text ant-btn-sm"
type="button"
>
<span>
Text
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-purple ant-btn-variant-link ant-btn-sm"
type="button"
>
<span>
Link
</span>
</button>
</div>
<div
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-middle"
>
<button
class="ant-btn ant-btn-default ant-btn-color-cyan ant-btn-variant-solid ant-btn-sm"
type="button"
>
<span>
Solid
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-cyan ant-btn-variant-outlined ant-btn-sm"
type="button"
>
<span>
Outlined
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-cyan ant-btn-variant-dashed ant-btn-sm"
type="button"
>
<span>
Dashed
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-cyan ant-btn-variant-filled ant-btn-sm"
type="button"
>
<span>
Filled
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-cyan ant-btn-variant-text ant-btn-sm"
type="button"
>
<span>
Text
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-cyan ant-btn-variant-link ant-btn-sm"
type="button"
>
<span>
Link
</span>
</button>
</div>
</div>
`;
@ -743,6 +899,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="large"
/>
@ -762,6 +919,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="default"
/>
@ -781,6 +939,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="small"
/>
@ -1242,6 +1401,236 @@ Array [
</span>
</button>
</div>
<div
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
role="separator"
>
<span
class="ant-divider-inner-text"
>
👇🏻 https://github.com/ant-design/ant-design/issues/52124 👇🏻
</span>
</div>
<div>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg"
style="height: 60px;"
type="button"
>
<span>
without icon
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg"
style="height: 60px;"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="search"
class="anticon anticon-search"
role="img"
>
<svg
aria-hidden="true"
data-icon="search"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
/>
</svg>
</span>
</span>
<span>
with icon
</span>
</button>
</div>
<div
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
role="separator"
>
<span
class="ant-divider-inner-text"
>
👇🏻 https://github.com/ant-design/ant-design/issues/51380 👇🏻
</span>
</div>
<div>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg ant-btn-icon-only"
type="button"
>
<span
class="ant-btn-icon"
>
<svg
class="my-class-name"
fill="none"
height="1em"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 3h7a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-7m0-18H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7m0-18v18"
/>
</svg>
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg"
type="button"
>
<span
class="ant-btn-icon"
>
<svg
fill="none"
height="1em"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 3h7a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-7m0-18H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7m0-18v18"
/>
</svg>
</span>
<span>
custom icon
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg ant-btn-icon-only"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="search"
class="anticon anticon-search"
role="img"
>
<svg
aria-hidden="true"
data-icon="search"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
/>
</svg>
</span>
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="search"
class="anticon anticon-search"
role="img"
>
<svg
aria-hidden="true"
data-icon="search"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
/>
</svg>
</span>
</span>
<span>
with icon
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg"
type="button"
>
<span>
without icon
</span>
</button>
<span
class="ant-input-group-wrapper ant-input-group-wrapper-lg ant-input-group-wrapper-outlined ant-input-search ant-input-search-large"
style="width: 100px;"
>
<span
class="ant-input-wrapper ant-input-group"
>
<input
class="ant-input ant-input-lg ant-input-outlined"
type="search"
value=""
/>
<span
class="ant-input-group-addon"
>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg ant-btn-icon-only ant-input-search-button"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="search"
class="anticon anticon-search"
role="img"
>
<svg
aria-hidden="true"
data-icon="search"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
/>
</svg>
</span>
</span>
</button>
</span>
</span>
</span>
</div>
<div
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
role="separator"
@ -1976,6 +2365,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="start"
/>
@ -1996,6 +2386,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="end"
/>
@ -2925,6 +3316,37 @@ exports[`renders components/button/demo/loading.tsx extend context correctly 1`]
</span>
</span>
</button>
<button
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-loading"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="sync"
class="anticon anticon-sync anticon-spin"
role="img"
>
<svg
aria-hidden="true"
data-icon="sync"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M168 504.2c1-43.7 10-86.1 26.9-126 17.3-41 42.1-77.7 73.7-109.4S337 212.3 378 195c42.4-17.9 87.4-27 133.9-27s91.5 9.1 133.8 27A341.5 341.5 0 01755 268.8c9.9 9.9 19.2 20.4 27.8 31.4l-60.2 47a8 8 0 003 14.1l175.7 43c5 1.2 9.9-2.6 9.9-7.7l.8-180.9c0-6.7-7.7-10.5-12.9-6.3l-56.4 44.1C765.8 155.1 646.2 92 511.8 92 282.7 92 96.3 275.6 92 503.8a8 8 0 008 8.2h60c4.4 0 7.9-3.5 8-7.8zm756 7.8h-60c-4.4 0-7.9 3.5-8 7.8-1 43.7-10 86.1-26.9 126-17.3 41-42.1 77.8-73.7 109.4A342.45 342.45 0 01512.1 856a342.24 342.24 0 01-243.2-100.8c-9.9-9.9-19.2-20.4-27.8-31.4l60.2-47a8 8 0 00-3-14.1l-175.7-43c-5-1.2-9.9 2.6-9.9 7.7l-.7 181c0 6.7 7.7 10.5 12.9 6.3l56.4-44.1C258.2 868.9 377.8 932 512.2 932c229.2 0 415.5-183.7 419.8-411.8a8 8 0 00-8-8.2z"
/>
</svg>
</span>
</span>
<span>
Loading Icon
</span>
</button>
</div>
<div
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
@ -3004,6 +3426,37 @@ exports[`renders components/button/demo/loading.tsx extend context correctly 1`]
</span>
</span>
</button>
<button
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="poweroff"
class="anticon anticon-poweroff"
role="img"
>
<svg
aria-hidden="true"
data-icon="poweroff"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M705.6 124.9a8 8 0 00-11.6 7.2v64.2c0 5.5 2.9 10.6 7.5 13.6a352.2 352.2 0 0162.2 49.8c32.7 32.8 58.4 70.9 76.3 113.3a355 355 0 0127.9 138.7c0 48.1-9.4 94.8-27.9 138.7a355.92 355.92 0 01-76.3 113.3 353.06 353.06 0 01-113.2 76.4c-43.8 18.6-90.5 28-138.5 28s-94.7-9.4-138.5-28a353.06 353.06 0 01-113.2-76.4A355.92 355.92 0 01184 650.4a355 355 0 01-27.9-138.7c0-48.1 9.4-94.8 27.9-138.7 17.9-42.4 43.6-80.5 76.3-113.3 19-19 39.8-35.6 62.2-49.8 4.7-2.9 7.5-8.1 7.5-13.6V132c0-6-6.3-9.8-11.6-7.2C178.5 195.2 82 339.3 80 506.3 77.2 745.1 272.5 943.5 511.2 944c239 .5 432.8-193.3 432.8-432.4 0-169.2-97-315.7-238.4-386.7zM480 560h64c4.4 0 8-3.6 8-8V88c0-4.4-3.6-8-8-8h-64c-4.4 0-8 3.6-8 8v464c0 4.4 3.6 8 8 8z"
/>
</svg>
</span>
</span>
<span>
Loading Icon
</span>
</button>
</div>
</div>
`;
@ -3192,6 +3645,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="large"
/>
@ -3211,6 +3665,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="default"
/>
@ -3230,6 +3685,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="small"
/>

View File

@ -484,6 +484,162 @@ exports[`renders components/button/demo/color-variant.tsx correctly 1`] = `
</span>
</button>
</div>
<div
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-middle"
>
<button
class="ant-btn ant-btn-default ant-btn-color-pink ant-btn-variant-solid ant-btn-sm"
type="button"
>
<span>
Solid
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-pink ant-btn-variant-outlined ant-btn-sm"
type="button"
>
<span>
Outlined
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-pink ant-btn-variant-dashed ant-btn-sm"
type="button"
>
<span>
Dashed
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-pink ant-btn-variant-filled ant-btn-sm"
type="button"
>
<span>
Filled
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-pink ant-btn-variant-text ant-btn-sm"
type="button"
>
<span>
Text
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-pink ant-btn-variant-link ant-btn-sm"
type="button"
>
<span>
Link
</span>
</button>
</div>
<div
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-middle"
>
<button
class="ant-btn ant-btn-default ant-btn-color-purple ant-btn-variant-solid ant-btn-sm"
type="button"
>
<span>
Solid
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-purple ant-btn-variant-outlined ant-btn-sm"
type="button"
>
<span>
Outlined
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-purple ant-btn-variant-dashed ant-btn-sm"
type="button"
>
<span>
Dashed
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-purple ant-btn-variant-filled ant-btn-sm"
type="button"
>
<span>
Filled
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-purple ant-btn-variant-text ant-btn-sm"
type="button"
>
<span>
Text
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-purple ant-btn-variant-link ant-btn-sm"
type="button"
>
<span>
Link
</span>
</button>
</div>
<div
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-middle"
>
<button
class="ant-btn ant-btn-default ant-btn-color-cyan ant-btn-variant-solid ant-btn-sm"
type="button"
>
<span>
Solid
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-cyan ant-btn-variant-outlined ant-btn-sm"
type="button"
>
<span>
Outlined
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-cyan ant-btn-variant-dashed ant-btn-sm"
type="button"
>
<span>
Dashed
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-cyan ant-btn-variant-filled ant-btn-sm"
type="button"
>
<span>
Filled
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-cyan ant-btn-variant-text ant-btn-sm"
type="button"
>
<span>
Text
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-cyan ant-btn-variant-link ant-btn-sm"
type="button"
>
<span>
Link
</span>
</button>
</div>
</div>
`;
@ -727,6 +883,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="large"
/>
@ -746,6 +903,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="default"
/>
@ -765,6 +923,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="small"
/>
@ -1150,6 +1309,236 @@ Array [
</span>
</button>
</div>
<div
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
role="separator"
>
<span
class="ant-divider-inner-text"
>
👇🏻 https://github.com/ant-design/ant-design/issues/52124 👇🏻
</span>
</div>
<div>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg"
style="height:60px"
type="button"
>
<span>
without icon
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg"
style="height:60px"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="search"
class="anticon anticon-search"
role="img"
>
<svg
aria-hidden="true"
data-icon="search"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
/>
</svg>
</span>
</span>
<span>
with icon
</span>
</button>
</div>
<div
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
role="separator"
>
<span
class="ant-divider-inner-text"
>
👇🏻 https://github.com/ant-design/ant-design/issues/51380 👇🏻
</span>
</div>
<div>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg ant-btn-icon-only"
type="button"
>
<span
class="ant-btn-icon"
>
<svg
class="my-class-name"
fill="none"
height="1em"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 3h7a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-7m0-18H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7m0-18v18"
/>
</svg>
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg"
type="button"
>
<span
class="ant-btn-icon"
>
<svg
fill="none"
height="1em"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 3h7a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-7m0-18H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7m0-18v18"
/>
</svg>
</span>
<span>
custom icon
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg ant-btn-icon-only"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="search"
class="anticon anticon-search"
role="img"
>
<svg
aria-hidden="true"
data-icon="search"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
/>
</svg>
</span>
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="search"
class="anticon anticon-search"
role="img"
>
<svg
aria-hidden="true"
data-icon="search"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
/>
</svg>
</span>
</span>
<span>
with icon
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg"
type="button"
>
<span>
without icon
</span>
</button>
<span
class="ant-input-group-wrapper ant-input-group-wrapper-lg ant-input-group-wrapper-outlined ant-input-search ant-input-search-large"
style="width:100px"
>
<span
class="ant-input-wrapper ant-input-group"
>
<input
class="ant-input ant-input-lg ant-input-outlined"
type="search"
value=""
/>
<span
class="ant-input-group-addon"
>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg ant-btn-icon-only ant-input-search-button"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="search"
class="anticon anticon-search"
role="img"
>
<svg
aria-hidden="true"
data-icon="search"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
/>
</svg>
</span>
</span>
</button>
</span>
</span>
</span>
</div>
<div
class="ant-divider ant-divider-horizontal ant-divider-with-text ant-divider-with-text-center ant-divider-plain"
role="separator"
@ -1800,6 +2189,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="start"
/>
@ -1820,6 +2210,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="end"
/>
@ -2553,6 +2944,37 @@ exports[`renders components/button/demo/loading.tsx correctly 1`] = `
</span>
</span>
</button>
<button
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-loading"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="sync"
class="anticon anticon-sync anticon-spin"
role="img"
>
<svg
aria-hidden="true"
data-icon="sync"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M168 504.2c1-43.7 10-86.1 26.9-126 17.3-41 42.1-77.7 73.7-109.4S337 212.3 378 195c42.4-17.9 87.4-27 133.9-27s91.5 9.1 133.8 27A341.5 341.5 0 01755 268.8c9.9 9.9 19.2 20.4 27.8 31.4l-60.2 47a8 8 0 003 14.1l175.7 43c5 1.2 9.9-2.6 9.9-7.7l.8-180.9c0-6.7-7.7-10.5-12.9-6.3l-56.4 44.1C765.8 155.1 646.2 92 511.8 92 282.7 92 96.3 275.6 92 503.8a8 8 0 008 8.2h60c4.4 0 7.9-3.5 8-7.8zm756 7.8h-60c-4.4 0-7.9 3.5-8 7.8-1 43.7-10 86.1-26.9 126-17.3 41-42.1 77.8-73.7 109.4A342.45 342.45 0 01512.1 856a342.24 342.24 0 01-243.2-100.8c-9.9-9.9-19.2-20.4-27.8-31.4l60.2-47a8 8 0 00-3-14.1l-175.7-43c-5-1.2-9.9 2.6-9.9 7.7l-.7 181c0 6.7 7.7 10.5 12.9 6.3l56.4-44.1C258.2 868.9 377.8 932 512.2 932c229.2 0 415.5-183.7 419.8-411.8a8 8 0 00-8-8.2z"
/>
</svg>
</span>
</span>
<span>
Loading Icon
</span>
</button>
</div>
<div
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
@ -2632,6 +3054,37 @@ exports[`renders components/button/demo/loading.tsx correctly 1`] = `
</span>
</span>
</button>
<button
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="poweroff"
class="anticon anticon-poweroff"
role="img"
>
<svg
aria-hidden="true"
data-icon="poweroff"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M705.6 124.9a8 8 0 00-11.6 7.2v64.2c0 5.5 2.9 10.6 7.5 13.6a352.2 352.2 0 0162.2 49.8c32.7 32.8 58.4 70.9 76.3 113.3a355 355 0 0127.9 138.7c0 48.1-9.4 94.8-27.9 138.7a355.92 355.92 0 01-76.3 113.3 353.06 353.06 0 01-113.2 76.4c-43.8 18.6-90.5 28-138.5 28s-94.7-9.4-138.5-28a353.06 353.06 0 01-113.2-76.4A355.92 355.92 0 01184 650.4a355 355 0 01-27.9-138.7c0-48.1 9.4-94.8 27.9-138.7 17.9-42.4 43.6-80.5 76.3-113.3 19-19 39.8-35.6 62.2-49.8 4.7-2.9 7.5-8.1 7.5-13.6V132c0-6-6.3-9.8-11.6-7.2C178.5 195.2 82 339.3 80 506.3 77.2 745.1 272.5 943.5 511.2 944c239 .5 432.8-193.3 432.8-432.4 0-169.2-97-315.7-238.4-386.7zM480 560h64c4.4 0 8-3.6 8-8V88c0-4.4-3.6-8-8-8h-64c-4.4 0-8 3.6-8 8v464c0 4.4 3.6 8 8 8z"
/>
</svg>
</span>
</span>
<span>
Loading Icon
</span>
</button>
</div>
</div>
`;
@ -2713,6 +3166,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="large"
/>
@ -2732,6 +3186,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="default"
/>
@ -2751,6 +3206,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="small"
/>

View File

@ -2,13 +2,14 @@ import React, { Suspense, useRef, useState } from 'react';
import { SearchOutlined } from '@ant-design/icons';
import { resetWarned } from 'rc-util/lib/warning';
import Button from '..';
import Button, { _ButtonVariantTypes } from '..';
import type { GetRef } from '../../_util/type';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { act, fireEvent, render, waitFakeTimer } from '../../../tests/utils';
import ConfigProvider from '../../config-provider';
import theme from '../../theme';
import { PresetColors } from '../../theme/interface';
import type { BaseButtonProps } from '../button';
describe('Button', () => {
@ -475,6 +476,20 @@ describe('Button', () => {
});
});
it('should render preset colors and variants correctly', () => {
PresetColors.forEach((color) => {
_ButtonVariantTypes.forEach((variant) => {
const { container } = render(
<Button color={color} variant={variant}>
{color}
</Button>,
);
expect(container.firstChild).toHaveClass(`ant-btn-color-${color}`);
expect(container.firstChild).toHaveClass(`ant-btn-variant-${variant}`);
});
});
});
it('autoFocus should work', () => {
const { container } = render(<Button autoFocus>button</Button>);

View File

@ -20,7 +20,7 @@ import type {
} from './buttonHelpers';
import { isTwoCNChar, isUnBorderedButtonVariant, spaceChildren } from './buttonHelpers';
import IconWrapper from './IconWrapper';
import LoadingIcon from './LoadingIcon';
import DefaultLoadingIcon from './DefaultLoadingIcon';
import useStyle from './style';
import Compact from './style/compact';
@ -35,7 +35,7 @@ export interface BaseButtonProps {
shape?: ButtonShape;
size?: SizeType;
disabled?: boolean;
loading?: boolean | { delay?: number };
loading?: boolean | { delay?: number; icon?: React.ReactNode };
prefixCls?: string;
className?: string;
rootClassName?: string;
@ -310,8 +310,12 @@ const InternalCompoundedButton = React.forwardRef<
<IconWrapper prefixCls={prefixCls} className={iconClasses} style={iconStyle}>
{icon}
</IconWrapper>
) : typeof loading === 'object' && loading.icon ? (
<IconWrapper prefixCls={prefixCls} className={iconClasses} style={iconStyle}>
{loading.icon}
</IconWrapper>
) : (
<LoadingIcon
<DefaultLoadingIcon
existIcon={!!icon}
prefixCls={prefixCls}
loading={innerLoading}

View File

@ -1,6 +1,7 @@
import React from 'react';
import { cloneElement, isFragment } from '../_util/reactNode';
import { PresetColors } from '../theme/interface';
import type { BaseButtonProps, LegacyButtonType } from './button';
const rxTwoCNChar = /^[\u4E00-\u9FA5]{2}$/;
@ -106,5 +107,6 @@ export const _ButtonVariantTypes = [
] as const;
export type ButtonVariantType = (typeof _ButtonVariantTypes)[number];
export const _ButtonColorTypes = ['default', 'primary', 'danger'] as const;
export const _ButtonColorTypes = ['default', 'primary', 'danger', ...PresetColors] as const;
export type ButtonColorType = (typeof _ButtonColorTypes)[number];

View File

@ -68,6 +68,67 @@ const App: React.FC = () => {
Link
</Button>
</Flex>
<Flex gap="middle" wrap>
<Button color="pink" variant="solid">
Solid
</Button>
<Button color="pink" variant="outlined">
Outlined
</Button>
<Button color="pink" variant="dashed">
Dashed
</Button>
<Button color="pink" variant="filled">
Filled
</Button>
<Button color="pink" variant="text">
Text
</Button>
<Button color="pink" variant="link">
Link
</Button>
</Flex>
<Flex gap="middle" wrap>
<Button color="purple" variant="solid">
Solid
</Button>
<Button color="purple" variant="outlined">
Outlined
</Button>
<Button color="purple" variant="dashed">
Dashed
</Button>
<Button color="purple" variant="filled">
Filled
</Button>
<Button color="purple" variant="text">
Text
</Button>
<Button color="purple" variant="link">
Link
</Button>
</Flex>
<Flex gap="middle" wrap>
<Button color="cyan" variant="solid">
Solid
</Button>
<Button color="cyan" variant="outlined">
Outlined
</Button>
<Button color="cyan" variant="dashed">
Dashed
</Button>
<Button color="cyan" variant="filled">
Filled
</Button>
<Button color="cyan" variant="text">
Text
</Button>
<Button color="cyan" variant="link">
Link
</Button>
</Flex>
</Flex>
</ConfigProvider>
);

View File

@ -54,7 +54,7 @@ const App: React.FC = () => {
<Flex vertical gap="small">
{/* link color */}
<Flex gap="small">
<ConfigProvider theme={{ token: { colorPrimary: 'red' } }}>
<ConfigProvider theme={{ token: { colorLink: '#FF0000' } }}>
<Button type="link">Link Button</Button>
</ConfigProvider>
<Button type="link">Link Button</Button>

View File

@ -1,7 +1,8 @@
import React from 'react';
import { MinusSquareOutlined, SearchOutlined } from '@ant-design/icons';
import { Button, ConfigProvider, Divider, Flex, Radio, Tooltip } from 'antd';
import { Button, ConfigProvider, Divider, Flex, Radio, Tooltip, Input } from 'antd';
import type { ConfigProviderProps } from 'antd';
import { FiColumns } from 'react-icons/fi';
type SizeType = ConfigProviderProps['componentSize'];
@ -63,6 +64,35 @@ const App: React.FC = () => {
<Button>without icon</Button>
<Button icon={<SearchOutlined />}>with icon</Button>
</div>
<Divider plain>👇🏻 https://github.com/ant-design/ant-design/issues/52124 👇🏻</Divider>
<div>
<Button
style={{
height: 60,
}}
>
without icon
</Button>
<Button
icon={<SearchOutlined />}
style={{
height: 60,
}}
>
with icon
</Button>
</div>
<Divider plain>👇🏻 https://github.com/ant-design/ant-design/issues/51380 👇🏻</Divider>
<div>
<Button size="large" icon={<FiColumns className="my-class-name" />} />
<Button size="large" icon={<FiColumns />}>
custom icon
</Button>
<Button icon={<SearchOutlined />} />
<Button icon={<SearchOutlined />}>with icon</Button>
<Button size="large">without icon</Button>
<Input.Search style={{ width: 100 }} />
</div>
<Divider plain>👇🏻 https://github.com/ant-design/ant-design/issues/51380 👇🏻</Divider>
<Flex
gap="small"

View File

@ -1,7 +1,7 @@
## zh-CN
添加 `loading` 属性即可让按钮处于加载状态,最后三个按钮演示点击后进入加载状态。
添加 `loading` 属性即可让按钮处于加载状态,`loading.icon` 可以自定义加载图标,最后三个按钮演示点击后进入加载状态。
## en-US
A loading indicator can be added to a button by setting the `loading` property on the `Button`.
A loading indicator can be added to a button by setting the `loading` property on the `Button`. The `loading.icon` can be used to customize the loading icon.

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { PoweroffOutlined } from '@ant-design/icons';
import { PoweroffOutlined, SyncOutlined } from '@ant-design/icons';
import { Button, Flex } from 'antd';
const App: React.FC = () => {
@ -31,6 +31,9 @@ const App: React.FC = () => {
Loading
</Button>
<Button type="primary" icon={<PoweroffOutlined />} loading />
<Button type="primary" loading={{ icon: <SyncOutlined spin /> }}>
Loading Icon
</Button>
</Flex>
<Flex gap="small" wrap>
<Button type="primary" loading={loadings[0]} onClick={() => enterLoading(0)}>
@ -58,6 +61,14 @@ const App: React.FC = () => {
loading={loadings[3]}
onClick={() => enterLoading(3)}
/>
<Button
type="primary"
icon={<PoweroffOutlined />}
loading={loadings[3] && { icon: <SyncOutlined spin /> }}
onClick={() => enterLoading(3)}
>
Loading Icon
</Button>
</Flex>
</Flex>
);

View File

@ -63,7 +63,7 @@ Different button styles generated by setting Button properties. The recommended
| autoInsertSpace | We add a space between two Chinese characters by default, which 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 |
| color | Set button color | `default` \| `primary` \| `danger` | - | 5.21.0 |
| color | Set button color | `default` \| `primary` \| `danger` \| [PresetColors](#presetcolors) | - | `default`, `primary` and `danger`: 5.21.0, `PresetColors`: 5.23.0 |
| danger | Syntactic sugar. Set the danger status of button. will follow `color` if provided | boolean | false | |
| disabled | Disabled state of button | boolean | false | |
| ghost | Make background transparent and invert text and border colors | boolean | false | |
@ -71,7 +71,7 @@ Different button styles generated by setting Button properties. The recommended
| htmlType | Set the original html `type` of `button`, see: [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#type) | `submit` \| `reset` \| `button` | `button` | |
| icon | Set the icon component of button | ReactNode | - | |
| iconPosition | Set the icon position of button | `start` \| `end` | `start` | 5.17.0 |
| loading | Set the loading status of button | boolean \| { delay: number } | false | |
| loading | Set the loading status of button | boolean \| { delay: number, icon: ReactNode } | false | icon: 5.23.0 |
| shape | Can be used to set button shape | `default` \| `circle` \| `round` | `default` | |
| size | Set the size of button | `large` \| `middle` \| `small` | `middle` | |
| styles | Semantic DOM style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.4.0 |
@ -82,6 +82,10 @@ Different button styles generated by setting Button properties. The recommended
It accepts all props which native buttons support.
### PresetColors
> type PresetColors = 'blue' | 'purple' | 'cyan' | 'green' | 'magenta' | 'pink' | 'red' | 'orange' | 'yellow' | 'volcano' | 'geekblue' | 'lime' | 'gold';
## Semantic DOM
<code src="./demo/_semantic.tsx" simplify="true"></code>

View File

@ -69,7 +69,7 @@ group:
| autoInsertSpace | 我们默认提供两个汉字之间的空格,可以设置 `autoInsertSpace``false` 关闭 | boolean | `true` | 5.17.0 |
| block | 将按钮宽度调整为其父宽度的选项 | boolean | false | |
| classNames | 语义化结构 class | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.4.0 |
| color | 设置按钮的颜色 | `default` \| `primary` \| `danger` | - | 5.21.0 |
| color | 设置按钮的颜色 | `default` \| `primary` \| `danger` \| [PresetColors](#presetcolors) | - | `default`、`primary` 和 `danger`: 5.21.0, `PresetColors`: 5.23.0 |
| danger | 语法糖,设置危险按钮。当设置 `color` 时会以后者为准 | boolean | false | |
| disabled | 设置按钮失效状态 | boolean | false | |
| ghost | 幽灵属性,使按钮背景透明 | boolean | false | |
@ -77,7 +77,7 @@ group:
| htmlType | 设置 `button` 原生的 `type` 值,可选值请参考 [HTML 标准](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/button#type) | `submit` \| `reset` \| `button` | `button` | |
| icon | 设置按钮的图标组件 | ReactNode | - | |
| iconPosition | 设置按钮图标组件的位置 | `start` \| `end` | `start` | 5.17.0 |
| loading | 设置按钮载入状态 | boolean \| { delay: number } | false | |
| loading | 设置按钮载入状态 | boolean \| { delay: number, icon: ReactNode } | false | icon: 5.23.0 |
| shape | 设置按钮形状 | `default` \| `circle` \| `round` | `default` | |
| size | 设置按钮大小 | `large` \| `middle` \| `small` | `middle` | |
| styles | 语义化结构 style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.4.0 |
@ -88,6 +88,10 @@ group:
支持原生 button 的其他所有属性。
### PresetColors
> type PresetColors = 'blue' | 'purple' | 'cyan' | 'green' | 'magenta' | 'pink' | 'red' | 'orange' | 'yellow' | 'volcano' | 'geekblue' | 'lime' | 'gold';
## Semantic DOM
<code src="./demo/_semantic.tsx" simplify="true"></code>

View File

@ -1,8 +1,9 @@
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
import { unit } from '@ant-design/cssinjs';
import { genFocusStyle } from '../../style';
import type { GenerateStyle } from '../../theme/internal';
import { genFocusStyle, resetIcon } from '../../style';
import { PresetColors } from '../../theme/interface';
import type { GenerateStyle, PresetColorKey } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import type { ButtonVariantType } from '../buttonHelpers';
import genGroupStyle from './group';
@ -48,15 +49,8 @@ const genSharedButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token): CSS
pointerEvents: 'none',
},
'> span:not(:only-child)': {
display: 'inline-flex',
alignSelf: 'baseline',
},
[`> span${componentCls}-icon, > span${iconCls}`]: {
display: 'inline-flex',
alignSelf: 'center',
},
// https://github.com/ant-design/ant-design/issues/51380
[`${componentCls}-icon > svg`]: resetIcon(),
'> a': {
color: 'currentColor',
@ -305,6 +299,95 @@ const genTextLinkButtonStyle = (
});
// =============================== Color ==============================
const genPresetColorStyle: GenerateStyle<ButtonToken, CSSObject> = (token) => {
const { componentCls } = token;
return PresetColors.reduce<CSSObject>((prev: CSSObject, colorKey: PresetColorKey) => {
const darkColor = token[`${colorKey}6`];
const lightColor = token[`${colorKey}1`];
const hoverColor = token[`${colorKey}5`];
const lightHoverColor = token[`${colorKey}2`];
const lightBorderColor = token[`${colorKey}3`];
const activeColor = token[`${colorKey}7`];
const boxShadow = `0 ${token.controlOutlineWidth} 0 ${token[`${colorKey}1`]}`;
return {
...prev,
[`&${componentCls}-color-${colorKey}`]: {
color: darkColor,
boxShadow,
...genSolidButtonStyle(
token,
token.colorTextLightSolid,
darkColor,
{
background: hoverColor,
},
{
background: activeColor,
},
),
...genOutlinedDashedButtonStyle(
token,
darkColor,
token.colorBgContainer,
{
color: hoverColor,
borderColor: hoverColor,
background: token.colorBgContainer,
},
{
color: activeColor,
borderColor: activeColor,
background: token.colorBgContainer,
},
),
...genDashedButtonStyle(token),
...genFilledButtonStyle(
token,
lightColor,
{
background: lightHoverColor,
},
{
background: lightBorderColor,
},
),
...genTextLinkButtonStyle(
token,
darkColor,
'link',
{
color: hoverColor,
},
{
color: activeColor,
},
),
...genTextLinkButtonStyle(
token,
darkColor,
'text',
{
color: hoverColor,
background: lightColor,
},
{
color: activeColor,
background: lightBorderColor,
},
),
},
};
}, {});
};
const genDefaultButtonStyle: GenerateStyle<ButtonToken, CSSObject> = (token) => ({
color: token.defaultColor,
@ -520,6 +603,8 @@ const genColorButtonStyle: GenerateStyle<ButtonToken> = (token) => {
[`${componentCls}-color-default`]: genDefaultButtonStyle(token),
[`${componentCls}-color-primary`]: genPrimaryButtonStyle(token),
[`${componentCls}-color-dangerous`]: genDangerousStyle(token),
...genPresetColorStyle(token),
};
};
@ -593,7 +678,6 @@ const genButtonStyle = (token: ButtonToken, prefixCls = ''): CSSInterpolation =>
componentCls,
controlHeight,
fontSize,
lineHeight,
borderRadius,
buttonPaddingHorizontal,
iconCls,
@ -605,7 +689,6 @@ const genButtonStyle = (token: ButtonToken, prefixCls = ''): CSSInterpolation =>
{
[prefixCls]: {
fontSize,
lineHeight,
height: controlHeight,
padding: `${unit(buttonPaddingVertical!)} ${unit(buttonPaddingHorizontal!)}`,
borderRadius,
@ -615,6 +698,7 @@ const genButtonStyle = (token: ButtonToken, prefixCls = ''): CSSInterpolation =>
[iconCls]: {
fontSize: buttonIconOnlyFontSize,
verticalAlign: 'calc(-0.125em - 1px)',
},
},
},
@ -632,7 +716,6 @@ const genButtonStyle = (token: ButtonToken, prefixCls = ''): CSSInterpolation =>
const genSizeBaseButtonStyle: GenerateStyle<ButtonToken> = (token) => {
const baseToken = mergeToken<ButtonToken>(token, {
fontSize: token.contentFontSize,
lineHeight: token.contentLineHeight,
});
return genButtonStyle(baseToken, token.componentCls);
};
@ -641,10 +724,9 @@ const genSizeSmallButtonStyle: GenerateStyle<ButtonToken> = (token) => {
const smallToken = mergeToken<ButtonToken>(token, {
controlHeight: token.controlHeightSM,
fontSize: token.contentFontSizeSM,
lineHeight: token.contentLineHeightSM,
padding: token.paddingXS,
buttonPaddingHorizontal: token.paddingInlineSM,
buttonPaddingVertical: token.paddingBlockSM,
buttonPaddingVertical: 0,
borderRadius: token.borderRadiusSM,
buttonIconOnlyFontSize: token.onlyIconSizeSM,
});
@ -656,9 +738,8 @@ const genSizeLargeButtonStyle: GenerateStyle<ButtonToken> = (token) => {
const largeToken = mergeToken<ButtonToken>(token, {
controlHeight: token.controlHeightLG,
fontSize: token.contentFontSizeLG,
lineHeight: token.contentLineHeightLG,
buttonPaddingHorizontal: token.paddingInlineLG,
buttonPaddingVertical: token.paddingBlockLG,
buttonPaddingVertical: 0,
borderRadius: token.borderRadiusLG,
buttonIconOnlyFontSize: token.onlyIconSizeLG,
});

View File

@ -239,11 +239,11 @@ export interface ButtonToken extends FullToken<'Button'> {
export const prepareToken: (token: Parameters<GenStyleFn<'Button'>>[0]) => ButtonToken = (
token,
) => {
const { paddingInline, onlyIconSize, paddingBlock } = token;
const { paddingInline, onlyIconSize } = token;
const buttonToken = mergeToken<ButtonToken>(token, {
buttonPaddingHorizontal: paddingInline,
buttonPaddingVertical: paddingBlock,
buttonPaddingVertical: 0,
buttonIconOnlyFontSize: onlyIconSize,
});

File diff suppressed because it is too large Load Diff

View File

@ -147,6 +147,7 @@ exports[`Calendar Calendar MonthSelect should display correct label 1`] = `
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -166,6 +167,7 @@ exports[`Calendar Calendar MonthSelect should display correct label 1`] = `
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -1099,6 +1101,7 @@ exports[`Calendar Calendar should support locale 1`] = `
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -1118,6 +1121,7 @@ exports[`Calendar Calendar should support locale 1`] = `
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -2051,6 +2055,7 @@ exports[`Calendar rtl render component should be rendered correctly in RTL direc
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -2070,6 +2075,7 @@ exports[`Calendar rtl render component should be rendered correctly in RTL direc
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -3003,6 +3009,7 @@ exports[`Calendar support Calendar.generateCalendar 1`] = `
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -3022,6 +3029,7 @@ exports[`Calendar support Calendar.generateCalendar 1`] = `
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="year"
/>

View File

@ -0,0 +1,7 @@
## zh-CN
通过将 `showWeek` 属性设置为 `true`,在全屏日历中显示周数。
## en-US
Show week number in fullscreen calendar by setting `showWeek` prop to `true`.

View File

@ -0,0 +1,12 @@
import React from 'react';
import { Calendar } from 'antd';
const App: React.FC = () => (
<>
<Calendar fullscreen showWeek />
<br />
<Calendar fullscreen={false} showWeek />
</>
);
export default App;

View File

@ -49,6 +49,7 @@ export interface CalendarProps<DateType> {
defaultValue?: DateType;
mode?: CalendarMode;
fullscreen?: boolean;
showWeek?: boolean;
onChange?: (date: DateType) => void;
onPanelChange?: (date: DateType, mode: CalendarMode) => void;
onSelect?: (date: DateType, selectInfo: SelectInfo) => void;
@ -89,6 +90,7 @@ const generateCalendar = <DateType extends AnyObject>(generateConfig: GenerateCo
mode,
validRange,
fullscreen = true,
showWeek,
onChange,
onPanelChange,
onSelect,
@ -299,6 +301,7 @@ const generateCalendar = <DateType extends AnyObject>(generateConfig: GenerateCo
picker={panelMode}
disabledDate={mergedDisabledDate}
hideHeader
showWeek={showWeek}
/>
</div>,
);

View File

@ -19,6 +19,7 @@ When data is in the form of dates, such as schedules, timetables, prices calenda
<code src="./demo/card.tsx" clientOnly>Card</code>
<code src="./demo/select.tsx" clientOnly>Selectable Calendar</code>
<code src="./demo/lunar.tsx" clientOnly>Lunar Calendar</code>
<code src="./demo/week.tsx" clientOnly version="5.23.0">Show Week</code>
<code src="./demo/customize-header.tsx" clientOnly>Customize Header</code>
<code src="./demo/component-token.tsx" debug>Component Token</code>
@ -45,7 +46,8 @@ Common props ref[Common props](/docs/react/common-props)
| defaultValue | The date selected by default | [dayjs](https://day.js.org/) | - | |
| disabledDate | Function that specifies the dates that cannot be selected, `currentDate` is same dayjs object as `value` prop which you shouldn't mutate it](https://github.com/ant-design/ant-design/issues/30987) | (currentDate: Dayjs) => boolean | - | |
| fullscreen | Whether to display in full-screen | boolean | true | |
| headerRender | Render custom header in panel | function(object:{value: Dayjs, type: string, onChange: f(), onTypeChange: f()}) | - | |
| showWeek | Whether to display week number | boolean | false | 5.23.0 |
| headerRender | Render custom header in panel | function(object:{value: Dayjs, type: 'year' \| 'month', onChange: f(), onTypeChange: f()}) | - | |
| locale | The calendar's locale | object | [(default)](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) | |
| mode | The display mode of the calendar | `month` \| `year` | `month` | |
| validRange | To set valid range | \[[dayjs](https://day.js.org/), [dayjs](https://day.js.org/)] | - | |

View File

@ -1,7 +1,7 @@
import type { Dayjs } from 'dayjs';
import dayjsGenerateConfig from 'rc-picker/lib/generate/dayjs';
import type { CalendarProps } from './generateCalendar';
import type { CalendarMode, CalendarProps } from './generateCalendar';
import generateCalendar from './generateCalendar';
const Calendar = generateCalendar<Dayjs>(dayjsGenerateConfig);
@ -12,5 +12,5 @@ export type CalendarType = typeof Calendar & {
(Calendar as CalendarType).generateCalendar = generateCalendar;
export type { CalendarProps };
export type { CalendarMode, CalendarProps };
export default Calendar as CalendarType;

View File

@ -20,6 +20,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*-p-wQLik200AAA
<code src="./demo/card.tsx" clientOnly>卡片模式</code>
<code src="./demo/select.tsx" clientOnly>选择功能</code>
<code src="./demo/lunar.tsx" clientOnly>农历日历</code>
<code src="./demo/week.tsx" clientOnly version="5.23.0">周数</code>
<code src="./demo/customize-header.tsx" clientOnly>自定义头部</code>
<code src="./demo/component-token.tsx" debug>组件 Token</code>
@ -46,7 +47,8 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*-p-wQLik200AAA
| defaultValue | 默认展示的日期 | [dayjs](https://day.js.org/) | - | |
| disabledDate | 不可选择的日期,参数为当前 `value`,注意使用时[不要直接修改](https://github.com/ant-design/ant-design/issues/30987) | (currentDate: Dayjs) => boolean | - | |
| fullscreen | 是否全屏显示 | boolean | true | |
| headerRender | 自定义头部内容 | function(object:{value: Dayjs, type: string, onChange: f(), onTypeChange: f()}) | - | |
| showWeek | 是否显示周数列 | boolean | false | 5.23.0 |
| headerRender | 自定义头部内容 | function(object:{value: Dayjs, type: 'year' \| 'month', onChange: f(), onTypeChange: f()}) | - | |
| locale | 国际化配置 | object | [(默认配置)](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) | |
| mode | 初始模式 | `month` \| `year` | `month` | |
| validRange | 设置可以显示的日期 | \[[dayjs](https://day.js.org/), [dayjs](https://day.js.org/)] | - | |

View File

@ -149,6 +149,18 @@ export const genCalendarStyles = (token: CalendarToken): CSSObject => {
},
},
},
[`${componentCls}-cell-week ${componentCls}-cell-inner`]: {
display: 'block',
borderRadius: 0,
borderTop: `${unit(token.lineWidthBold)} ${token.lineType} ${token.colorSplit}`,
width: '100%',
height: token
.calc(token.dateValueHeight)
.add(token.dateContentHeight)
.add(token.calc(token.paddingXS).div(2))
.add(token.lineWidthBold)
.equal(),
},
[`${componentCls}-cell`]: {
'&::before': {
display: 'none',

View File

@ -160,6 +160,7 @@ Array [
class="ant-tabs ant-tabs-top ant-tabs-large ant-card-head-tabs"
>
<div
aria-orientation="horizontal"
class="ant-tabs-nav"
role="tablist"
>
@ -195,7 +196,7 @@ Array [
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-tab2"
role="tab"
tabindex="0"
tabindex="-1"
>
tab2
</div>
@ -1127,6 +1128,7 @@ Array [
class="ant-tabs ant-tabs-top ant-tabs-large ant-card-head-tabs"
>
<div
aria-orientation="horizontal"
class="ant-tabs-nav"
role="tablist"
>
@ -1162,7 +1164,7 @@ Array [
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-tab2"
role="tab"
tabindex="0"
tabindex="-1"
>
tab2
</div>
@ -1267,6 +1269,7 @@ Array [
class="ant-tabs ant-tabs-top ant-tabs-middle ant-card-head-tabs"
>
<div
aria-orientation="horizontal"
class="ant-tabs-nav"
role="tablist"
>
@ -1287,7 +1290,7 @@ Array [
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-article"
role="tab"
tabindex="0"
tabindex="-1"
>
article
</div>
@ -1317,7 +1320,7 @@ Array [
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-project"
role="tab"
tabindex="0"
tabindex="-1"
>
project
</div>

View File

@ -156,6 +156,7 @@ Array [
class="ant-tabs ant-tabs-top ant-tabs-large ant-card-head-tabs"
>
<div
aria-orientation="horizontal"
class="ant-tabs-nav"
role="tablist"
>
@ -187,7 +188,7 @@ Array [
aria-selected="false"
class="ant-tabs-tab-btn"
role="tab"
tabindex="0"
tabindex="-1"
>
tab2
</div>
@ -1084,6 +1085,7 @@ Array [
class="ant-tabs ant-tabs-top ant-tabs-large ant-card-head-tabs"
>
<div
aria-orientation="horizontal"
class="ant-tabs-nav"
role="tablist"
>
@ -1115,7 +1117,7 @@ Array [
aria-selected="false"
class="ant-tabs-tab-btn"
role="tab"
tabindex="0"
tabindex="-1"
>
tab2
</div>
@ -1201,6 +1203,7 @@ Array [
class="ant-tabs ant-tabs-top ant-tabs-middle ant-card-head-tabs"
>
<div
aria-orientation="horizontal"
class="ant-tabs-nav"
role="tablist"
>
@ -1219,7 +1222,7 @@ Array [
aria-selected="false"
class="ant-tabs-tab-btn"
role="tab"
tabindex="0"
tabindex="-1"
>
article
</div>
@ -1245,7 +1248,7 @@ Array [
aria-selected="false"
class="ant-tabs-tab-btn"
role="tab"
tabindex="0"
tabindex="-1"
>
project
</div>

View File

@ -14,6 +14,7 @@ exports[`Card correct pass tabList props 1`] = `
class="ant-tabs ant-tabs-top ant-tabs-editable ant-tabs-large ant-tabs-card ant-tabs-editable-card ant-card-head-tabs"
>
<div
aria-orientation="horizontal"
class="ant-tabs-nav"
role="tablist"
>
@ -76,14 +77,14 @@ exports[`Card correct pass tabList props 1`] = `
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-deprecated"
role="tab"
tabindex="0"
tabindex="-1"
>
Deprecated
</div>
<button
aria-label="remove"
class="ant-tabs-tab-remove"
tabindex="0"
tabindex="-1"
type="button"
>
<span
@ -133,7 +134,7 @@ exports[`Card correct pass tabList props 1`] = `
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-notClosable"
role="tab"
tabindex="0"
tabindex="-1"
>
NotClosable
</div>

View File

@ -59,11 +59,11 @@ const App: React.FC = () => {
<SemanticPreview
semantics={[
{ name: 'header', desc: locale.header, version: '5.14.0' },
{ name: 'body', desc: locale.body, version: '5.14.0' },
{ name: 'extra', desc: locale.extra, version: '5.14.0' },
{ name: 'title', desc: locale.title, version: '5.14.0' },
{ name: 'actions', desc: locale.actions, version: '5.14.0' },
{ name: 'extra', desc: locale.extra, version: '5.14.0' },
{ name: 'cover', desc: locale.cover, version: '5.14.0' },
{ name: 'body', desc: locale.body, version: '5.14.0' },
{ name: 'actions', desc: locale.actions, version: '5.14.0' },
]}
>
<BlockCard>

View File

@ -8,6 +8,10 @@ export default () => (
components: {
Card: {
headerBg: '#e6f4ff',
bodyPaddingSM: 22,
headerPaddingSM: 20,
headerPadding: 18,
bodyPadding: 26,
headerFontSize: 20,
headerFontSizeSM: 20,
headerHeight: 60,

View File

@ -31,6 +31,26 @@ export interface ComponentToken {
* @descEN Height of small card header
*/
headerHeightSM: number | string;
/**
* @desc
* @descEN Padding of small card body
*/
bodyPaddingSM: number;
/**
* @desc
* @descEN Padding of small card head
*/
headerPaddingSM: number;
/**
* @desc
* @descEN Padding of card body
*/
bodyPadding: number;
/**
* @desc
* @descEN Padding of card head
*/
headerPadding: number;
/**
* @desc
* @descEN Background color of card actions
@ -64,11 +84,6 @@ interface CardToken extends FullToken<'Card'> {
* @descEN Padding of card header
*/
cardHeadPadding: number;
/**
* @desc
* @descEN Padding of small card
*/
cardPaddingSM: number;
/**
* @desc
* @descEN Padding of base card
@ -85,7 +100,7 @@ interface CardToken extends FullToken<'Card'> {
// ============================== Head ==============================
const genCardHeadStyle: GenerateStyle<CardToken> = (token): CSSObject => {
const { antCls, componentCls, headerHeight, cardPaddingBase, tabsMarginBottom } = token;
const { antCls, componentCls, headerHeight, headerPadding, tabsMarginBottom } = token;
return {
display: 'flex',
@ -93,7 +108,7 @@ const genCardHeadStyle: GenerateStyle<CardToken> = (token): CSSObject => {
flexDirection: 'column',
minHeight: headerHeight,
marginBottom: -1, // Fix card grid overflow bug: https://gw.alipayobjects.com/zos/rmsportal/XonYxBikwpgbqIQBeuhk.png
padding: `0 ${unit(cardPaddingBase)}`,
padding: `0 ${unit(headerPadding)}`,
color: token.colorTextHeading,
fontWeight: token.fontWeightStrong,
fontSize: token.headerFontSize,
@ -259,11 +274,11 @@ const genCardMetaStyle: GenerateStyle<CardToken> = (token): CSSObject => ({
// ============================== Inner ==============================
const genCardTypeInnerStyle: GenerateStyle<CardToken> = (token): CSSObject => {
const { componentCls, cardPaddingBase, colorFillAlter } = token;
const { componentCls, colorFillAlter, headerPadding, bodyPadding } = token;
return {
[`${componentCls}-head`]: {
padding: `0 ${unit(cardPaddingBase)}`,
padding: `0 ${unit(headerPadding)}`,
background: colorFillAlter,
'&-title': {
@ -272,7 +287,7 @@ const genCardTypeInnerStyle: GenerateStyle<CardToken> = (token): CSSObject => {
},
[`${componentCls}-body`]: {
padding: `${unit(token.padding)} ${unit(cardPaddingBase)}`,
padding: `${unit(token.padding)} ${unit(bodyPadding)}`,
},
};
};
@ -298,7 +313,7 @@ const genCardStyle: GenerateStyle<CardToken> = (token): CSSObject => {
cardHeadPadding,
colorBorderSecondary,
boxShadowTertiary,
cardPaddingBase,
bodyPadding,
extraColor,
} = token;
@ -325,7 +340,7 @@ const genCardStyle: GenerateStyle<CardToken> = (token): CSSObject => {
},
[`${componentCls}-body`]: {
padding: cardPaddingBase,
padding: bodyPadding,
borderRadius: `0 0 ${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)}`,
...clearFix(),
},
@ -400,13 +415,13 @@ const genCardStyle: GenerateStyle<CardToken> = (token): CSSObject => {
// ============================== Size ==============================
const genCardSizeStyle: GenerateStyle<CardToken> = (token): CSSObject => {
const { componentCls, cardPaddingSM, headerHeightSM, headerFontSizeSM } = token;
const { componentCls, bodyPaddingSM, headerPaddingSM, headerHeightSM, headerFontSizeSM } = token;
return {
[`${componentCls}-small`]: {
[`> ${componentCls}-head`]: {
minHeight: headerHeightSM,
padding: `0 ${unit(cardPaddingSM)}`,
padding: `0 ${unit(headerPaddingSM)}`,
fontSize: headerFontSizeSM,
[`> ${componentCls}-head-wrapper`]: {
@ -417,7 +432,7 @@ const genCardSizeStyle: GenerateStyle<CardToken> = (token): CSSObject => {
},
[`> ${componentCls}-body`]: {
padding: cardPaddingSM,
padding: bodyPaddingSM,
},
},
[`${componentCls}-small${componentCls}-contain-tabs`]: {
@ -442,6 +457,10 @@ export const prepareComponentToken: GetDefaultToken<'Card'> = (token) => ({
actionsLiMargin: `${token.paddingSM}px 0`,
tabsMarginBottom: -token.padding - token.lineWidth,
extraColor: token.colorText,
bodyPaddingSM: 12, // Fixed padding.
headerPaddingSM: 12,
bodyPadding: token.bodyPadding ?? token.paddingLG,
headerPadding: token.headerPadding ?? token.paddingLG,
});
// ============================== Export ==============================
@ -453,7 +472,6 @@ export default genStyleHooks(
cardHeadPadding: token.padding,
cardPaddingBase: token.paddingLG,
cardActionsIconSize: token.fontSize,
cardPaddingSM: 12, // Fixed padding.
});
return [

View File

@ -1158,6 +1158,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="top"
/>
@ -1177,6 +1178,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="bottom"
/>
@ -1196,6 +1198,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="left"
/>
@ -1215,6 +1218,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="right"
/>

View File

@ -1147,6 +1147,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="top"
/>
@ -1166,6 +1167,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="bottom"
/>
@ -1185,6 +1187,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="left"
/>
@ -1204,6 +1207,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="right"
/>

View File

@ -310,6 +310,162 @@ exports[`renders components/cascader/demo/change-on-select.tsx extend context co
exports[`renders components/cascader/demo/change-on-select.tsx extend context correctly 2`] = `[]`;
exports[`renders components/cascader/demo/component-token.tsx extend context correctly 1`] = `
<div
class="ant-select ant-cascader ant-select-outlined ant-select-single ant-select-allow-clear ant-select-show-arrow"
>
<div
class="ant-select-selector"
>
<span
class="ant-select-selection-wrap"
>
<span
class="ant-select-selection-search"
>
<input
aria-autocomplete="list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="false"
aria-haspopup="listbox"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="ant-select-selection-search-input"
id="rc_select_TEST_OR_SSR"
readonly=""
role="combobox"
style="opacity: 0;"
type="search"
unselectable="on"
value=""
/>
</span>
<span
class="ant-select-selection-placeholder"
>
Please select
</span>
</span>
</div>
<div
class="ant-select-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up ant-cascader-dropdown ant-select-dropdown-placement-bottomLeft"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box; min-width: auto;"
>
<div>
<div
class="ant-cascader-menus"
>
<ul
class="ant-cascader-menu"
role="menu"
>
<li
aria-checked="false"
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
data-path-key="zhejiang"
role="menuitemcheckbox"
title="Zhejiang"
>
<div
class="ant-cascader-menu-item-content"
>
Zhejiang
</div>
<div
class="ant-cascader-menu-item-expand-icon"
>
<span
aria-label="right"
class="anticon anticon-right"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</div>
</li>
<li
aria-checked="false"
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
data-path-key="jiangsu"
role="menuitemcheckbox"
title="Jiangsu"
>
<div
class="ant-cascader-menu-item-content"
>
Jiangsu
</div>
<div
class="ant-cascader-menu-item-expand-icon"
>
<span
aria-label="right"
class="anticon anticon-right"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</div>
</li>
</ul>
</div>
</div>
</div>
<span
aria-hidden="true"
class="ant-select-arrow"
style="user-select: none;"
unselectable="on"
>
<span
aria-label="down"
class="anticon anticon-down ant-select-suffix"
role="img"
>
<svg
aria-hidden="true"
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</span>
</div>
`;
exports[`renders components/cascader/demo/component-token.tsx extend context correctly 2`] = `[]`;
exports[`renders components/cascader/demo/custom-dropdown.tsx extend context correctly 1`] = `
<div
class="ant-select ant-cascader ant-select-outlined ant-select-single ant-select-allow-clear ant-select-show-arrow"
@ -2043,6 +2199,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="topLeft"
/>
@ -2062,6 +2219,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="topRight"
/>
@ -2081,6 +2239,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="bottomLeft"
/>
@ -2100,6 +2259,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="bottomRight"
/>

View File

@ -128,6 +128,71 @@ exports[`renders components/cascader/demo/change-on-select.tsx correctly 1`] = `
</div>
`;
exports[`renders components/cascader/demo/component-token.tsx correctly 1`] = `
<div
class="ant-select ant-cascader ant-select-outlined ant-select-single ant-select-allow-clear ant-select-show-arrow"
>
<div
class="ant-select-selector"
>
<span
class="ant-select-selection-wrap"
>
<span
class="ant-select-selection-search"
>
<input
aria-autocomplete="list"
aria-controls="undefined_list"
aria-expanded="false"
aria-haspopup="listbox"
aria-owns="undefined_list"
autocomplete="off"
class="ant-select-selection-search-input"
readonly=""
role="combobox"
style="opacity:0"
type="search"
unselectable="on"
value=""
/>
</span>
<span
class="ant-select-selection-placeholder"
>
Please select
</span>
</span>
</div>
<span
aria-hidden="true"
class="ant-select-arrow"
style="user-select:none;-webkit-user-select:none"
unselectable="on"
>
<span
aria-label="down"
class="anticon anticon-down ant-select-suffix"
role="img"
>
<svg
aria-hidden="true"
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
</span>
</div>
`;
exports[`renders components/cascader/demo/custom-dropdown.tsx correctly 1`] = `
<div
class="ant-select ant-cascader ant-select-outlined ant-select-single ant-select-allow-clear ant-select-show-arrow"
@ -1022,6 +1087,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="topLeft"
/>
@ -1041,6 +1107,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="topRight"
/>
@ -1060,6 +1127,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="bottomLeft"
/>
@ -1079,6 +1147,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="bottomRight"
/>

View File

@ -0,0 +1,7 @@
## zh-CN
组件 Token
## en-US
Component Token

View File

@ -0,0 +1,64 @@
import React from 'react';
import type { CascaderProps } from 'antd';
import { Cascader, ConfigProvider } from 'antd';
interface Option {
value: string;
label: string;
children?: Option[];
}
const options: Option[] = [
{
value: 'zhejiang',
label: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
children: [
{
value: 'xihu',
label: 'West Lake',
},
],
},
],
},
{
value: 'jiangsu',
label: 'Jiangsu',
children: [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
},
],
},
],
},
];
const onChange: CascaderProps<Option>['onChange'] = (value) => {
console.log(value);
};
const App: React.FC = () => (
<ConfigProvider
theme={{
components: {
Cascader: {
optionSelectedColor: 'red',
},
},
}}
>
<Cascader options={options} onChange={onChange} placeholder="Please select" />
</ConfigProvider>
);
export default App;

View File

@ -37,6 +37,7 @@ demo:
<code src="./demo/status.tsx">Status</code>
<code src="./demo/panel.tsx" version=">= 5.10.0">Panel</code>
<code src="./demo/render-panel.tsx" debug>_InternalPanelDoNotUseOrYouWillBeFired</code>
<code src="./demo/component-token.tsx" debug>Component Token</code>
## API

View File

@ -365,9 +365,7 @@ if (process.env.NODE_ENV !== 'production') {
// We don't care debug panel
/* istanbul ignore next */
const PurePanel = genPurePanel(Cascader, undefined, undefined, (props: any) =>
omit(props, ['visible']),
);
const PurePanel = genPurePanel(Cascader, 'dropdownAlign', (props: any) => omit(props, ['visible']));
Cascader.SHOW_PARENT = SHOW_PARENT;
Cascader.SHOW_CHILD = SHOW_CHILD;

View File

@ -38,6 +38,7 @@ demo:
<code src="./demo/status.tsx">自定义状态</code>
<code src="./demo/panel.tsx" version=">= 5.10.0">面板使用</code>
<code src="./demo/render-panel.tsx" debug>_InternalPanelDoNotUseOrYouWillBeFired</code>
<code src="./demo/component-token.tsx" debug>Component Token</code>
## API

View File

@ -92,6 +92,7 @@ const getColumnsStyle: GenerateStyle<CascaderToken> = (token: CascaderToken): CS
[`&-active:not(${cascaderMenuItemCls}-disabled)`]: {
'&, &:hover': {
color: token.optionSelectedColor,
fontWeight: token.optionSelectedFontWeight,
backgroundColor: token.optionSelectedBg,
},

View File

@ -26,6 +26,11 @@ export interface ComponentToken {
* @descEN Background color of selected item
*/
optionSelectedBg: string;
/**
* @desc
* @descEN Text color when option is selected
*/
optionSelectedColor: string;
/**
* @desc
* @descEN Font weight of selected item
@ -100,6 +105,7 @@ export const prepareComponentToken = (token: GlobalToken) => {
optionSelectedFontWeight: token.fontWeightStrong,
optionPadding: `${itemPaddingVertical}px ${token.paddingSM}px`,
menuPadding: token.paddingXXS,
optionSelectedColor: token.colorText,
};
};

View File

@ -727,7 +727,7 @@ exports[`renders components/collapse/demo/custom.tsx correctly 1`] = `
>
<div
class="ant-collapse-item ant-collapse-item-active"
style="margin-bottom:24px;background:rgba(0, 0, 0, 0.02);border-radius:8px;border:none"
style="margin-bottom:24px;background:rgba(0,0,0,0.02);border-radius:8px;border:none"
>
<div
aria-disabled="false"
@ -782,7 +782,7 @@ exports[`renders components/collapse/demo/custom.tsx correctly 1`] = `
</div>
<div
class="ant-collapse-item"
style="margin-bottom:24px;background:rgba(0, 0, 0, 0.02);border-radius:8px;border:none"
style="margin-bottom:24px;background:rgba(0,0,0,0.02);border-radius:8px;border:none"
>
<div
aria-disabled="false"
@ -823,7 +823,7 @@ exports[`renders components/collapse/demo/custom.tsx correctly 1`] = `
</div>
<div
class="ant-collapse-item"
style="margin-bottom:24px;background:rgba(0, 0, 0, 0.02);border-radius:8px;border:none"
style="margin-bottom:24px;background:rgba(0,0,0,0.02);border-radius:8px;border:none"
>
<div
aria-disabled="false"

View File

@ -1,7 +1,7 @@
import type { CSSProperties } from 'react';
import { unit } from '@ant-design/cssinjs';
import { resetComponent, resetIcon } from '../../style';
import { genFocusStyle, resetComponent, resetIcon } from '../../style';
import { genCollapseMotion } from '../../style/motion';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
@ -95,6 +95,14 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
[`& > ${componentCls}-item`]: {
borderBottom: borderBase,
'&:first-child': {
[`
&,
& > ${componentCls}-header`]: {
borderRadius: `${unit(collapsePanelBorderRadius)} ${unit(collapsePanelBorderRadius)} 0 0`,
},
},
'&:last-child': {
[`
&,
@ -115,6 +123,7 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = (token) => {
lineHeight,
cursor: 'pointer',
transition: `all ${motionDurationSlow}, visibility 0s`,
...genFocusStyle(token),
[`> ${componentCls}-header-text`]: {
flex: 'auto',

View File

@ -221,7 +221,7 @@ const ColorPicker: CompoundedComponent = (props) => {
return wrapCSSVar(
<Popover
style={styles?.popup}
overlayInnerStyle={styles?.popupOverlayInner}
styles={{ body: styles?.popupOverlayInner }}
onOpenChange={(visible) => {
if (!visible || !mergedDisabled) {
setPopupOpen(visible);
@ -253,7 +253,7 @@ const ColorPicker: CompoundedComponent = (props) => {
/>
</ContextIsolator>
}
overlayClassName={mergedPopupCls}
classNames={{ root: mergedPopupCls }}
{...popoverProps}
>
{children || (
@ -280,14 +280,15 @@ if (process.env.NODE_ENV !== 'production') {
const PurePanel = genPurePanel(
ColorPicker,
'color-picker',
/* istanbul ignore next */
(prefixCls) => prefixCls,
undefined,
(props: ColorPickerProps) => ({
...props,
placement: 'bottom' as TriggerPlacement,
autoAdjustOverflow: false,
}),
'color-picker',
/* istanbul ignore next */
(prefixCls) => prefixCls,
);
ColorPicker._InternalPanelDoNotUseOrYouWillBeFired = PurePanel;

View File

@ -3981,7 +3981,8 @@ exports[`renders components/color-picker/demo/line-gradient.tsx extend context c
<div
aria-label="segmented control"
class="ant-segmented ant-segmented-sm"
role="listbox"
role="radiogroup"
tabindex="0"
>
<div
class="ant-segmented-group"
@ -3992,12 +3993,12 @@ exports[`renders components/color-picker/demo/line-gradient.tsx extend context c
<input
checked=""
class="ant-segmented-item-input"
name="test-id"
type="radio"
/>
<div
aria-selected="false"
class="ant-segmented-item-label"
role="option"
title="Single"
>
Single
@ -4008,12 +4009,12 @@ exports[`renders components/color-picker/demo/line-gradient.tsx extend context c
>
<input
class="ant-segmented-item-input"
name="test-id"
type="radio"
/>
<div
aria-selected="true"
class="ant-segmented-item-label"
role="option"
title="Gradient"
>
Gradient

View File

@ -12,7 +12,7 @@ import Form from '../../form';
import theme from '../../theme';
import { AggregationColor } from '../color';
import ColorPicker from '../ColorPicker';
import type { ColorPickerProps, ColorValueType } from '../interface';
import type { ColorPickerProps, ColorValueType, PresetsItem } from '../interface';
import { generateColor } from '../util';
function doMouseMove(
@ -178,6 +178,7 @@ describe('ColorPicker', () => {
onChange={handleColorChange}
presets={[
{
key: 'Recommended',
label: 'Recommended',
colors: [
'#000000',
@ -193,6 +194,7 @@ describe('ColorPicker', () => {
],
},
{
key: 'Recent',
label: 'Recent',
colors: [],
},
@ -243,7 +245,8 @@ describe('ColorPicker', () => {
});
describe('preset collapsed', () => {
const recommendedPreset = {
const recommendedPreset: PresetsItem = {
key: 'Recommended',
label: 'Recommended',
colors: ['#f00', '#0f0', '#00f'],
};
@ -263,6 +266,7 @@ describe('ColorPicker', () => {
presets={[
recommendedPreset,
{
key: 'Recent',
label: 'Recent',
colors: ['#f00d', '#0f0d', '#00fd'],
defaultOpen: false,
@ -381,6 +385,7 @@ describe('ColorPicker', () => {
open
presets={[
{
key: 'test',
label: 'test',
colors: ['#0000001A'],
},
@ -955,9 +960,9 @@ describe('ColorPicker', () => {
<ColorPicker
open
presets={[
{ label: <span>aaa</span>, colors: ['#333'], defaultOpen: true },
{ label: <span>bbb</span>, colors: ['#666'], defaultOpen: true },
{ label: <span>ccc</span>, colors: ['#999'], defaultOpen: true },
{ label: <span>aaa</span>, colors: ['#333'], key: 'a', defaultOpen: true },
{ label: <span>bbb</span>, colors: ['#666'], key: 'b', defaultOpen: true },
{ label: <span>ccc</span>, colors: ['#999'], key: 'c', defaultOpen: true },
]}
/>,
);

View File

@ -35,10 +35,10 @@ export const isBright = (value: AggregationColor, bgColorToken: string) => {
return r * 0.299 + g * 0.587 + b * 0.114 > 192;
};
const genCollapsePanelKey = (preset: PresetsItem, index: number) =>
typeof preset.label === 'string' || typeof preset.label === 'number'
? `panel-${preset.label}-${index}`
: `panel-${index}`;
const genCollapsePanelKey = (preset: PresetsItem, index: number) => {
const mergedKey = preset.key ?? index;
return `panel-${mergedKey}`;
};
const ColorPresets: FC<ColorPresetsProps> = ({ prefixCls, presets, value: color, onChange }) => {
const [locale] = useLocale('ColorPicker');
@ -65,7 +65,7 @@ const ColorPresets: FC<ColorPresetsProps> = ({ prefixCls, presets, value: color,
onChange?.(colorValue);
};
const items: CollapseProps['items'] = presetsValue.map((preset, index) => ({
const items = presetsValue.map<NonNullable<CollapseProps['items']>[number]>((preset, index) => ({
key: genCollapsePanelKey(preset, index),
label: <div className={`${colorPresetsPrefixCls}-label`}>{preset?.label}</div>,
children: (

View File

@ -5,11 +5,9 @@ import type { ColorPickerProps } from 'antd';
type Presets = Required<ColorPickerProps>['presets'][number];
const genPresets = (presets = presetPalettes) =>
Object.entries(presets).map<Presets>(([label, colors]) => ({
label,
colors,
}));
function genPresets(presets = presetPalettes) {
return Object.entries(presets).map<Presets>(([label, colors]) => ({ label, colors, key: label }));
}
const HorizontalLayoutDemo = () => {
const { token } = theme.useToken();

View File

@ -5,8 +5,9 @@ import type { ColorPickerProps } from 'antd';
type Presets = Required<ColorPickerProps>['presets'][number];
const genPresets = (presets = presetPalettes) =>
Object.entries(presets).map<Presets>(([label, colors]) => ({ label, colors }));
function genPresets(presets = presetPalettes) {
return Object.entries(presets).map<Presets>(([label, colors]) => ({ label, colors, key: label }));
}
const Demo: React.FC = () => {
const { token } = theme.useToken();

View File

@ -54,7 +54,7 @@ Common props ref[Common props](/docs/react/common-props)
| format | Format of color | `rgb` \| `hex` \| `hsb` | `hex` | |
| mode | Configure single or gradient color | `'single' \| 'gradient' \| ('single' \| 'gradient')[]` | `single` | 5.20.0 |
| open | Whether to show popup | boolean | - | |
| presets | Preset colors | `{ label: ReactNode, colors: Array<string \| Color>, defaultOpen?: boolean }[]` | - | `defaultOpen: 5.11.0` |
| presets | Preset colors | `{ label: ReactNode, colors: Array<string \| Color>, defaultOpen?: boolean, key?: React.Key }[]` | - | `defaultOpen: 5.11.0, key: 5.23.0` |
| placement | Placement of popup | The design of the [placement](/components/tooltip/#api) parameter is the same as the `Tooltips` component. | `bottomLeft` | |
| panelRender | Custom Render Panel | `(panel: React.ReactNode, extra: { components: { Picker: FC; Presets: FC } }) => React.ReactNode` | - | 5.7.0 |
| showText | Show color text | boolean \| `(color: Color) => React.ReactNode` | - | 5.7.0 |

View File

@ -55,7 +55,7 @@ group:
| format | 颜色格式 | `rgb` \| `hex` \| `hsb` | `hex` | |
| mode | 选择器模式,用于配置单色与渐变 | `'single' \| 'gradient' \| ('single' \| 'gradient')[]` | `single` | 5.20.0 |
| open | 是否显示弹出窗口 | boolean | - | |
| presets | 预设的颜色 | `{ label: ReactNode, colors: Array<string \| Color>, defaultOpen?: boolean }[]` | - | `defaultOpen: 5.11.0` |
| presets | 预设的颜色 | `{ label: ReactNode, colors: Array<string \| Color>, defaultOpen?: boolean, key?: React.Key }[]` | - | `defaultOpen: 5.11.0, key: 5.23.0` |
| placement | 弹出窗口的位置 | 同 `Tooltips` 组件的 [placement](/components/tooltip-cn/#api) 参数设计 | `bottomLeft` | |
| panelRender | 自定义渲染面板 | `(panel: React.ReactNode, extra: { components: { Picker: FC; Presets: FC } }) => React.ReactNode` | - | 5.7.0 |
| showText | 显示颜色文本 | boolean \| `(color: Color) => React.ReactNode` | - | 5.7.0 |

View File

@ -1,4 +1,5 @@
import type { CSSProperties, FC, ReactNode } from 'react';
import React from 'react';
import type {
ColorGenInput,
ColorPickerProps as RcColorPickerProps,
@ -33,7 +34,13 @@ export interface PresetsItem {
* @default true
*/
defaultOpen?: boolean;
/**
* The key of the panel
* @since 5.23.0
*/
key?: React.Key;
}
export type TriggerType = 'click' | 'hover';
export type TriggerPlacement = TooltipPlacement; // Alias, to prevent breaking changes.

View File

@ -15,13 +15,10 @@ const defaultReactRender: RenderType = (node, container) => {
// Warning for React 19
if (process.env.NODE_ENV !== 'production') {
const majorVersion = parseInt(React.version.split('.')[0], 10);
const fullKeys = Object.keys(ReactDOM);
warning(
majorVersion < 19 ||
!!(
ReactDOM as typeof ReactDOM & {
createRoot: VoidFunction;
}
).createRoot,
majorVersion < 19 || fullKeys.includes('createRoot'),
'compatible',
'antd v5 support React is 16 ~ 18. see https://u.ant.design/v5-for-19 for compatible.',
);

View File

@ -1755,6 +1755,7 @@ exports[`ConfigProvider components Calendar configProvider 1`] = `
<input
checked=""
class="config-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -1774,6 +1775,7 @@ exports[`ConfigProvider components Calendar configProvider 1`] = `
>
<input
class="config-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -2639,6 +2641,7 @@ exports[`ConfigProvider components Calendar configProvider 1`] = `
>
<input
class="config-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -2659,6 +2662,7 @@ exports[`ConfigProvider components Calendar configProvider 1`] = `
<input
checked=""
class="config-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -3058,6 +3062,7 @@ exports[`ConfigProvider components Calendar configProvider componentDisabled 1`]
checked=""
class="config-radio-button-input"
disabled=""
name="test-id"
type="radio"
value="month"
/>
@ -3078,6 +3083,7 @@ exports[`ConfigProvider components Calendar configProvider componentDisabled 1`]
<input
class="config-radio-button-input"
disabled=""
name="test-id"
type="radio"
value="year"
/>
@ -3945,6 +3951,7 @@ exports[`ConfigProvider components Calendar configProvider componentDisabled 1`]
<input
class="config-radio-button-input"
disabled=""
name="test-id"
type="radio"
value="month"
/>
@ -3966,6 +3973,7 @@ exports[`ConfigProvider components Calendar configProvider componentDisabled 1`]
checked=""
class="config-radio-button-input"
disabled=""
name="test-id"
type="radio"
value="year"
/>
@ -4362,6 +4370,7 @@ exports[`ConfigProvider components Calendar configProvider componentSize large 1
<input
checked=""
class="config-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -4381,6 +4390,7 @@ exports[`ConfigProvider components Calendar configProvider componentSize large 1
>
<input
class="config-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -5246,6 +5256,7 @@ exports[`ConfigProvider components Calendar configProvider componentSize large 1
>
<input
class="config-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -5266,6 +5277,7 @@ exports[`ConfigProvider components Calendar configProvider componentSize large 1
<input
checked=""
class="config-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -5662,6 +5674,7 @@ exports[`ConfigProvider components Calendar configProvider componentSize middle
<input
checked=""
class="config-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -5681,6 +5694,7 @@ exports[`ConfigProvider components Calendar configProvider componentSize middle
>
<input
class="config-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -6546,6 +6560,7 @@ exports[`ConfigProvider components Calendar configProvider componentSize middle
>
<input
class="config-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -6566,6 +6581,7 @@ exports[`ConfigProvider components Calendar configProvider componentSize middle
<input
checked=""
class="config-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -6962,6 +6978,7 @@ exports[`ConfigProvider components Calendar configProvider componentSize small 1
<input
checked=""
class="config-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -6981,6 +6998,7 @@ exports[`ConfigProvider components Calendar configProvider componentSize small 1
>
<input
class="config-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -7846,6 +7864,7 @@ exports[`ConfigProvider components Calendar configProvider componentSize small 1
>
<input
class="config-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -7866,6 +7885,7 @@ exports[`ConfigProvider components Calendar configProvider componentSize small 1
<input
checked=""
class="config-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -8262,6 +8282,7 @@ exports[`ConfigProvider components Calendar normal 1`] = `
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -8281,6 +8302,7 @@ exports[`ConfigProvider components Calendar normal 1`] = `
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -9146,6 +9168,7 @@ exports[`ConfigProvider components Calendar normal 1`] = `
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -9166,6 +9189,7 @@ exports[`ConfigProvider components Calendar normal 1`] = `
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -9562,6 +9586,7 @@ exports[`ConfigProvider components Calendar prefixCls 1`] = `
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -9581,6 +9606,7 @@ exports[`ConfigProvider components Calendar prefixCls 1`] = `
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -10446,6 +10472,7 @@ exports[`ConfigProvider components Calendar prefixCls 1`] = `
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="month"
/>
@ -10466,6 +10493,7 @@ exports[`ConfigProvider components Calendar prefixCls 1`] = `
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="year"
/>
@ -16125,7 +16153,7 @@ exports[`ConfigProvider components Input configProvider 1`] = `
>
<input
class="config-input config-input-outlined"
type="text"
type="search"
value=""
/>
<span
@ -16225,7 +16253,7 @@ exports[`ConfigProvider components Input configProvider componentDisabled 1`] =
<input
class="config-input config-input-disabled config-input-outlined"
disabled=""
type="text"
type="search"
value=""
/>
<span
@ -16326,7 +16354,7 @@ exports[`ConfigProvider components Input configProvider componentSize large 1`]
>
<input
class="config-input config-input-lg config-input-outlined"
type="text"
type="search"
value=""
/>
<span
@ -16424,7 +16452,7 @@ exports[`ConfigProvider components Input configProvider componentSize middle 1`]
>
<input
class="config-input config-input-outlined"
type="text"
type="search"
value=""
/>
<span
@ -16522,7 +16550,7 @@ exports[`ConfigProvider components Input configProvider componentSize small 1`]
>
<input
class="config-input config-input-sm config-input-outlined"
type="text"
type="search"
value=""
/>
<span
@ -16620,7 +16648,7 @@ exports[`ConfigProvider components Input normal 1`] = `
>
<input
class="ant-input ant-input-outlined"
type="text"
type="search"
value=""
/>
<span
@ -16718,7 +16746,7 @@ exports[`ConfigProvider components Input prefixCls 1`] = `
>
<input
class="ant-input ant-input-outlined"
type="text"
type="search"
value=""
/>
<span
@ -22174,6 +22202,7 @@ exports[`ConfigProvider components Radio configProvider 1`] = `
<input
checked=""
class="config-radio-input"
name="test-id"
type="radio"
/>
<span
@ -22197,6 +22226,7 @@ exports[`ConfigProvider components Radio configProvider 1`] = `
<input
checked=""
class="config-radio-button-input"
name="test-id"
type="radio"
/>
<span
@ -22226,6 +22256,7 @@ exports[`ConfigProvider components Radio configProvider componentDisabled 1`] =
checked=""
class="config-radio-input"
disabled=""
name="test-id"
type="radio"
/>
<span
@ -22250,6 +22281,7 @@ exports[`ConfigProvider components Radio configProvider componentDisabled 1`] =
checked=""
class="config-radio-button-input"
disabled=""
name="test-id"
type="radio"
/>
<span
@ -22278,6 +22310,7 @@ exports[`ConfigProvider components Radio configProvider componentSize large 1`]
<input
checked=""
class="config-radio-input"
name="test-id"
type="radio"
/>
<span
@ -22301,6 +22334,7 @@ exports[`ConfigProvider components Radio configProvider componentSize large 1`]
<input
checked=""
class="config-radio-button-input"
name="test-id"
type="radio"
/>
<span
@ -22329,6 +22363,7 @@ exports[`ConfigProvider components Radio configProvider componentSize middle 1`]
<input
checked=""
class="config-radio-input"
name="test-id"
type="radio"
/>
<span
@ -22352,6 +22387,7 @@ exports[`ConfigProvider components Radio configProvider componentSize middle 1`]
<input
checked=""
class="config-radio-button-input"
name="test-id"
type="radio"
/>
<span
@ -22380,6 +22416,7 @@ exports[`ConfigProvider components Radio configProvider componentSize small 1`]
<input
checked=""
class="config-radio-input"
name="test-id"
type="radio"
/>
<span
@ -22403,6 +22440,7 @@ exports[`ConfigProvider components Radio configProvider componentSize small 1`]
<input
checked=""
class="config-radio-button-input"
name="test-id"
type="radio"
/>
<span
@ -22431,6 +22469,7 @@ exports[`ConfigProvider components Radio normal 1`] = `
<input
checked=""
class="ant-radio-input"
name="test-id"
type="radio"
/>
<span
@ -22454,6 +22493,7 @@ exports[`ConfigProvider components Radio normal 1`] = `
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
/>
<span
@ -22482,6 +22522,7 @@ exports[`ConfigProvider components Radio prefixCls 1`] = `
<input
checked=""
class="prefix-Radio-input"
name="test-id"
type="radio"
/>
<span
@ -22505,6 +22546,7 @@ exports[`ConfigProvider components Radio prefixCls 1`] = `
<input
checked=""
class="prefix-Radio-button-input"
name="test-id"
type="radio"
/>
<span
@ -28935,6 +28977,7 @@ exports[`ConfigProvider components Tabs configProvider 1`] = `
class="config-tabs config-tabs-top"
>
<div
aria-orientation="horizontal"
class="config-tabs-nav"
role="tablist"
>
@ -29025,6 +29068,7 @@ exports[`ConfigProvider components Tabs configProvider componentDisabled 1`] = `
class="config-tabs config-tabs-top"
>
<div
aria-orientation="horizontal"
class="config-tabs-nav"
role="tablist"
>
@ -29115,6 +29159,7 @@ exports[`ConfigProvider components Tabs configProvider componentSize large 1`] =
class="config-tabs config-tabs-top config-tabs-large"
>
<div
aria-orientation="horizontal"
class="config-tabs-nav"
role="tablist"
>
@ -29205,6 +29250,7 @@ exports[`ConfigProvider components Tabs configProvider componentSize middle 1`]
class="config-tabs config-tabs-top config-tabs-middle"
>
<div
aria-orientation="horizontal"
class="config-tabs-nav"
role="tablist"
>
@ -29295,6 +29341,7 @@ exports[`ConfigProvider components Tabs configProvider componentSize small 1`] =
class="config-tabs config-tabs-top config-tabs-small"
>
<div
aria-orientation="horizontal"
class="config-tabs-nav"
role="tablist"
>
@ -29385,6 +29432,7 @@ exports[`ConfigProvider components Tabs normal 1`] = `
class="ant-tabs ant-tabs-top"
>
<div
aria-orientation="horizontal"
class="ant-tabs-nav"
role="tablist"
>
@ -29475,6 +29523,7 @@ exports[`ConfigProvider components Tabs prefixCls 1`] = `
class="prefix-Tabs prefix-Tabs-top"
>
<div
aria-orientation="horizontal"
class="prefix-Tabs-nav"
role="tablist"
>
@ -41434,7 +41483,6 @@ exports[`ConfigProvider components Tree configProvider 1`] = `
<div>
<div
class="config-tree config-tree-icon-hide"
role="tree"
>
<div>
<input
@ -41459,6 +41507,7 @@ exports[`ConfigProvider components Tree configProvider 1`] = `
</div>
<div
class="config-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -41470,9 +41519,10 @@ exports[`ConfigProvider components Tree configProvider 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-tree-treenode config-tree-treenode-switcher-close config-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -41499,7 +41549,6 @@ exports[`ConfigProvider components Tree configProvider 1`] = `
</div>
<div
class="config-tree config-tree-block-node config-tree-directory"
role="tree"
>
<div>
<input
@ -41524,6 +41573,7 @@ exports[`ConfigProvider components Tree configProvider 1`] = `
</div>
<div
class="config-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -41535,9 +41585,10 @@ exports[`ConfigProvider components Tree configProvider 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-tree-treenode config-tree-treenode-switcher-close config-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -41592,7 +41643,6 @@ exports[`ConfigProvider components Tree configProvider componentDisabled 1`] = `
<div>
<div
class="config-tree config-tree-icon-hide"
role="tree"
>
<div>
<input
@ -41617,6 +41667,7 @@ exports[`ConfigProvider components Tree configProvider componentDisabled 1`] = `
</div>
<div
class="config-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -41628,9 +41679,10 @@ exports[`ConfigProvider components Tree configProvider componentDisabled 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-tree-treenode config-tree-treenode-switcher-close config-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -41657,7 +41709,6 @@ exports[`ConfigProvider components Tree configProvider componentDisabled 1`] = `
</div>
<div
class="config-tree config-tree-block-node config-tree-directory"
role="tree"
>
<div>
<input
@ -41682,6 +41733,7 @@ exports[`ConfigProvider components Tree configProvider componentDisabled 1`] = `
</div>
<div
class="config-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -41693,9 +41745,10 @@ exports[`ConfigProvider components Tree configProvider componentDisabled 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-tree-treenode config-tree-treenode-switcher-close config-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -41750,7 +41803,6 @@ exports[`ConfigProvider components Tree configProvider componentSize large 1`] =
<div>
<div
class="config-tree config-tree-icon-hide"
role="tree"
>
<div>
<input
@ -41775,6 +41827,7 @@ exports[`ConfigProvider components Tree configProvider componentSize large 1`] =
</div>
<div
class="config-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -41786,9 +41839,10 @@ exports[`ConfigProvider components Tree configProvider componentSize large 1`] =
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-tree-treenode config-tree-treenode-switcher-close config-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -41815,7 +41869,6 @@ exports[`ConfigProvider components Tree configProvider componentSize large 1`] =
</div>
<div
class="config-tree config-tree-block-node config-tree-directory"
role="tree"
>
<div>
<input
@ -41840,6 +41893,7 @@ exports[`ConfigProvider components Tree configProvider componentSize large 1`] =
</div>
<div
class="config-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -41851,9 +41905,10 @@ exports[`ConfigProvider components Tree configProvider componentSize large 1`] =
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-tree-treenode config-tree-treenode-switcher-close config-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -41908,7 +41963,6 @@ exports[`ConfigProvider components Tree configProvider componentSize middle 1`]
<div>
<div
class="config-tree config-tree-icon-hide"
role="tree"
>
<div>
<input
@ -41933,6 +41987,7 @@ exports[`ConfigProvider components Tree configProvider componentSize middle 1`]
</div>
<div
class="config-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -41944,9 +41999,10 @@ exports[`ConfigProvider components Tree configProvider componentSize middle 1`]
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-tree-treenode config-tree-treenode-switcher-close config-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -41973,7 +42029,6 @@ exports[`ConfigProvider components Tree configProvider componentSize middle 1`]
</div>
<div
class="config-tree config-tree-block-node config-tree-directory"
role="tree"
>
<div>
<input
@ -41998,6 +42053,7 @@ exports[`ConfigProvider components Tree configProvider componentSize middle 1`]
</div>
<div
class="config-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -42009,9 +42065,10 @@ exports[`ConfigProvider components Tree configProvider componentSize middle 1`]
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-tree-treenode config-tree-treenode-switcher-close config-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -42066,7 +42123,6 @@ exports[`ConfigProvider components Tree configProvider componentSize small 1`] =
<div>
<div
class="config-tree config-tree-icon-hide"
role="tree"
>
<div>
<input
@ -42091,6 +42147,7 @@ exports[`ConfigProvider components Tree configProvider componentSize small 1`] =
</div>
<div
class="config-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -42102,9 +42159,10 @@ exports[`ConfigProvider components Tree configProvider componentSize small 1`] =
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-tree-treenode config-tree-treenode-switcher-close config-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -42131,7 +42189,6 @@ exports[`ConfigProvider components Tree configProvider componentSize small 1`] =
</div>
<div
class="config-tree config-tree-block-node config-tree-directory"
role="tree"
>
<div>
<input
@ -42156,6 +42213,7 @@ exports[`ConfigProvider components Tree configProvider componentSize small 1`] =
</div>
<div
class="config-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -42167,9 +42225,10 @@ exports[`ConfigProvider components Tree configProvider componentSize small 1`] =
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-tree-treenode config-tree-treenode-switcher-close config-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -42224,7 +42283,6 @@ exports[`ConfigProvider components Tree normal 1`] = `
<div>
<div
class="ant-tree ant-tree-icon-hide"
role="tree"
>
<div>
<input
@ -42249,6 +42307,7 @@ exports[`ConfigProvider components Tree normal 1`] = `
</div>
<div
class="ant-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -42260,9 +42319,10 @@ exports[`ConfigProvider components Tree normal 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="ant-tree-treenode ant-tree-treenode-switcher-close ant-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -42289,7 +42349,6 @@ exports[`ConfigProvider components Tree normal 1`] = `
</div>
<div
class="ant-tree ant-tree-block-node ant-tree-directory"
role="tree"
>
<div>
<input
@ -42314,6 +42373,7 @@ exports[`ConfigProvider components Tree normal 1`] = `
</div>
<div
class="ant-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -42325,9 +42385,10 @@ exports[`ConfigProvider components Tree normal 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="ant-tree-treenode ant-tree-treenode-switcher-close ant-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -42382,7 +42443,6 @@ exports[`ConfigProvider components Tree prefixCls 1`] = `
<div>
<div
class="prefix-Tree prefix-Tree-icon-hide"
role="tree"
>
<div>
<input
@ -42407,6 +42467,7 @@ exports[`ConfigProvider components Tree prefixCls 1`] = `
</div>
<div
class="prefix-Tree-list"
role="tree"
style="position: relative;"
>
<div
@ -42418,9 +42479,10 @@ exports[`ConfigProvider components Tree prefixCls 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="prefix-Tree-treenode prefix-Tree-treenode-switcher-close prefix-Tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -42447,7 +42509,6 @@ exports[`ConfigProvider components Tree prefixCls 1`] = `
</div>
<div
class="prefix-Tree prefix-Tree-block-node prefix-Tree-directory"
role="tree"
>
<div>
<input
@ -42472,6 +42533,7 @@ exports[`ConfigProvider components Tree prefixCls 1`] = `
</div>
<div
class="prefix-Tree-list"
role="tree"
style="position: relative;"
>
<div
@ -42483,9 +42545,10 @@ exports[`ConfigProvider components Tree prefixCls 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="prefix-Tree-treenode prefix-Tree-treenode-switcher-close prefix-Tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -42585,7 +42648,6 @@ exports[`ConfigProvider components TreeSelect configProvider 1`] = `
</span>
<div
class="config-select-tree config-select-tree-active-focused"
role="tree"
>
<div>
<input
@ -42610,6 +42672,7 @@ exports[`ConfigProvider components TreeSelect configProvider 1`] = `
</div>
<div
class="config-select-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -42622,9 +42685,10 @@ exports[`ConfigProvider components TreeSelect configProvider 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-select-tree-treenode config-select-tree-treenode-switcher-close config-select-tree-treenode-active config-select-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -42795,7 +42859,6 @@ exports[`ConfigProvider components TreeSelect configProvider componentSize large
</span>
<div
class="config-select-tree config-select-tree-active-focused"
role="tree"
>
<div>
<input
@ -42820,6 +42883,7 @@ exports[`ConfigProvider components TreeSelect configProvider componentSize large
</div>
<div
class="config-select-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -42832,9 +42896,10 @@ exports[`ConfigProvider components TreeSelect configProvider componentSize large
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-select-tree-treenode config-select-tree-treenode-switcher-close config-select-tree-treenode-active config-select-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -42940,7 +43005,6 @@ exports[`ConfigProvider components TreeSelect configProvider componentSize middl
</span>
<div
class="config-select-tree config-select-tree-active-focused"
role="tree"
>
<div>
<input
@ -42965,6 +43029,7 @@ exports[`ConfigProvider components TreeSelect configProvider componentSize middl
</div>
<div
class="config-select-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -42977,9 +43042,10 @@ exports[`ConfigProvider components TreeSelect configProvider componentSize middl
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-select-tree-treenode config-select-tree-treenode-switcher-close config-select-tree-treenode-active config-select-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -43085,7 +43151,6 @@ exports[`ConfigProvider components TreeSelect configProvider componentSize small
</span>
<div
class="config-select-tree config-select-tree-active-focused"
role="tree"
>
<div>
<input
@ -43110,6 +43175,7 @@ exports[`ConfigProvider components TreeSelect configProvider componentSize small
</div>
<div
class="config-select-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -43122,9 +43188,10 @@ exports[`ConfigProvider components TreeSelect configProvider componentSize small
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="config-select-tree-treenode config-select-tree-treenode-switcher-close config-select-tree-treenode-active config-select-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -43230,7 +43297,6 @@ exports[`ConfigProvider components TreeSelect normal 1`] = `
</span>
<div
class="ant-select-tree ant-select-tree-active-focused"
role="tree"
>
<div>
<input
@ -43255,6 +43321,7 @@ exports[`ConfigProvider components TreeSelect normal 1`] = `
</div>
<div
class="ant-select-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -43267,9 +43334,10 @@ exports[`ConfigProvider components TreeSelect normal 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="ant-select-tree-treenode ant-select-tree-treenode-switcher-close ant-select-tree-treenode-active ant-select-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"
@ -43375,7 +43443,6 @@ exports[`ConfigProvider components TreeSelect prefixCls 1`] = `
</span>
<div
class="prefix-TreeSelect-tree prefix-TreeSelect-tree-active-focused"
role="tree"
>
<div>
<input
@ -43400,6 +43467,7 @@ exports[`ConfigProvider components TreeSelect prefixCls 1`] = `
</div>
<div
class="prefix-TreeSelect-tree-list"
role="tree"
style="position: relative;"
>
<div
@ -43412,9 +43480,10 @@ exports[`ConfigProvider components TreeSelect prefixCls 1`] = `
style="display: flex; flex-direction: column;"
>
<div
aria-grabbed="false"
aria-expanded="false"
class="prefix-TreeSelect-tree-treenode prefix-TreeSelect-tree-treenode-switcher-close prefix-TreeSelect-tree-treenode-active prefix-TreeSelect-tree-treenode-leaf-last"
draggable="false"
role="treeitem"
>
<span
aria-hidden="true"

View File

@ -39,7 +39,7 @@ describe('ConfigProvider.Theme', () => {
);
expect(themeStyle).toBeTruthy();
expect(themeStyle?.innerHTML).toContain(`--bamboo-${kebabCase(colorName)}: rgb(0, 0, 255)`);
expect(themeStyle?.innerHTML).toContain(`--bamboo-${kebabCase(colorName)}: rgb(0,0,255)`);
});
});
@ -234,7 +234,7 @@ describe('ConfigProvider.Theme', () => {
expect(button).toHaveClass('foo');
expect(button).toHaveStyle({
'--ant-color-text': 'rgba(0, 0, 0, 0.88)',
'--ant-color-text': 'rgba(0,0,0,0.88)',
boxShadow: 'var(--ant-button-default-shadow)',
'border-radius': 'var(--ant-border-radius)',
});
@ -257,14 +257,14 @@ describe('ConfigProvider.Theme', () => {
expect(fooBtn).toHaveClass('foo');
expect(fooBtn).toHaveStyle({
'--ant-color-text': 'rgba(0, 0, 0, 0.88)',
'--ant-color-text': 'rgba(0,0,0,0.88)',
boxShadow: 'var(--ant-button-default-shadow)',
'border-radius': 'var(--ant-border-radius)',
});
expect(barBtn).toHaveClass('bar');
expect(barBtn).toHaveStyle({
'--bar-color-text': 'rgba(0, 0, 0, 0.88)',
'--bar-color-text': 'rgba(0,0,0,0.88)',
boxShadow: 'var(--bar-button-default-shadow)',
'border-radius': 'var(--bar-border-radius)',
});
@ -298,7 +298,7 @@ describe('ConfigProvider.Theme', () => {
const fooBtn = container.querySelector('.button-foo')!;
expect(fooBtn).toHaveClass('foo');
expect(fooBtn).toHaveStyle({
'--foo-color-text': 'rgba(0, 0, 0, 0.88)',
'--foo-color-text': 'rgba(0,0,0,0.88)',
boxShadow: 'var(--foo-button-default-shadow)',
'border-radius': 'var(--foo-border-radius)',
});
@ -306,7 +306,7 @@ describe('ConfigProvider.Theme', () => {
const barBtn = container.querySelector('.button-bar')!;
expect(barBtn).toHaveClass('bar');
expect(barBtn).toHaveStyle({
'--bar-color-text': 'rgba(0, 0, 0, 0.88)',
'--bar-color-text': 'rgba(0,0,0,0.88)',
boxShadow: 'var(--bar-button-default-shadow)',
'border-radius': 'var(--bar-border-radius)',
});
@ -314,7 +314,7 @@ describe('ConfigProvider.Theme', () => {
const bananaBtn = container.querySelector('.button-banana')!;
expect(bananaBtn).toHaveClass('banana');
expect(bananaBtn).toHaveStyle({
'--banana-color-text': 'rgba(0, 0, 0, 0.88)',
'--banana-color-text': 'rgba(0,0,0,0.88)',
boxShadow: 'var(--banana-button-default-shadow)',
'border-radius': 'var(--banana-border-radius)',
});
@ -322,7 +322,7 @@ describe('ConfigProvider.Theme', () => {
const catBtn = container.querySelector('.button-cat')!;
expect(catBtn).toHaveClass('apple');
expect(catBtn).toHaveStyle({
'--cat-color-text': 'rgba(0, 0, 0, 0.88)',
'--cat-color-text': 'rgba(0,0,0,0.88)',
boxShadow: 'var(--cat-button-default-shadow)',
'border-radius': 'var(--cat-border-radius)',
});

View File

@ -9,7 +9,9 @@ import type { CardProps } from '../card';
import type { CascaderProps } from '../cascader';
import type { CollapseProps } from '../collapse';
import type { DatePickerProps, RangePickerProps } from '../date-picker';
import type { DescriptionsProps } from '../descriptions';
import type { DrawerProps } from '../drawer';
import type { EmptyProps } from '../empty';
import type { FlexProps } from '../flex/interface';
import type { FloatButtonGroupProps } from '../float-button/interface';
import type { FormProps } from '../form/Form';
@ -22,8 +24,11 @@ import type { MenuProps } from '../menu';
import type { ModalProps } from '../modal';
import type { ArgsProps } from '../notification/interface';
import type { PaginationProps } from '../pagination';
import type { PopconfirmProps } from '../popconfirm';
import type { PopoverProps } from '../popover';
import type { ResultProps } from '../result';
import type { SelectProps } from '../select';
import type { SliderProps } from '../slider';
import type { SpaceProps } from '../space';
import type { SpinProps } from '../spin';
import type { TableProps } from '../table';
@ -31,6 +36,7 @@ import type { TabsProps } from '../tabs';
import type { TagProps } from '../tag';
import type { AliasToken, MappingAlgorithm, OverrideToken } from '../theme/interface';
import type { TimePickerProps } from '../time-picker';
import type { TooltipProps } from '../tooltip';
import type { TourProps } from '../tour/interface';
import type { TransferProps } from '../transfer';
import type { TreeSelectProps } from '../tree-select';
@ -134,6 +140,11 @@ export type MenuConfig = ComponentStyleConfig & Pick<MenuProps, 'expandIcon'>;
export type TourConfig = Pick<TourProps, 'closeIcon'>;
export type DescriptionsConfig = ComponentStyleConfig &
Pick<DescriptionsProps, 'classNames' | 'styles'>;
export type EmptyConfig = ComponentStyleConfig & Pick<EmptyProps, 'classNames' | 'styles'>;
export type ModalConfig = ComponentStyleConfig &
Pick<ModalProps, 'classNames' | 'styles' | 'closeIcon' | 'closable'>;
@ -177,6 +188,17 @@ export type SelectConfig = ComponentStyleConfig & Pick<SelectProps, 'showSearch'
export type SpaceConfig = ComponentStyleConfig & Pick<SpaceProps, 'size' | 'classNames' | 'styles'>;
export type TooltipConfig = Pick<TooltipProps, 'className' | 'style' | 'styles' | 'classNames'>;
export type PopoverConfig = Pick<PopoverProps, 'className' | 'style' | 'styles' | 'classNames'>;
export type PopconfirmConfig = Pick<
PopconfirmProps,
'className' | 'style' | 'styles' | 'classNames'
>;
export type SliderConfig = ComponentStyleConfig & Pick<SliderProps, 'styles' | 'classNames'>;
export type SpinConfig = ComponentStyleConfig & Pick<SpinProps, 'indicator'>;
export type ResultConfig = ComponentStyleConfig & Pick<ResultProps, 'classNames' | 'styles'>;
@ -272,12 +294,12 @@ export interface ConfigConsumerProps {
modal?: ModalConfig;
progress?: ComponentStyleConfig;
result?: ResultConfig;
slider?: ComponentStyleConfig;
slider?: SliderConfig;
breadcrumb?: ComponentStyleConfig;
menu?: MenuConfig;
checkbox?: ComponentStyleConfig;
descriptions?: ComponentStyleConfig;
empty?: ComponentStyleConfig;
descriptions?: DescriptionsConfig;
empty?: EmptyConfig;
badge?: BadgeConfig;
radio?: ComponentStyleConfig;
rate?: ComponentStyleConfig;
@ -292,6 +314,9 @@ export interface ConfigConsumerProps {
timeline?: ComponentStyleConfig;
timePicker?: TimePickerConfig;
tour?: TourConfig;
tooltip?: TooltipConfig;
popover?: PopoverConfig;
popconfirm?: PopconfirmConfig;
upload?: ComponentStyleConfig;
notification?: NotificationConfig;
tree?: ComponentStyleConfig;

View File

@ -1,5 +1,5 @@
import { generate } from '@ant-design/colors';
import { TinyColor } from '@ctrl/tinycolor';
import { FastColor } from '@ant-design/fast-color';
import canUseDom from 'rc-util/lib/Dom/canUseDom';
import { updateCSS } from 'rc-util/lib/Dom/dynamicCSS';
@ -11,21 +11,21 @@ const dynamicStyleMark = `-ant-${Date.now()}-${Math.random()}`;
export function getStyle(globalPrefixCls: string, theme: Theme) {
const variables: Record<string, string> = {};
const formatColor = (color: TinyColor, updater?: (cloneColor: TinyColor) => TinyColor) => {
const formatColor = (color: FastColor, updater?: (cloneColor: FastColor) => FastColor) => {
let clone = color.clone();
clone = updater?.(clone) || clone;
return clone.toRgbString();
};
const fillColor = (colorVal: string, type: string) => {
const baseColor = new TinyColor(colorVal);
const baseColor = new FastColor(colorVal);
const colorPalettes = generate(baseColor.toRgbString());
variables[`${type}-color`] = formatColor(baseColor);
variables[`${type}-color-disabled`] = colorPalettes[1];
variables[`${type}-color-hover`] = colorPalettes[4];
variables[`${type}-color-active`] = colorPalettes[6];
variables[`${type}-color-outline`] = baseColor.clone().setAlpha(0.2).toRgbString();
variables[`${type}-color-outline`] = baseColor.clone().setA(0.2).toRgbString();
variables[`${type}-color-deprecated-bg`] = colorPalettes[0];
variables[`${type}-color-deprecated-border`] = colorPalettes[2];
};
@ -34,7 +34,7 @@ export function getStyle(globalPrefixCls: string, theme: Theme) {
if (theme.primaryColor) {
fillColor(theme.primaryColor, 'primary');
const primaryColor = new TinyColor(theme.primaryColor);
const primaryColor = new FastColor(theme.primaryColor);
const primaryColors = generate(primaryColor.toRgbString());
// Legacy - We should use semantic naming standard
@ -47,12 +47,12 @@ export function getStyle(globalPrefixCls: string, theme: Theme) {
variables['primary-color-deprecated-t-20'] = formatColor(primaryColor, (c) => c.tint(20));
variables['primary-color-deprecated-t-50'] = formatColor(primaryColor, (c) => c.tint(50));
variables['primary-color-deprecated-f-12'] = formatColor(primaryColor, (c) =>
c.setAlpha(c.getAlpha() * 0.12),
c.setA(c.a * 0.12),
);
const primaryActiveColor = new TinyColor(primaryColors[0]);
const primaryActiveColor = new FastColor(primaryColors[0]);
variables['primary-color-active-deprecated-f-30'] = formatColor(primaryActiveColor, (c) =>
c.setAlpha(c.getAlpha() * 0.3),
c.setA(c.a * 0.3),
);
variables['primary-color-active-deprecated-d-02'] = formatColor(primaryActiveColor, (c) =>
c.darken(2),

View File

@ -123,11 +123,11 @@ const {
| colorPicker | Set ColorPicker common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| datePicker | Set datePicker common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| rangePicker | Set rangePicker common props | { className?: string, style?: React.CSSProperties } | - | 5.11.0 |
| descriptions | Set Descriptions common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| descriptions | Set Descriptions common props | { className?: string, style?: React.CSSProperties, classNames?: [DescriptionsProps\["classNames"\]](/components/descriptions#api), styles?: [DescriptionsProps\["styles"\]](/components/descriptions#api) } | - | 5.7.0, `classNames` and `styles`: 5.23.0 |
| divider | Set Divider common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| drawer | Set Drawer common props | { className?: string, style?: React.CSSProperties, classNames?: [DrawerProps\["classNames"\]](/components/drawer#api), styles?: [DrawerProps\["styles"\]](/components/drawer#api), closeIcon?: ReactNode } | - | 5.7.0, `classNames` and `styles`: 5.10.0, `closeIcon`: 5.14.0 |
| dropdown | Set Dropdown common props | { className?: string, style?: React.CSSProperties } | - | 5.11.0 |
| empty | Set Empty common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| empty | Set Empty common props | { className?: string, style?: React.CSSProperties, classNames?: [EmptyProps\["classNames"\]](/components/empty#api), styles?: [EmptyProps\["styles"\]](/components/empty#api) } | - | 5.7.0, `classNames` and `styles`: 5.23.0 |
| flex | Set Flex common props | { className?: string, style?: React.CSSProperties, vertical?: boolean } | - | 5.10.0 |
| floatButtonGroup | Set FloatButton.Group common props | { closeIcon?: React.ReactNode } | - | 5.16.0 |
| form | Set Form common props | { className?: string, style?: React.CSSProperties, 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; className: 5.7.0; style: 5.7.0 |
@ -149,7 +149,7 @@ const {
| skeleton | Set Skeleton common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| segmented | Set Segmented common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| select | Set Select common props | { className?: string, showSearch?: boolean, style?: React.CSSProperties } | - | 5.7.0 |
| slider | Set Slider common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| slider | Set Slider common props | { className?: string, style?: React.CSSProperties, classNames?: [SliderProps\["classNames"\]](/components/slider#api), styles?: [SliderProps\["styles"\]](/components/slider#api) } | - | 5.7.0, `classNames` and `styles`: 5.23.0 |
| switch | Set Switch common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| space | Set Space common props, ref [Space](/components/space) | { size: `small` \| `middle` \| `large` \| `number`, className?: string, style?: React.CSSProperties, classNames?: [SpaceProps\["classNames"\]](/components/space#api), styles?: [SpaceProps\["styles"\]](/components/space#api) } | - | 5.6.0 |
| splitter | Set Splitter common props | { className?: string, style?: React.CSSProperties } | - | 5.21.0 |
@ -162,6 +162,9 @@ 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#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 |
| popconfirm | Set Popconfirm common props | { className?: string, style?: React.CSSProperties, classNames?:[Popconfirm\["classNames"\]](/components/popconfirm#api), styles?: [Popconfirm\["styles"\]](/components/popconfirm#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

@ -51,11 +51,15 @@ import type {
Theme,
ThemeConfig,
TimePickerConfig,
TooltipConfig,
PopoverConfig,
PopconfirmConfig,
TourConfig,
TransferConfig,
TreeSelectConfig,
Variant,
WaveConfig,
EmptyConfig,
} from './context';
import {
ConfigConsumer,
@ -208,7 +212,7 @@ export interface ConfigProviderProps {
floatButtonGroup?: FloatButtonGroupConfig;
checkbox?: ComponentStyleConfig;
descriptions?: ComponentStyleConfig;
empty?: ComponentStyleConfig;
empty?: EmptyConfig;
badge?: BadgeConfig;
radio?: ComponentStyleConfig;
rate?: ComponentStyleConfig;
@ -235,6 +239,9 @@ export interface ConfigProviderProps {
*/
wave?: WaveConfig;
tour?: TourConfig;
tooltip?: TooltipConfig;
popover?: PopoverConfig;
popconfirm?: PopconfirmConfig;
}
interface ProviderChildrenProps extends ConfigProviderProps {
@ -389,6 +396,9 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
dropdown,
warning: warningConfig,
tour,
tooltip,
popover,
popconfirm,
floatButtonGroup,
variant,
inputNumber,
@ -489,6 +499,9 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
dropdown,
warning: warningConfig,
tour,
tooltip,
popover,
popconfirm,
floatButtonGroup,
variant,
inputNumber,

View File

@ -125,11 +125,11 @@ const {
| colorPicker | 设置 ColorPicker 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| datePicker | 设置 DatePicker 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| rangePicker | 设置 RangePicker 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.11.0 |
| descriptions | 设置 Descriptions 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| descriptions | 设置 Descriptions 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [DescriptionsProps\["classNames"\]](/components/descriptions-cn#api), styles?: [DescriptionsProps\["styles"\]](/components/descriptions-cn#api) } | - | 5.7.0, `classNames``styles`: 5.23.0 |
| divider | 设置 Divider 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| drawer | 设置 Drawer 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [DrawerProps\["classNames"\]](/components/drawer-cn#api), styles?: [DrawerProps\["styles"\]](/components/drawer-cn#api), closeIcon?: ReactNode } | - | 5.7.0, `classNames``styles`: 5.10.0, `closeIcon`: 5.14.0 |
| dropdown | 设置 Dropdown 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.11.0 |
| empty | 设置 Empty 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| empty | 设置 Empty 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?:[EmptyProps\["classNames"\]](/components/empty-cn#api), styles?: [EmptyProps\["styles"\]](/components/empty-cn#api) } | - | 5.7.0, `classNames``styles`: 5.23.0 |
| flex | 设置 Flex 组件的通用属性 | { className?: string, style?: React.CSSProperties, vertical?: boolean } | - | 5.10.0 |
| floatButtonGroup | 设置 FloatButton.Group 组件的通用属性 | { closeIcon?: React.ReactNode } | - | 5.16.0 |
| form | 设置 Form 组件的通用属性 | { className?: string, style?: React.CSSProperties, 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; className: 5.7.0; style: 5.7.0 |
@ -151,7 +151,7 @@ const {
| skeleton | 设置 Skeleton 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| segmented | 设置 Segmented 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| select | 设置 Select 组件的通用属性 | { className?: string, showSearch?: boolean, style?: React.CSSProperties } | - | 5.7.0 |
| slider | 设置 Slider 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| slider | 设置 Slider 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?: [SliderProps\["classNames"\]](/components/slider-cn#api), styles?: [SliderProps\["styles"\]](/components/slider-cn#api) } | - | 5.7.0, `classNames``styles`: 5.23.0 |
| switch | 设置 Switch 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| space | 设置 Space 的通用属性,参考 [Space](/components/space-cn) | { size: `small` \| `middle` \| `large` \| `number`, className?: string, style?: React.CSSProperties, classNames?: [SpaceProps\["classNames"\]](/components/space-cn#api), styles?: [SpaceProps\["styles"\]](/components/space-cn#api) } | - | 5.6.0 |
| splitter | 设置 Splitter 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.21.0 |
@ -164,6 +164,9 @@ const {
| timeline | 设置 Timeline 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| 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 |
| popconfirm | 设置 Popconfirm 组件的通用属性 | { className?: string, style?: React.CSSProperties, classNames?:[Popconfirm\["classNames"\]](/components/popconfirm-cn#api), styles?: [Popconfirm\["styles"\]](/components/popconfirm-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

@ -47230,6 +47230,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="topLeft"
/>
@ -47249,6 +47250,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="topRight"
/>
@ -47268,6 +47270,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="bottomLeft"
/>
@ -47287,6 +47290,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="bottomRight"
/>
@ -61481,6 +61485,7 @@ exports[`renders components/date-picker/demo/size.tsx extend context correctly 1
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="large"
/>
@ -61501,6 +61506,7 @@ exports[`renders components/date-picker/demo/size.tsx extend context correctly 1
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="middle"
/>
@ -61520,6 +61526,7 @@ exports[`renders components/date-picker/demo/size.tsx extend context correctly 1
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="small"
/>

View File

@ -4782,6 +4782,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="topLeft"
/>
@ -4801,6 +4802,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="topRight"
/>
@ -4820,6 +4822,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="bottomLeft"
/>
@ -4839,6 +4842,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="bottomRight"
/>
@ -5999,6 +6003,7 @@ exports[`renders components/date-picker/demo/size.tsx correctly 1`] = `
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="large"
/>
@ -6019,6 +6024,7 @@ exports[`renders components/date-picker/demo/size.tsx correctly 1`] = `
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="middle"
/>
@ -6038,6 +6044,7 @@ exports[`renders components/date-picker/demo/size.tsx correctly 1`] = `
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="small"
/>

View File

@ -31,9 +31,9 @@ export type DatePickerType = typeof DatePicker & {
// We don't care debug panel
/* istanbul ignore next */
const PurePanel = genPurePanel(DatePicker, 'picker', null);
const PurePanel = genPurePanel(DatePicker, 'popupAlign', undefined, 'picker');
(DatePicker as DatePickerType)._InternalPanelDoNotUseOrYouWillBeFired = PurePanel;
const PureRangePanel = genPurePanel(DatePicker.RangePicker, 'picker', null);
const PureRangePanel = genPurePanel(DatePicker.RangePicker, 'popupAlign', undefined, 'picker');
(DatePicker as DatePickerType)._InternalRangePanelDoNotUseOrYouWillBeFired = PureRangePanel;
(DatePicker as DatePickerType).generatePicker = generatePicker;

View File

@ -1,6 +1,6 @@
import { unit } from '@ant-design/cssinjs';
import type { CSSObject } from '@ant-design/cssinjs';
import { TinyColor } from '@ctrl/tinycolor';
import { FastColor } from '@ant-design/fast-color';
import type { GenerateStyle } from '../../theme/internal';
import type { PickerToken, SharedPickerToken } from './token';
@ -477,7 +477,7 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
},
[`&${componentCls}-cell-week`]: {
color: new TinyColor(colorTextLightSolid).setAlpha(0.5).toHexString(),
color: new FastColor(colorTextLightSolid).setA(0.5).toHexString(),
},
[pickerCellInnerCls]: {
@ -578,7 +578,7 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
},
'&-active': {
background: new TinyColor(controlItemBgActive).setAlpha(0.2).toHexString(),
background: new FastColor(controlItemBgActive).setA(0.2).toHexString(),
},
'&:hover': {

View File

@ -1,4 +1,4 @@
import { TinyColor } from '@ctrl/tinycolor';
import { FastColor } from '@ant-design/fast-color';
import type { SharedComponentToken, SharedInputToken } from '../../input/style/token';
import { initComponentToken } from '../../input/style/token';
@ -6,9 +6,9 @@ import type { MultipleSelectorToken, SelectorToken } from '../../select/style/to
import type { ArrowToken } from '../../style/roundedArrow';
import { getArrowToken } from '../../style/roundedArrow';
import type {
GlobalToken,
FullToken,
GetDefaultToken,
GlobalToken,
TokenWithCommonCls,
} from '../../theme/internal';
@ -175,8 +175,8 @@ export const initPanelComponentToken = (token: GlobalToken): PanelComponentToken
INTERNAL_FIXED_ITEM_MARGIN,
cellHoverBg: token.controlItemBgHover,
cellActiveWithRangeBg: token.controlItemBgActive,
cellHoverWithRangeBg: new TinyColor(token.colorPrimary).lighten(35).toHexString(),
cellRangeBorderColor: new TinyColor(token.colorPrimary).lighten(20).toHexString(),
cellHoverWithRangeBg: new FastColor(token.colorPrimary).lighten(35).toHexString(),
cellRangeBorderColor: new FastColor(token.colorPrimary).lighten(20).toHexString(),
cellBgDisabled: colorBgContainerDisabled,
timeColumnWidth: controlHeightLG * 1.4,
timeColumnHeight: 28 * 8,

View File

@ -1,6 +1,7 @@
import * as React from 'react';
import type { JSX } from 'react';
import classNames from 'classnames';
import DescriptionsContext from './DescriptionsContext';
function notEmpty(val: any) {
return val !== undefined && val !== null;
@ -12,8 +13,18 @@ export interface CellProps {
className?: string;
component: string;
style?: React.CSSProperties;
/** @deprecated Please use `styles={{ label: {} }}` instead */
labelStyle?: React.CSSProperties;
/** @deprecated Please use `styles={{ content: {} }}` instead */
contentStyle?: React.CSSProperties;
styles?: {
label?: React.CSSProperties;
content?: React.CSSProperties;
};
classNames?: {
label?: string;
content?: string;
};
bordered?: boolean;
label?: React.ReactNode;
content?: React.ReactNode;
@ -35,9 +46,12 @@ const Cell: React.FC<CellProps> = (props) => {
content,
colon,
type,
styles,
} = props;
const Component = component as keyof JSX.IntrinsicElements;
const descContext = React.useContext(DescriptionsContext);
const { classNames: descriptionsClassNames } = descContext;
if (bordered) {
return (
@ -46,14 +60,16 @@ const Cell: React.FC<CellProps> = (props) => {
{
[`${itemPrefixCls}-item-label`]: type === 'label',
[`${itemPrefixCls}-item-content`]: type === 'content',
[`${descriptionsClassNames?.label}`]: type === 'label',
[`${descriptionsClassNames?.content}`]: type === 'content',
},
className,
)}
style={style}
colSpan={span}
>
{notEmpty(label) && <span style={labelStyle}>{label}</span>}
{notEmpty(content) && <span style={contentStyle}>{content}</span>}
{notEmpty(label) && <span style={{ ...labelStyle, ...styles?.label }}>{label}</span>}
{notEmpty(content) && <span style={{ ...labelStyle, ...styles?.content }}>{content}</span>}
</Component>
);
}
@ -67,16 +83,19 @@ const Cell: React.FC<CellProps> = (props) => {
<div className={`${itemPrefixCls}-item-container`}>
{(label || label === 0) && (
<span
className={classNames(`${itemPrefixCls}-item-label`, {
className={classNames(`${itemPrefixCls}-item-label`, descriptionsClassNames?.label, {
[`${itemPrefixCls}-item-no-colon`]: !colon,
})}
style={labelStyle}
style={{ ...labelStyle, ...styles?.label }}
>
{label}
</span>
)}
{(content || content === 0) && (
<span className={classNames(`${itemPrefixCls}-item-content`)} style={contentStyle}>
<span
className={classNames(`${itemPrefixCls}-item-content`, descriptionsClassNames?.content)}
style={{ ...contentStyle, ...styles?.content }}
>
{content}
</span>
)}

View File

@ -1,8 +1,18 @@
import React from 'react';
export interface DescriptionsContextProps {
/** @deprecated Please use `styles={{ label: {} }}` instead */
labelStyle?: React.CSSProperties;
/** @deprecated Please use `styles={{ content: {} }}` instead */
contentStyle?: React.CSSProperties;
styles?: {
label?: React.CSSProperties;
content?: React.CSSProperties;
};
classNames?: {
label?: string;
content?: string;
};
}
const DescriptionsContext = React.createContext<DescriptionsContextProps>({});

View File

@ -5,8 +5,18 @@ export interface DescriptionsItemProps {
className?: string;
style?: React.CSSProperties;
label?: React.ReactNode;
/** @deprecated Please use `styles={{ label: {} }}` instead */
labelStyle?: React.CSSProperties;
/** @deprecated Please use `styles={{ content: {} }}` instead */
contentStyle?: React.CSSProperties;
styles?: {
label?: React.CSSProperties;
content?: React.CSSProperties;
};
classNames?: {
label?: string;
content?: string;
};
children: React.ReactNode;
span?: number;
}

View File

@ -22,6 +22,7 @@ function renderCells(
showContent,
labelStyle: rootLabelStyle,
contentStyle: rootContentStyle,
styles: rootStyles,
}: CellConfig & DescriptionsContextProps,
) {
return items.map(
@ -36,6 +37,7 @@ function renderCells(
contentStyle,
span = 1,
key,
styles,
},
index,
) => {
@ -45,8 +47,20 @@ function renderCells(
key={`${type}-${key || index}`}
className={className}
style={style}
labelStyle={{ ...rootLabelStyle, ...labelStyle }}
contentStyle={{ ...rootContentStyle, ...contentStyle }}
styles={{
label: {
...rootLabelStyle,
...rootStyles?.label,
...labelStyle,
...styles?.label,
},
content: {
...rootContentStyle,
...rootStyles?.content,
...contentStyle,
...styles?.content,
},
}}
span={span}
colon={colon}
component={component}
@ -63,7 +77,13 @@ function renderCells(
<Cell
key={`label-${key || index}`}
className={className}
style={{ ...rootLabelStyle, ...style, ...labelStyle }}
style={{
...rootLabelStyle,
...rootStyles?.label,
...style,
...labelStyle,
...styles?.label,
}}
span={1}
colon={colon}
component={component[0]}
@ -75,7 +95,13 @@ function renderCells(
<Cell
key={`content-${key || index}`}
className={className}
style={{ ...rootContentStyle, ...style, ...contentStyle }}
style={{
...rootContentStyle,
...rootStyles?.content,
...style,
...contentStyle,
...styles?.content,
}}
span={span * 2 - 1}
component={component[1]}
itemPrefixCls={itemPrefixCls}

View File

@ -513,6 +513,7 @@ exports[`renders components/descriptions/demo/component-token.tsx extend context
<input
checked=""
class="ant-radio-input"
name="test-id"
type="radio"
value="default"
/>
@ -532,6 +533,7 @@ exports[`renders components/descriptions/demo/component-token.tsx extend context
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="middle"
/>
@ -551,6 +553,7 @@ exports[`renders components/descriptions/demo/component-token.tsx extend context
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="small"
/>
@ -1604,6 +1607,7 @@ exports[`renders components/descriptions/demo/size.tsx extend context correctly
<input
checked=""
class="ant-radio-input"
name="test-id"
type="radio"
value="default"
/>
@ -1623,6 +1627,7 @@ exports[`renders components/descriptions/demo/size.tsx extend context correctly
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="middle"
/>
@ -1642,6 +1647,7 @@ exports[`renders components/descriptions/demo/size.tsx extend context correctly
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="small"
/>
@ -2060,6 +2066,7 @@ Array [
<input
checked=""
class="ant-radio-input"
name="test-id"
type="radio"
value="horizontal"
/>
@ -2079,6 +2086,7 @@ Array [
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="vertical"
/>

View File

@ -467,6 +467,7 @@ exports[`renders components/descriptions/demo/component-token.tsx correctly 1`]
<input
checked=""
class="ant-radio-input"
name="test-id"
type="radio"
value="default"
/>
@ -486,6 +487,7 @@ exports[`renders components/descriptions/demo/component-token.tsx correctly 1`]
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="middle"
/>
@ -505,6 +507,7 @@ exports[`renders components/descriptions/demo/component-token.tsx correctly 1`]
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="small"
/>
@ -1486,6 +1489,7 @@ exports[`renders components/descriptions/demo/size.tsx correctly 1`] = `
<input
checked=""
class="ant-radio-input"
name="test-id"
type="radio"
value="default"
/>
@ -1505,6 +1509,7 @@ exports[`renders components/descriptions/demo/size.tsx correctly 1`] = `
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="middle"
/>
@ -1524,6 +1529,7 @@ exports[`renders components/descriptions/demo/size.tsx correctly 1`] = `
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="small"
/>
@ -1908,6 +1914,7 @@ Array [
<input
checked=""
class="ant-radio-input"
name="test-id"
type="radio"
value="horizontal"
/>
@ -1927,6 +1934,7 @@ Array [
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="vertical"
/>

View File

@ -415,4 +415,83 @@ describe('Descriptions', () => {
expect(wrapper.container.querySelectorAll('.ant-descriptions-item-label')).toHaveLength(1);
expect(wrapper.container.querySelectorAll('.ant-descriptions-item-content')).toHaveLength(1);
});
it('should apply custom styles to Descriptions', () => {
const customClassNames = {
root: 'custom-root',
header: 'custom-header',
title: 'custom-title',
extra: 'custom-extra',
label: 'custom-label',
content: 'custom-content',
};
const customStyles = {
root: { backgroundColor: 'red' },
header: { backgroundColor: 'black' },
title: { backgroundColor: 'yellow' },
extra: { backgroundColor: 'purple' },
label: { backgroundColor: 'blue' },
content: { backgroundColor: 'green' },
};
const { container } = render(
<Descriptions
classNames={customClassNames}
styles={customStyles}
extra={'extra'}
title="User Info"
items={[
{
key: '1',
label: 'UserName',
children: '1',
},
{
key: '2',
label: 'UserName',
children: '2',
styles: {
content: { color: 'yellow' },
label: { color: 'orange' },
},
},
]}
/>,
);
const rootElement = container.querySelector('.ant-descriptions') as HTMLElement;
const headerElement = container.querySelector('.ant-descriptions-header') as HTMLElement;
const titleElement = container.querySelector('.ant-descriptions-title') as HTMLElement;
const extraElement = container.querySelector('.ant-descriptions-extra') as HTMLElement;
const labelElement = container.querySelector('.ant-descriptions-item-label') as HTMLElement;
const contentElement = container.querySelector('.ant-descriptions-item-content') as HTMLElement;
const labelElements = container.querySelectorAll(
'.ant-descriptions-item-label',
) as NodeListOf<HTMLElement>;
const contentElements = container.querySelectorAll(
'.ant-descriptions-item-content',
) as NodeListOf<HTMLElement>;
// check classNames
expect(rootElement.classList).toContain('custom-root');
expect(headerElement.classList).toContain('custom-header');
expect(titleElement.classList).toContain('custom-title');
expect(extraElement.classList).toContain('custom-extra');
expect(labelElement.classList).toContain('custom-label');
expect(contentElement.classList).toContain('custom-content');
// check styles
expect(rootElement.style.backgroundColor).toBe('red');
expect(headerElement.style.backgroundColor).toBe('black');
expect(titleElement.style.backgroundColor).toBe('yellow');
expect(extraElement.style.backgroundColor).toBe('purple');
expect(labelElement.style.backgroundColor).toBe('blue');
expect(contentElement.style.backgroundColor).toBe('green');
expect(labelElements[1].style.color).toBe('orange');
expect(contentElements[1].style.color).toBe('yellow');
expect(labelElements[0].style.color).not.toBe('orange');
expect(contentElements[0].style.color).not.toBe('yellow');
});
});

View File

@ -0,0 +1,75 @@
import React from 'react';
import { Button, Descriptions, DescriptionsProps, Divider, Switch } from 'antd';
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
import useLocale from '../../../.dumi/hooks/useLocale';
const locales = {
cn: {
root: '根节点',
header: '头部元素',
title: '标题元素',
extra: '额外内容',
label: '标签元素',
content: '内容元素',
},
en: {
root: 'root element',
header: 'header element',
title: 'title element',
extra: 'extra element',
label: 'label element',
content: 'content element',
},
};
const items: DescriptionsProps['items'] = [
{
key: '1',
label: 'Telephone',
children: '1810000000',
},
];
const BlockList: React.FC<React.PropsWithChildren> = (props: any) => {
const divRef = React.useRef<HTMLDivElement>(null);
const [bordered, setBordered] = React.useState(false);
const handleBorderChange = (checked: boolean) => {
setBordered(checked);
};
return (
<div ref={divRef} style={{ width: '100%', height: '100%' }}>
<Switch checked={bordered} onChange={handleBorderChange} /> Toggle Border
<Divider />
<Descriptions
title="User Info"
items={items}
extra={<Button type="primary">Edit</Button>}
bordered={bordered}
{...props}
/>
</div>
);
};
const App: React.FC = () => {
const [locale] = useLocale(locales);
return (
<SemanticPreview
semantics={[
{ name: 'root', desc: locale.root, version: '5.23.0' },
{ name: 'header', desc: locale.header, version: '5.23.0' },
{ name: 'title', desc: locale.title, version: '5.23.0' },
{ name: 'extra', desc: locale.extra, version: '5.23.0' },
{ name: 'label', desc: locale.label, version: '5.23.0' },
{ name: 'content', desc: locale.content, version: '5.23.0' },
]}
>
<BlockList />
</SemanticPreview>
);
};
export default App;

View File

@ -12,8 +12,10 @@ const items: DescriptionsProps['items'] = [
key: '1',
label: 'Product',
children: 'Cloud Database',
labelStyle,
contentStyle,
styles: {
label: labelStyle,
content: contentStyle,
},
},
{
key: '2',
@ -42,8 +44,10 @@ const rootStyleItems: DescriptionsProps['items'] = [
key: '3',
label: 'Automatic Renewal',
children: 'YES',
labelStyle: { color: 'orange' },
contentStyle: { color: 'blue' },
styles: {
label: { color: 'orange' },
content: { color: 'blue' },
},
},
];
@ -69,8 +73,10 @@ const App: React.FC = () => {
<Divider />
<Descriptions
title="Root style"
labelStyle={labelStyle}
contentStyle={contentStyle}
styles={{
label: labelStyle,
content: contentStyle,
}}
bordered={border}
layout={layout}
items={rootStyleItems}

View File

@ -103,6 +103,10 @@ Common props ref[Common props](/docs/react/common-props)
> The number of span Description.Item. Span={2} takes up the width of two DescriptionItems. When both `style` and `labelStyle`(or `contentStyle`) configured, both of them will work. And next one will overwrite first when conflict.
## Semantic DOM
<code src="./demo/_semantic.tsx" simplify="true"></code>
## Design Token
<ComponentTokenTable component="Descriptions"></ComponentTokenTable>

View File

@ -4,6 +4,7 @@ import classNames from 'classnames';
import type { Breakpoint } from '../_util/responsiveObserver';
import { matchScreen } from '../_util/responsiveObserver';
import { devUseWarning } from '../_util/warning';
import { ConfigContext } from '../config-provider';
import useSize from '../config-provider/hooks/useSize';
import useBreakpoint from '../grid/hooks/useBreakpoint';
@ -48,6 +49,22 @@ export interface DescriptionsProps {
colon?: boolean;
labelStyle?: React.CSSProperties;
contentStyle?: React.CSSProperties;
styles?: {
root?: React.CSSProperties;
header?: React.CSSProperties;
title?: React.CSSProperties;
extra?: React.CSSProperties;
label?: React.CSSProperties;
content?: React.CSSProperties;
};
classNames?: {
root?: string;
header?: string;
title?: string;
extra?: string;
label?: string;
content?: string;
};
items?: DescriptionsItemType[];
id?: string;
}
@ -68,13 +85,25 @@ const Descriptions: React.FC<DescriptionsProps> & CompoundedComponent = (props)
size: customizeSize,
labelStyle,
contentStyle,
styles,
items,
classNames: descriptionsClassNames,
...restProps
} = props;
const { getPrefixCls, direction, descriptions } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('descriptions', customizePrefixCls);
const screens = useBreakpoint();
// ============================== Warn ==============================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning('Descriptions');
[
['labelStyle', 'styles={{ label: {} }}'],
['contentStyle', 'styles={{ content: {} }}'],
].forEach(([deprecatedName, newName]) => {
warning.deprecated(!(deprecatedName in props), deprecatedName, newName);
});
}
// Column count
const mergedColumn = React.useMemo(() => {
if (typeof column === 'number') {
@ -99,8 +128,19 @@ const Descriptions: React.FC<DescriptionsProps> & CompoundedComponent = (props)
// ======================== Render ========================
const contextValue = React.useMemo(
() => ({ labelStyle, contentStyle }),
[labelStyle, contentStyle],
() => ({
labelStyle,
contentStyle,
styles: {
content: { ...descriptions?.styles?.content, ...styles?.content },
label: { ...descriptions?.styles?.label, ...styles?.label },
},
classNames: {
label: classNames(descriptions?.classNames?.label, descriptionsClassNames?.label),
content: classNames(descriptions?.classNames?.content, descriptionsClassNames?.content),
},
}),
[labelStyle, contentStyle, styles, descriptionsClassNames, descriptions],
);
return wrapCSSVar(
@ -109,6 +149,8 @@ const Descriptions: React.FC<DescriptionsProps> & CompoundedComponent = (props)
className={classNames(
prefixCls,
descriptions?.className,
descriptions?.classNames?.root,
descriptionsClassNames?.root,
{
[`${prefixCls}-${mergedSize}`]: mergedSize && mergedSize !== 'default',
[`${prefixCls}-bordered`]: !!bordered,
@ -119,13 +161,45 @@ const Descriptions: React.FC<DescriptionsProps> & CompoundedComponent = (props)
hashId,
cssVarCls,
)}
style={{ ...descriptions?.style, ...style }}
style={{ ...descriptions?.style, ...descriptions?.styles?.root, ...styles?.root, ...style }}
{...restProps}
>
{(title || extra) && (
<div className={`${prefixCls}-header`}>
{title && <div className={`${prefixCls}-title`}>{title}</div>}
{extra && <div className={`${prefixCls}-extra`}>{extra}</div>}
<div
className={classNames(
`${prefixCls}-header`,
descriptions?.classNames?.header,
descriptionsClassNames?.header,
)}
style={{ ...descriptions?.styles?.header, ...styles?.header }}
>
{title && (
<div
className={classNames(
`${prefixCls}-title`,
descriptions?.classNames?.title,
descriptionsClassNames?.title,
)}
style={{
...descriptions?.styles?.title,
...styles?.title,
}}
>
{title}
</div>
)}
{extra && (
<div
className={classNames(
`${prefixCls}-extra`,
descriptions?.classNames?.extra,
descriptionsClassNames?.extra,
)}
style={{ ...descriptions?.styles?.extra, ...styles?.extra }}
>
{extra}
</div>
)}
</div>
)}

View File

@ -104,6 +104,10 @@ const items: DescriptionsProps['items'] = [
> span 是 Description.Item 的数量。 span={2} 会占用两个 DescriptionItem 的宽度。当同时配置 `style``labelStyle`(或 `contentStyle`)时,两者会同时作用。样式冲突时,后者会覆盖前者。
## Semantic DOM
<code src="./demo/_semantic.tsx" simplify="true"></code>
## 主题变量Design Token
<ComponentTokenTable component="Descriptions"></ComponentTokenTable>

View File

@ -500,6 +500,7 @@ Array [
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="top"
/>
@ -520,6 +521,7 @@ Array [
<input
checked=""
class="ant-radio-input"
name="test-id"
type="radio"
value="right"
/>
@ -539,6 +541,7 @@ Array [
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="bottom"
/>
@ -558,6 +561,7 @@ Array [
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="left"
/>
@ -3150,6 +3154,7 @@ Array [
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="top"
/>
@ -3169,6 +3174,7 @@ Array [
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="right"
/>
@ -3188,6 +3194,7 @@ Array [
>
<input
class="ant-radio-input"
name="test-id"
type="radio"
value="bottom"
/>
@ -3208,6 +3215,7 @@ Array [
<input
checked=""
class="ant-radio-input"
name="test-id"
type="radio"
value="left"
/>

Some files were not shown because too many files have changed in this diff Show More