Merge branch 'next' into feat/masonry-v6

This commit is contained in:
afc163 2025-01-21 14:39:33 +08:00 committed by GitHub
commit 1cd065f767
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
616 changed files with 23711 additions and 7719 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,5 +1,5 @@
import { useEffect, useRef } from 'react';
import { removeCSS, updateCSS } from 'rc-util/lib/Dom/dynamicCSS';
import { removeCSS, updateCSS } from '@rc-component/util/lib/Dom/dynamicCSS';
import theme from '../../components/theme';

View File

@ -27,10 +27,10 @@ const { _InternalPanelDoNotUseOrYouWillBeFired: TourDoNotUseOrYouWillBeFired } =
const { _InternalPanelDoNotUseOrYouWillBeFired: FloatButtonDoNotUseOrYouWillBeFired } = FloatButton;
const SAMPLE_CONTENT_EN =
'Ant Design 5.0 use CSS-in-JS technology to provide dynamic & mix theme ability. And which use component level CSS-in-JS solution get your application a better performance.';
'Ant Design use CSS-in-JS technology to provide dynamic & mix theme ability. And which use component level CSS-in-JS solution get your application a better performance.';
const SAMPLE_CONTENT_CN =
'Ant Design 5.0 使用 CSS-in-JS 技术以提供动态与混合主题的能力。与此同时,我们使用组件级别的 CSS-in-JS 解决方案,让你的应用获得更好的性能。';
'Ant Design 使用 CSS-in-JS 技术以提供动态与混合主题的能力。与此同时,我们使用组件级别的 CSS-in-JS 解决方案,让你的应用获得更好的性能。';
const locales = {
cn: {
@ -158,7 +158,7 @@ const ComponentsList: React.FC = () => {
title: 'Modal',
type: 'update',
node: (
<ModalDoNotUseOrYouWillBeFired title="Ant Design 5.0" width={300}>
<ModalDoNotUseOrYouWillBeFired title="Ant Design" width={300}>
{locale.sampleContent}
</ModalDoNotUseOrYouWillBeFired>
),
@ -210,7 +210,7 @@ const ComponentsList: React.FC = () => {
type: 'new',
node: (
<TourDoNotUseOrYouWillBeFired
title="Ant Design 5.0"
title="Ant Design"
description={locale.tour}
style={{ width: isMobile ? 'auto' : 350 }}
current={3}
@ -255,7 +255,7 @@ const ComponentsList: React.FC = () => {
node: (
<Alert
style={{ width: 400 }}
message="Ant Design 5.0"
message="Ant Design"
description={locale.sampleContent}
closable={{ closeIcon: true, disabled: true }}
/>

View File

@ -28,7 +28,7 @@ const { _InternalPanelDoNotUseOrYouWillBeFired: InternalMessage } = message;
const locales = {
cn: {
range: '设置范围',
text: 'Ant Design 5.0 使用 CSS-in-JS 技术以提供动态与混合主题的能力。与此同时,我们使用组件级别的 CSS-in-JS 解决方案,让你的应用获得更好的性能。',
text: 'Ant Design 使用 CSS-in-JS 技术以提供动态与混合主题的能力。与此同时,我们使用组件级别的 CSS-in-JS 解决方案,让你的应用获得更好的性能。',
infoText: '信息内容展示',
dropdown: '下拉菜单',
finished: '已完成',
@ -45,11 +45,11 @@ const locales = {
dashed: '虚线按钮',
icon: '图标按钮',
hello: '你好Ant Design!',
release: 'Ant Design 5.0 正式发布!',
release: 'Ant Design 6.0 正式发布!',
},
en: {
range: 'Set Range',
text: 'Ant Design 5.0 use CSS-in-JS technology to provide dynamic & mix theme ability. And which use component level CSS-in-JS solution get your application a better performance.',
text: 'Ant Design use CSS-in-JS technology to provide dynamic & mix theme ability. And which use component level CSS-in-JS solution get your application a better performance.',
infoText: 'Info Text',
dropdown: 'Dropdown',
finished: 'Finished',
@ -66,7 +66,7 @@ const locales = {
dashed: 'Dashed',
icon: 'Icon',
hello: 'Hello, Ant Design!',
release: 'Ant Design 5.0 is released!',
release: 'Ant Design 6.0 is released!',
},
};
@ -109,7 +109,7 @@ const ComponentsBlock: React.FC = () => {
return (
<Tilt options={{ max: 20, glare: true, scale: 1 }} className={styles.holder}>
<ModalPanel title="Ant Design 5.0" width="100%">
<ModalPanel title="Ant Design" width="100%">
{locale.text}
</ModalPanel>
<Alert message={locale.infoText} type="info" />

View File

@ -156,7 +156,7 @@ const PreviewBanner: React.FC<Readonly<React.PropsWithChildren>> = (props) => {
</Suspense>
<div className={styles.mask} />
<Typography className={styles.typography}>
<h1>Ant Design 5.0</h1>
<h1>Ant Design</h1>
<p>{locale.slogan}</p>
</Typography>
<Flex gap="middle" className={styles.btnWrap}>

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

@ -1,12 +1,12 @@
import * as React from 'react';
import { defaultAlgorithm, defaultTheme } from '@ant-design/compatible';
import { FastColor } from '@ant-design/fast-color';
import {
BellOutlined,
FolderOutlined,
HomeOutlined,
QuestionCircleOutlined,
} from '@ant-design/icons';
import { TinyColor } from '@ctrl/tinycolor';
import type { ColorPickerProps, GetProp, MenuProps, ThemeConfig } from 'antd';
import {
Breadcrumb,
@ -56,7 +56,7 @@ const TokenChecker: React.FC = () => {
const locales = {
cn: {
themeTitle: '定制主题,随心所欲',
themeDesc: 'Ant Design 5.0 开放更多样式算法,让你定制主题更简单',
themeDesc: 'Ant Design 开放更多样式算法,让你定制主题更简单',
customizeTheme: '定制主题',
myTheme: '我的主题',
@ -73,7 +73,7 @@ const locales = {
},
en: {
themeTitle: 'Flexible theme customization',
themeDesc: 'Ant Design 5.0 enable extendable algorithm, make custom theme easier',
themeDesc: 'Ant Design enable extendable algorithm, make custom theme easier',
customizeTheme: 'Customize Theme',
myTheme: 'My Theme',
@ -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;
@ -478,7 +478,7 @@ const Theme: React.FC = () => {
alt="antd logo"
/>
</div>
<h1>Ant Design 5.0</h1>
<h1>Ant Design</h1>
</div>
<Flex className={styles.menu} gap="middle">
<BellOutlined />

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

@ -154,7 +154,9 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
colon={false}
column={1}
style={{ marginTop: token.margin }}
labelStyle={{ paddingInlineEnd: token.padding, width: 56 }}
styles={{
label: { paddingInlineEnd: token.padding, width: 56 },
}}
items={
[
{

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

@ -1,7 +1,7 @@
import React from 'react';
import toArray from '@rc-component/util/lib/Children/toArray';
import { Image } from 'antd';
import classNames from 'classnames';
import toArray from 'rc-util/lib/Children/toArray';
interface ImagePreviewProps {
className?: string;

View File

@ -0,0 +1,80 @@
import React, { Suspense, useEffect, useState } from 'react';
import { Tooltip } from 'antd';
import { FormattedMessage } from 'dumi';
import { ping } from '../../utils';
let pingDeferrer: PromiseLike<boolean>;
const codeBlockJs =
'https://renderoffice.a' +
'lipay' +
'objects.com/p' +
'/yuyan/180020010001206410/parseFileData-v1.0.1.js';
function useShowCodeBlockButton() {
const [showCodeBlockButton, setShowCodeBlockButton] = useState(false);
useEffect(() => {
pingDeferrer ??= new Promise<boolean>((resolve) => {
ping((status) => {
if (status !== 'timeout' && status !== 'error') {
// Async insert `codeBlockJs` into body end
const script = document.createElement('script');
script.src = codeBlockJs;
script.async = true;
document.body.appendChild(script);
return resolve(true);
}
return resolve(false);
});
});
pingDeferrer.then(setShowCodeBlockButton);
}, []);
return showCodeBlockButton;
}
interface CodeBlockButtonProps {
title?: string;
dependencies: Record<PropertyKey, string>;
jsx: string;
}
const CodeBlockButton: React.FC<CodeBlockButtonProps> = ({ title, dependencies = {}, jsx }) => {
const showCodeBlockButton = useShowCodeBlockButton();
const codeBlockPrefillConfig = {
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 showCodeBlockButton ? (
<Tooltip title={<FormattedMessage id="app.demo.codeblock" />}>
<div className="code-box-code-action">
<img
alt="codeblock"
src="https://mdn.alipayobjects.com/huamei_wtld8u/afts/img/A*K8rjSJpTNQ8AAAAAAAAAAAAADhOIAQ/original"
className="code-box-codeblock"
onClick={() => {
openHituCodeBlock(JSON.stringify(codeBlockPrefillConfig));
}}
/>
</div>
</Tooltip>
) : null;
};
export default (props: CodeBlockButtonProps) => (
<Suspense>
<CodeBlockButton {...props} />
</Suspense>
);

View File

@ -16,11 +16,10 @@ 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 CodeBlockButton from './CodeBlockButton';
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);
@ -278,18 +254,6 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
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';";
@ -324,7 +288,7 @@ createRoot(document.getElementById('container')).render(<Demo />);
main: 'index.js',
dependencies: {
...dependencies,
'rc-util': pkgDependencyList['rc-util'],
'@rc-component/util': pkgDependencyList['@rc-component/util'],
react: '^18.0.0',
'react-dom': '^18.0.0',
'react-scripts': '^5.0.0',
@ -440,24 +404,7 @@ 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}
<CodeBlockButton title={localizedTitle} dependencies={dependencies} jsx={jsx} />
<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

@ -20,6 +20,7 @@ interface ChangelogInfo {
version: string;
changelog: string;
refs: string[];
contributors: string[];
releaseDate: string;
}
@ -160,14 +161,30 @@ const ParseChangelog: React.FC<{ changelog: string }> = (props) => {
return <span>{parsedChangelog}</span>;
};
const RefLinks: React.FC<{ refs: string[] }> = ({ refs }) => {
const RefLinks: React.FC<{ refs: string[]; contributors: string[] }> = ({ refs, contributors }) => {
const { styles } = useStyle();
return (
<>
{refs?.map((ref) => (
<React.Fragment key={ref}>
<a className={styles.linkRef} key={ref} href={ref} target="_blank" rel="noreferrer">
#{ref.match(/^.*\/(\d+)$/)?.[1]}
#{ref.match(/[^/]+$/)?.[0]}
</a>
</React.Fragment>
))}
{contributors?.map((contributor) => (
<React.Fragment key={contributor}>
<a
className={styles.linkRef}
key={contributor}
href={`https://github.com/${contributor}`}
target="_blank"
rel="noreferrer"
>
@{contributor}
</a>
</React.Fragment>
))}
</>
);
@ -178,7 +195,7 @@ const RenderChangelogList: React.FC<{ changelogList: ChangelogInfo[] }> = ({ cha
const { styles } = useStyle();
const len = changelogList.length;
for (let i = 0; i < len; i += 1) {
const { refs, changelog } = changelogList[i];
const { refs, changelog, contributors } = changelogList[i];
// Check if the next line is an image link and append it to the current line
if (i + 1 < len && changelogList[i + 1].changelog.trim().startsWith('<img')) {
const imgDom = new DOMParser().parseFromString(changelogList[i + 1].changelog, 'text/html');
@ -186,7 +203,7 @@ const RenderChangelogList: React.FC<{ changelogList: ChangelogInfo[] }> = ({ cha
elements.push(
<li key={i}>
<ParseChangelog changelog={changelog} />
<RefLinks refs={refs} />
<RefLinks refs={refs} contributors={contributors} />
<br />
<img
src={imgElement?.getAttribute('src') || ''}
@ -200,7 +217,7 @@ const RenderChangelogList: React.FC<{ changelogList: ChangelogInfo[] }> = ({ cha
elements.push(
<li key={i}>
<ParseChangelog changelog={changelog} />
<RefLinks refs={refs} />
<RefLinks refs={refs} contributors={contributors} />
</li>,
);
}

View File

@ -1,7 +1,7 @@
import React from 'react';
import { css, Global } from '@emotion/react';
import { updateCSS } from '@rc-component/util/lib/Dom/dynamicCSS';
import { useTheme } from 'antd-style';
import { updateCSS } from 'rc-util/lib/Dom/dynamicCSS';
export default () => {
const { anchorTop } = useTheme();

View File

@ -282,12 +282,13 @@ const GlobalDemoStyles: React.FC = () => {
cursor: pointer;
}
&-riddle {
width: 14px;
height: 14px;
&-codeblock {
width: 16px;
height: 16px;
overflow: hidden;
border: 0;
cursor: pointer;
max-width: 100% !important;
}
&-codesandbox {

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

@ -1,4 +1,5 @@
import React, { Suspense, useCallback, useEffect } from 'react';
import { Monitoring } from 'react-scan/monitoring';
import {
createCache,
extractStyle,
@ -12,7 +13,13 @@ import { getSandpackCssText } from '@codesandbox/sandpack-react';
import { theme as antdTheme, App } from 'antd';
import type { MappingAlgorithm } from 'antd';
import type { DirectionType, ThemeConfig } from 'antd/es/config-provider';
import { createSearchParams, useOutlet, useSearchParams, useServerInsertedHTML } from 'dumi';
import {
createSearchParams,
useOutlet,
useParams,
useSearchParams,
useServerInsertedHTML,
} from 'dumi';
import { DarkContext } from '../../hooks/useDark';
import useLayoutState from '../../hooks/useLayoutState';
@ -63,6 +70,7 @@ const getAlgorithm = (themes: ThemeName[] = []) =>
const GlobalLayout: React.FC = () => {
const outlet = useOutlet();
const { pathname } = useLocation();
const params = useParams();
const [searchParams, setSearchParams] = useSearchParams();
const [{ theme = [], direction, isMobile, bannerVisible = false }, setSiteState] =
useLayoutState<SiteState>({
@ -72,6 +80,9 @@ const GlobalLayout: React.FC = () => {
bannerVisible: false,
});
// TODO: This can be remove in v6
const useCssVar = searchParams.get('cssVar') !== 'false';
const updateSiteConfig = useCallback(
(props: SiteState) => {
setSiteState((prev) => ({ ...prev, ...props }));
@ -152,8 +163,8 @@ const GlobalLayout: React.FC = () => {
() => ({
algorithm: getAlgorithm(theme),
token: { motion: !theme.includes('motion-off') },
cssVar: true,
hashed: false,
cssVar: useCssVar,
hashed: !useCssVar,
}),
[theme],
);
@ -222,7 +233,17 @@ const GlobalLayout: React.FC = () => {
>
<SiteContext.Provider value={siteContextValue}>
<SiteThemeProvider theme={themeConfig}>
<HappyProvider disabled={!theme.includes('happy-work')}>{content}</HappyProvider>
<HappyProvider disabled={!theme.includes('happy-work')}>
{content}
<Monitoring
apiKey="GhrCCNrHZHXlf4P6E03ntrFwhRLxJL30" // Safe to expose publically
url="https://monitoring.react-scan.com/api/v1/ingest"
commit={process.env.COMMIT_HASH}
branch={process.env.BRANCH}
params={params as Record<string, string>}
path={pathname}
/>
</HappyProvider>
</SiteThemeProvider>
</SiteContext.Provider>
</StyleProvider>

View File

@ -35,7 +35,7 @@
"app.demo.codepen": "Open in CodePen",
"app.demo.codesandbox": "Open in CodeSandbox",
"app.demo.stackblitz": "Open in Stackblitz",
"app.demo.riddle": "Open in Riddle",
"app.demo.codeblock": "Open in Hitu",
"app.demo.separate": "Open in a new window",
"app.demo.online": "Online Address",
"app.home.introduce": "A design system for enterprise-level products. Create an efficient and enjoyable work experience.",

View File

@ -35,7 +35,7 @@
"app.demo.codepen": "在 CodePen 中打开",
"app.demo.codesandbox": "在 CodeSandbox 中打开",
"app.demo.stackblitz": "在 Stackblitz 中打开",
"app.demo.riddle": "在 Riddle 中打开",
"app.demo.codeblock": "在海兔中打开",
"app.demo.separate": "在新窗口打开",
"app.demo.online": "线上地址",
"app.home.introduce": "企业级产品设计体系,创造高效愉悦的工作体验",

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import { removeCSS, updateCSS } from '@rc-component/util/lib/Dom/dynamicCSS';
import { createStyles } from 'antd-style';
import { removeCSS, updateCSS } from 'rc-util/lib/Dom/dynamicCSS';
import useLocale from '../../../hooks/useLocale';

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

@ -5,7 +5,7 @@ on:
- cron: "0 0 * * *" # Run at 00:00 every day
permissions:
issues: write # Need write permission to modify issue assignees
issues: write
jobs:
reminder_job:
@ -19,12 +19,14 @@ jobs:
let page = 1;
const perPage = 100;
const reminderSignature = "This issue has been inactive for more than 14 days";
while (true) {
const { data: issues } = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
assignee: '*', // Filter assigned issues
assignee: '*',
per_page: perPage,
page: page,
});
@ -53,6 +55,19 @@ jobs:
);
if (daysInactive >= daysBeforeReminder && !hasLinkedPR) {
// get issue comments
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
});
// check if reminder has been sent
const hasReminder = comments.some(comment =>
comment.body.includes(reminderSignature)
);
if (!hasReminder) {
const assigneesMentions = issue.assignees
.map(user => `@${user.login}`)
.join(' ');
@ -65,6 +80,7 @@ jobs:
});
}
}
}
page += 1;
}

View File

@ -117,7 +117,7 @@ jobs:
cd ..
- name: Upload to Release
uses: softprops/action-gh-release@7b4da11513bf3f43f9999e90eabced41ab8bb048 # v2.2.0
uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0
with:
fail_on_unmatched_files: true
files: website.tar.gz

View File

@ -5,6 +5,8 @@ const compileModules = [
'@ant-design',
'countup.js',
'.pnpm',
'@asamuzakjp/css-color',
'@rc-component',
];
const ignoreList = [];

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,83 @@ tag: vVERSION
---
## 5.23.1
`2025-01-13`
- 🆕 Add Tree leaf node className for differentiate node type. [#52274](https://github.com/ant-design/ant-design/pull/52274) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 🐞 Fix DatePicker switch buttons is not hidden when `superPrevIcon/superNextIcon/prevIcon/nextIcon` is null. [#52327](https://github.com/ant-design/ant-design/pull/52327) [@afc163](https://github.com/afc163)
- 🐞 Fix Select throws `error not a valid selector` in Jest tests. [#51844](https://github.com/ant-design/ant-design/pull/51844) [@renovate](https://github.com/renovate)
- 🐞 Fix Layout.Sider under ConfigProvider directly, the `theme` not working. [#52302](https://github.com/ant-design/ant-design/pull/52302) [@zombieJ](https://github.com/zombieJ)
- 🐞 Fix Splitter lost previous state when re-expanding. [#52222](https://github.com/ant-design/ant-design/pull/52222) [@jjlstruggle](https://github.com/jjlstruggle)
- 🐞 Fix Table unexpected row selections when set `checkStrictly` to false in tree mode. [#52338](https://github.com/ant-design/ant-design/pull/52338) [@LeeSSHH](https://github.com/LeeSSHH)
- Button
- 🐞 Fix Button alignment and icon centering by adjusting the icon size for icon-only Buttons. [#52353](https://github.com/ant-design/ant-design/pull/52353) [@afc163](https://github.com/afc163)
- 💄 Fix Button missing `box-shadow` style. [#52304](https://github.com/ant-design/ant-design/pull/52304) [@zombieJ](https://github.com/zombieJ)
- RTL
- 💄 Fix Collapse arrow direction in RTL mode. [#52374](https://github.com/ant-design/ant-design/pull/52374) [@aojunhao123](https://github.com/aojunhao123)
- 💄 Fix Layout.Sider arrow direction in RTL mode. [#52374](https://github.com/ant-design/ant-design/pull/52374) [@aojunhao123](https://github.com/aojunhao123)
## 5.23.0
`2025-01-06`
- 🔥 TreeSelect support `maxCount` to limit the maximum number of selections. [#51759](https://github.com/ant-design/ant-design/pull/51759) [@aojunhao123](https://github.com/aojunhao123)
- 🔥 Modal `width` support responsive size. [#51653](https://github.com/ant-design/ant-design/pull/51653) [@zombieJ](https://github.com/zombieJ)
- 🔥 Splitter support `lazy` mode. [#51557](https://github.com/ant-design/ant-design/pull/51557) [@OysterD3](https://github.com/OysterD3)
- Button
- 🔥 Button `color` support full color palette. [#51550](https://github.com/ant-design/ant-design/pull/51550) [@OysterD3](https://github.com/OysterD3)
<img width="520" alt="Button Colors" src="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*ApyYQpXQQfgAAAAAAAAAAAAADgCCAQ/original">
- 🆕 Button support `loading={{ icon: ReactNode }}` to customize loading icon. [#51758](https://github.com/ant-design/ant-design/pull/51758) [@zhangchao-wooc](https://github.com/zhangchao-wooc)
- Menu
- 🐞 Fix Menu `extra` font size and vertical align issue. [#52217](https://github.com/ant-design/ant-design/pull/52217) [@guoyunhe](https://github.com/guoyunhe)
- 🆕 Menu add token `subMenuItemSelectedColor` to resolve submenu title color being overrided by `itemSelectedColor`. [#52182](https://github.com/ant-design/ant-design/pull/52182) [@afc163](https://github.com/afc163)
- 🆕 Semantic Props
- 🆕 ConfigProvider support Empty semantic props `classNames` and `styles`. [#52208](https://github.com/ant-design/ant-design/pull/52208) [@thinkasany](https://github.com/thinkasany)
- 🆕 ConfigProvider support Popconfirm semantic props `classNames` and `styles`. [#52126](https://github.com/ant-design/ant-design/pull/52126) [@thinkasany](https://github.com/thinkasany)
- 🆕 ConfigProvider support Popover semantic props `classNames` and `styles`. [#52110](https://github.com/ant-design/ant-design/pull/52110) [@thinkasany](https://github.com/thinkasany)
- 🆕 ConfigProvider support Tooltip semantic props `classNames` and `styles`. [#51872](https://github.com/ant-design/ant-design/pull/51872) [@thinkasany](https://github.com/thinkasany)
- 🆕 ConfigProvider support Descriptions semantic props `classNames` and `styles`. [#52120](https://github.com/ant-design/ant-design/pull/52120) [@thinkasany](https://github.com/thinkasany)
- 🆕 ConfigProvider support Slider semantic props `classNames` and `styles`. [#52185](https://github.com/ant-design/ant-design/pull/52185) [@thinkasany](https://github.com/thinkasany)
- 🆕 Transfer support `showSearch` config `defaultValue` & `placeholder`. [#52125](https://github.com/ant-design/ant-design/pull/52125) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 🆕 Calendar now supports `showWeek` prop. [#52072](https://github.com/ant-design/ant-design/pull/52072) [@afc163](https://github.com/afc163)
- 🆕 Mentions support `onPopupScroll` props. [#51858](https://github.com/ant-design/ant-design/pull/51858) [@OysterD3](https://github.com/OysterD3)
- 🆕 Card support `bodyPaddingSM`, `headerPaddingSM`, `bodyPadding`, `headerPadding` component token. [#51762](https://github.com/ant-design/ant-design/pull/51762) [@thinkasany](https://github.com/thinkasany)
- 🆕 ColorPicker `presets` support `key` prop. [#51794](https://github.com/ant-design/ant-design/pull/51794) [@li-jia-nan](https://github.com/li-jia-nan)
- 🆕 Cascader support `optionSelectedColor` token. [#51769](https://github.com/ant-design/ant-design/pull/51769) [@thinkasany](https://github.com/thinkasany)
- Tree
- 🛠 Refactor Tree part code to Function Component for React 19 perf preparing. [#52209](https://github.com/ant-design/ant-design/pull/52209) [@li-jia-nan](https://github.com/li-jia-nan)
- 💄 Optimize Tree `disabled` & `selected` node display style. [#52173](https://github.com/ant-design/ant-design/pull/52173) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 🐞 Fix Slider crash when `tipFormatter` is undefined. [#52184](https://github.com/ant-design/ant-design/pull/52184) [@thinkasany](https://github.com/thinkasany)
- 🐞 Fix Layout.Sider `trigger` style not correct. [#46a8eff](https://github.com/ant-design/ant-design/commit/46a8eff) [@Wxh16144](https://github.com/Wxh16144)
- Table
- 🐞 Fix Table `fixedright` is not working in `expandable`. [#52176](https://github.com/ant-design/ant-design/pull/52176) [@afc163](https://github.com/afc163)
- 🐞 Fix Table sticky scrollbar not working in rtl direction. [#52176](https://github.com/ant-design/ant-design/pull/52176) [@afc163](https://github.com/afc163)
- 💄 Optimize Flex to always reset `margin` & `padding` for customize component. [#52170](https://github.com/ant-design/ant-design/pull/52170) [@li-jia-nan](https://github.com/li-jia-nan)
- 🐞 Fix DatePicker.RangePicker `needConfirm` sometime can switch panel without confirm. [#52102](https://github.com/ant-design/ant-design/pull/52102) [@Zyf665](https://github.com/Zyf665)
- 💄 Optimize Collapse focus styles and items border radius. [#52086](https://github.com/ant-design/ant-design/pull/52086) [@aojunhao123](https://github.com/aojunhao123)
- ⌨️ Add Radio.Group default `name` prop to improve a11y. [#52076](https://github.com/ant-design/ant-design/pull/52076) [@aojunhao123](https://github.com/aojunhao123)
- ⌨️ Input.Search add `type=search` by default. [#52083](https://github.com/ant-design/ant-design/pull/52083) [@Kaikiat1126](https://github.com/Kaikiat1126)
- ⌨️ Improve Tabs focus style for keyboard operation. [#52002](https://github.com/ant-design/ant-design/pull/52002) [@aojunhao123](https://github.com/aojunhao123)
- Segmented
- ⌨️ Optimize Segmented focus style to improve a11y. [#51934](https://github.com/ant-design/ant-design/pull/51934) [@aojunhao123](https://github.com/aojunhao123)
- ⌨️ Segmented support `name` prop to improve a11y. [#51725](https://github.com/ant-design/ant-design/pull/51725) [@thinkasany](https://github.com/thinkasany)
- 📦 MISC: Reduce bundle size by replacing `@ctrl/tinycolor` with `@ant-design/fast-color`. [#52190](https://github.com/ant-design/ant-design/pull/52190) [#52157](https://github.com/ant-design/ant-design/pull/52157) [@aojunhao123](https://github.com/aojunhao123)
- ⌨️ Adjust Input, InputNumber, Mentions, Textarea clear icon from `span` to `button` to improve a11y. [#52180](https://github.com/ant-design/ant-design/pull/52180) [@li-jia-nan](https://github.com/li-jia-nan)
- 🐞 MISC: Fix build error when using React 19. [#52168](https://github.com/ant-design/ant-design/pull/52168) [@zombieJ](https://github.com/zombieJ)
- TypeScript
- 🤖 Adjust Table `ref` type to React.Ref. [#52205](https://github.com/ant-design/ant-design/pull/52205) [@li-jia-nan](https://github.com/li-jia-nan)
- 🤖 Calendar export CalendarMode type. [#52160](https://github.com/ant-design/ant-design/pull/52160) [@Kaikiat1126](https://github.com/Kaikiat1126)
## 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`
@ -2025,7 +2102,7 @@ tag: vVERSION
- 💄 Adjust Select, TreeSelect, Cascader always show the `arrow` by default when multiple. [#41028](https://github.com/ant-design/ant-design/pull/41028)
- 🐞 Fix Form `Form.Item.useStatus` problem with sever-side-rendering. [#40977](https://github.com/ant-design/ant-design/pull/40977) [@AndyBoat](https://github.com/AndyBoat)
- 🐞 MISC: Fix arrow shape in some components. [#40971](https://github.com/ant-design/ant-design/pull/40971)
- 🐞 Fix Layout throw `React does not recognize the `suffixCls` prop on a DOM element` warning. [#40969](https://github.com/ant-design/ant-design/pull/40969)
- 🐞 Fix Layout throw "React does not recognize the `suffixCls` prop on a DOM element" warning. [#40969](https://github.com/ant-design/ant-design/pull/40969)
- 🐞 Fix Watermark that text will be displayed when the picture loads abnormally. [#40770](https://github.com/ant-design/ant-design/pull/40770) [@OriginRing](https://github.com/OriginRing)
- 🐞 Image support flip function in preview mode. Fix Image `fallback` when used in ssr. [#40660](https://github.com/ant-design/ant-design/pull/40660)
- 🐞 Fix Typography component is not centered in the Select component. [#40422](https://github.com/ant-design/ant-design/pull/40422) [@Yuiai01](https://github.com/Yuiai01)

View File

@ -15,6 +15,83 @@ tag: vVERSION
---
## 5.23.1
`2025-01-13`
- 🆕 新增 Tree 组件叶子节点的 className 用于区分节点类型。[#52274](https://github.com/ant-design/ant-design/pull/52274) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 🐞 修复 DatePicker `superPrevIcon/superNextIcon/prevIcon/nextIcon` 设置为 null 时切换按钮依旧存在的问题。[#52327](https://github.com/ant-design/ant-design/pull/52327) [@afc163](https://github.com/afc163)
- 🐞 修复 Select 组件在 jest 测试中报错 `not a valid selector` 的问题。[#51844](https://github.com/ant-design/ant-design/pull/51844) [@renovate](https://github.com/renovate)
- 🐞 修复 Layout.Sider 直接嵌套在 ConfigProvider 下时,`theme` 配置无效的问题。[#52302](https://github.com/ant-design/ant-design/pull/52302) [@zombieJ](https://github.com/zombieJ)
- 🐞 修复 Splitter 二次展开时丢失上一次状态的问题。[#52222](https://github.com/ant-design/ant-design/pull/52222) [@jjlstruggle](https://github.com/jjlstruggle)
- 🐞 修复 Table 树形展示且设置 `checkStrictly` 为 false 时,某些行被错误选中的问题。[#52338](https://github.com/ant-design/ant-design/pull/52338) [@LeeSSHH](https://github.com/LeeSSHH)
- Button
- 🐞 调整 Button 纯图标的大小从而修复按钮对齐和图标居中问题。[#52353](https://github.com/ant-design/ant-design/pull/52353) [@afc163](https://github.com/afc163)
- 💄 修复 Button 丢失阴影样式的问题。[#52304](https://github.com/ant-design/ant-design/pull/52304) [@zombieJ](https://github.com/zombieJ)
- RTL
- 💄 修复 Collapse 在 RTL 模式下的箭头方向。[#52374](https://github.com/ant-design/ant-design/pull/52374) [@aojunhao123](https://github.com/aojunhao123)
- 💄 修复 Layout.Sider 在 RTL 模式下的箭头方向。[#52374](https://github.com/ant-design/ant-design/pull/52374) [@aojunhao123](https://github.com/aojunhao123)
## 5.23.0
`2025-01-06`
- 🔥 TreeSelect 新增 `maxCount` 属性以限制最大选择数量。[#51759](https://github.com/ant-design/ant-design/pull/51759) [@aojunhao123](https://github.com/aojunhao123)
- 🔥 Modal `width` 支持响应式尺寸。[#51653](https://github.com/ant-design/ant-design/pull/51653) [@zombieJ](https://github.com/zombieJ)
- 🔥 Splitter 增加 `lazy` 模式。[#51557](https://github.com/ant-design/ant-design/pull/51557) [@OysterD3](https://github.com/OysterD3)
- Button
- 🔥 Button `color` 属性支持完整色板。[#51550](https://github.com/ant-design/ant-design/pull/51550) [@OysterD3](https://github.com/OysterD3)
<img width="520" alt="Button Colors" src="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*ApyYQpXQQfgAAAAAAAAAAAAADgCCAQ/original">
- 🆕 Button 组件新增 `loading={{ icon: ReactNode }}` 以自定义加载图标。[#51758](https://github.com/ant-design/ant-design/pull/51758) [@zhangchao-wooc](https://github.com/zhangchao-wooc)
- Menu
- 🆕 Menu 新增 token `subMenuItemSelectedColor`,避免 `itemSelectedColor` 覆盖子菜单标题样式。[#52182](https://github.com/ant-design/ant-design/pull/52182) [@afc163](https://github.com/afc163)
- 🐞 修复 Menu `extra` 字体大小和垂直居中对齐问题。[#52217](https://github.com/ant-design/ant-design/pull/52217) [@guoyunhe](https://github.com/guoyunhe)
- 🆕 语义化
- 🆕 ConfigProvider 支持 Empty 组件语义化 `classNames``styles`。[#52208](https://github.com/ant-design/ant-design/pull/52208) [@thinkasany](https://github.com/thinkasany)
- 🆕 ConfigProvider 支持 Slider 组件语义化 `classNames``styles`。[#52185](https://github.com/ant-design/ant-design/pull/52185) [@thinkasany](https://github.com/thinkasany)
- 🆕 ConfigProvider 支持 Popconfirm 组件语义化 `classNames``styles`。[#52126](https://github.com/ant-design/ant-design/pull/52126) [@thinkasany](https://github.com/thinkasany)
- 🆕 ConfigProvider 支持 Popover 组件语义化 `classNames``styles`。[#52110](https://github.com/ant-design/ant-design/pull/52110) [@thinkasany](https://github.com/thinkasany)
- 🆕 ConfigProvider 支持 Tooltip 组件语义化 `classNames``styles`。[#51872](https://github.com/ant-design/ant-design/pull/51872) [@thinkasany](https://github.com/thinkasany)
- 🆕 ConfigProvider 支持 Descriptions 组件语义化 `classNames``styles`。[#52120](https://github.com/ant-design/ant-design/pull/52120) [@thinkasany](https://github.com/thinkasany)
- Tree
- 🛠 重构 Tree 部分代码为 Function Component 以为 React 19 做更好性能准备。[#52209](https://github.com/ant-design/ant-design/pull/52209) [@li-jia-nan](https://github.com/li-jia-nan)
- 💄 优化 Tree `disabled``selected` 节点状态下的颜色展示。[#52173](https://github.com/ant-design/ant-design/pull/52173) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 🆕 Transfer 支持 `showSearch` 配置 `defaultValue``placeholder`。[#52125](https://github.com/ant-design/ant-design/pull/52125) [@EmilyyyLiu](https://github.com/EmilyyyLiu)
- 🆕 Calendar 支持 `showWeek` 属性用于显示周数列。[#52072](https://github.com/ant-design/ant-design/pull/52072) [@afc163](https://github.com/afc163)
- 🆕 Mentions 新增 `onPopupScroll` 属性。[#51858](https://github.com/ant-design/ant-design/pull/51858) [@OysterD3](https://github.com/OysterD3)
- 🆕 Card 增加 `bodyPaddingSM`、`headerPaddingSM`、`bodyPadding`、`headerPadding` 组件 token。[#51762](https://github.com/ant-design/ant-design/pull/51762) [@thinkasany](https://github.com/thinkasany)
- 🆕 ColorPicker `presets` 支持传入 `key`。[#51794](https://github.com/ant-design/ant-design/pull/51794) [@li-jia-nan](https://github.com/li-jia-nan)
- 🆕 Cascader 新增 `optionSelectedColor` token。[#51769](https://github.com/ant-design/ant-design/pull/51769) [@thinkasany](https://github.com/thinkasany)
- 🐞 修复 Layout.Sider `trigger` 样式不正确的问题。[#46a8eff](https://github.com/ant-design/ant-design/commit/46a8eff) [@Wxh16144](https://github.com/Wxh16144)
- Table
- 🐞 修复 Table `expandable` 中设置 `fixedright` 不生效的问题。[#52176](https://github.com/ant-design/ant-design/pull/52176) [@afc163](https://github.com/afc163)
- 🐞 修复 Table `sticky` 模式下水平固定滚动条在 rtl 模式下不生效的问题。[#52176](https://github.com/ant-design/ant-design/pull/52176) [@afc163](https://github.com/afc163)
- 💄 优化 Flex 使其在自定义渲染组件时总是重置 `margin`、`padding` 样式。[#52170](https://github.com/ant-design/ant-design/pull/52170) [@li-jia-nan](https://github.com/li-jia-nan)
- 🐞 修复 DatePicker.RangePicker `needConfirm` 模式偶尔在不确认仍然可以切换面板的问题。[#52102](https://github.com/ant-design/ant-design/pull/52102) [@Zyf665](https://github.com/Zyf665)
- 🐞 修复 Slider 当 `tipFormatter` 未定义时导致崩溃的问题。[#52184](https://github.com/ant-design/ant-design/pull/52184) [@thinkasany](https://github.com/thinkasany)
- 💄 优化 Collapse 聚焦样式以及折叠项圆角。[#52086](https://github.com/ant-design/ant-design/pull/52086) [@aojunhao123](https://github.com/aojunhao123)
- ⌨️ 为 Radio.Group 添加默认 `name` 属性以提升无障碍体验。[#52076](https://github.com/ant-design/ant-design/pull/52076) [@aojunhao123](https://github.com/aojunhao123)
- ⌨️ Input.Search 添加默认 `type=search` 类型。[#52083](https://github.com/ant-design/ant-design/pull/52083) [@Kaikiat1126](https://github.com/Kaikiat1126)
- ⌨️ 优化 Tabs 键盘操作时的焦点样式。[#52002](https://github.com/ant-design/ant-design/pull/52002) [@aojunhao123](https://github.com/aojunhao123)
- Segmented
- ⌨️ 优化 Segmented 聚焦样式以提升无障碍体验。[#51934](https://github.com/ant-design/ant-design/pull/51934) [@aojunhao123](https://github.com/aojunhao123)
- ⌨️ Segmented 支持 `name` 属性以提升无障碍体验。[#51725](https://github.com/ant-design/ant-design/pull/51725) [@thinkasany](https://github.com/thinkasany)
- 📦 MISC: 用 `@ant-design/fast-color` 替换 `@ctrl/tinycolor` 以降低打包体积。[#52190](https://github.com/ant-design/ant-design/pull/52190) [#52157](https://github.com/ant-design/ant-design/pull/52157) [@aojunhao123](https://github.com/aojunhao123)
- ⌨️ 调整 Input、InputNumber、Mentions、Textarea 组件清除图标从 `span` 元素更改为 `button` 元素,提高了可访问性和交互性。[#52180](https://github.com/ant-design/ant-design/pull/52180) [@li-jia-nan](https://github.com/li-jia-nan)
- 🐞 MISC: 修复 React 19 下构建报错的问题。[#52168](https://github.com/ant-design/ant-design/pull/52168) [@zombieJ](https://github.com/zombieJ)
- TypeScript
- 🤖 调整 Table `ref` 类型为 React.Ref。[#52205](https://github.com/ant-design/ant-design/pull/52205) [@li-jia-nan](https://github.com/li-jia-nan)
- 🤖 Calendar 导出 CalendarMode 类型。[#52160](https://github.com/ant-design/ant-design/pull/52160) [@Kaikiat1126](https://github.com/Kaikiat1126)
## 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`
@ -175,6 +252,7 @@ tag: vVERSION
- 💄 修改 Button `textHoverBg` 在悬浮状态下的背景色为 `colorFillTertiary`。[#51187](https://github.com/ant-design/ant-design/pull/51187) [@coding-ice](https://github.com/coding-ice)
- TypeScript
- 🤖 优化 Switch `eventHandler` 类型。[#51165](https://github.com/ant-design/ant-design/pull/51165) [@thinkasany](https://github.com/thinkasany)
## 5.21.3
`2024-10-09`
@ -2025,7 +2103,7 @@ tag: vVERSION
- 💄 调整 Select, TreeSelect, Cascader 在多选时总是默认显示下拉箭头。[#41028](https://github.com/ant-design/ant-design/pull/41028)
- 🐞 修复 Form 组件 `Form.Item.useStatus` 导致的服务端渲染问题。[#40977](https://github.com/ant-design/ant-design/pull/40977) [@AndyBoat](https://github.com/AndyBoat)
- 🐞 杂项:修复部分组件箭头形状问题。[#40971](https://github.com/ant-design/ant-design/pull/40971)
- 🐞 修复 Layout 报错 `React does not recognize the `suffixCls` prop on a DOM element` 的问题。[#40969](https://github.com/ant-design/ant-design/pull/40969)
- 🐞 修复 Layout 报错 "React does not recognize the `suffixCls` prop on a DOM element" 的问题。[#40969](https://github.com/ant-design/ant-design/pull/40969)
- 🐞 修复 Watermark 组件图片加载异常时的问题,默认展示文字。[#40770](https://github.com/ant-design/ant-design/pull/40770) [@OriginRing](https://github.com/OriginRing)
- 🐞 Image 预览新增图片翻转功能。并修复 Image `fallback` 在 ssr 下失效的问题。[#40660](https://github.com/ant-design/ant-design/pull/40660)
- 🐞 修复 Select 中使用 Typography 不居中的问题。[#40422](https://github.com/ant-design/ant-design/pull/40422) [@Yuiai01](https://github.com/Yuiai01)

View File

@ -8,7 +8,6 @@ exports[`antd exports modules correctly 1`] = `
"App",
"AutoComplete",
"Avatar",
"BackTop",
"Badge",
"Breadcrumb",
"Button",

View File

@ -1,5 +1,5 @@
import * as React from 'react';
import useState from 'rc-util/lib/hooks/useState';
import useState from '@rc-component/util/lib/hooks/useState';
import Button from '../button';
import type { ButtonProps, LegacyButtonType } from '../button/button';

View File

@ -1,5 +1,5 @@
import * as React from 'react';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import useMergedState from '@rc-component/util/lib/hooks/useMergedState';
import ConfigProvider, { ConfigContext } from '../config-provider';
import type { AnyObject } from './type';
@ -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

@ -21,7 +21,7 @@ jest.mock('react-dom', () => {
return realReactDOM;
});
jest.mock('rc-util/lib/Dom/isVisible', () => {
jest.mock('@rc-component/util/lib/Dom/isVisible', () => {
const mockFn = () => (global as any).isVisible;
return mockFn;
});

View File

@ -4,17 +4,11 @@ import { PresetColors } from '../theme/interface';
type InverseColor = `${PresetColorKey}-inverse`;
const inverseColors = PresetColors.map<InverseColor>((color) => `${color}-inverse`);
export const PresetStatusColorTypes = [
'success',
'processing',
'error',
'default',
'warning',
] as const;
export const PresetStatusColors = ['success', 'processing', 'error', 'default', 'warning'] as const;
export type PresetColorType = PresetColorKey | InverseColor;
export type PresetStatusColorType = (typeof PresetStatusColorTypes)[number];
export type PresetStatusColorType = (typeof PresetStatusColors)[number];
/**
* determine if the color keyword belongs to the `Ant Design` {@link PresetColors}.
@ -30,5 +24,5 @@ export function isPresetColor(color?: any, includeInverse = true) {
}
export function isPresetStatusColor(color?: any): color is PresetStatusColorType {
return PresetStatusColorTypes.includes(color);
return PresetStatusColors.includes(color);
}

View File

@ -1,8 +1,8 @@
import type { ReactNode } from 'react';
import React from 'react';
import CloseOutlined from '@ant-design/icons/CloseOutlined';
import pickAttrs from '@rc-component/util/lib/pickAttrs';
import type { DialogProps } from 'rc-dialog';
import pickAttrs from 'rc-util/lib/pickAttrs';
export type ClosableType = DialogProps['closable'];

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

@ -1,4 +1,4 @@
import raf from 'rc-util/lib/raf';
import raf from '@rc-component/util/lib/raf';
import { easeInOutCubic } from './easings';
import getScroll, { isWindow } from './getScroll';

View File

@ -1,5 +1,5 @@
import canUseDom from 'rc-util/lib/Dom/canUseDom';
import { isStyleSupport } from 'rc-util/lib/Dom/styleChecker';
import canUseDom from '@rc-component/util/lib/Dom/canUseDom';
import { isStyleSupport } from '@rc-component/util/lib/Dom/styleChecker';
export const canUseDocElement = () => canUseDom() && window.document.documentElement;

View File

@ -1,4 +1,4 @@
import raf from 'rc-util/lib/raf';
import raf from '@rc-component/util/lib/raf';
function throttleByAnimationFrame<T extends any[]>(fn: (...args: T) => void) {
let requestId: number | null;

View File

@ -1,5 +1,6 @@
import * as React from 'react';
import rcWarning, { resetWarned as rcResetWarned } from 'rc-util/lib/warning';
import rcWarning, { resetWarned as rcResetWarned } from '@rc-component/util/lib/warning';
import { resetWarned as deprecatedRcResetWarned } from 'rc-util/lib/warning';
export function noop() {}
@ -8,6 +9,7 @@ let deprecatedWarnList: Record<string, string[]> | null = null;
export function resetWarned() {
deprecatedWarnList = null;
rcResetWarned();
deprecatedRcResetWarned();
}
type Warning = (valid: boolean, component: string, message?: string) => void;

View File

@ -1,8 +1,8 @@
import * as React from 'react';
import raf from '@rc-component/util/lib/raf';
import { composeRef } from '@rc-component/util/lib/ref';
import classNames from 'classnames';
import CSSMotion from 'rc-motion';
import raf from 'rc-util/lib/raf';
import { composeRef } from 'rc-util/lib/ref';
import { getReactRender, type UnmountType } from '../../config-provider/UnstableContext';
import { TARGET_CLS } from './interface';

View File

@ -1,7 +1,7 @@
import React, { useContext, useRef } from 'react';
import isVisible from '@rc-component/util/lib/Dom/isVisible';
import { composeRef, getNodeRef, supportRef } from '@rc-component/util/lib/ref';
import classNames from 'classnames';
import isVisible from 'rc-util/lib/Dom/isVisible';
import { composeRef, getNodeRef, supportRef } from 'rc-util/lib/ref';
import type { ConfigConsumerProps } from '../../config-provider';
import { ConfigContext } from '../../config-provider';

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import useEvent from 'rc-util/lib/hooks/useEvent';
import raf from 'rc-util/lib/raf';
import useEvent from '@rc-component/util/lib/hooks/useEvent';
import raf from '@rc-component/util/lib/raf';
import { ConfigContext } from '../../config-provider';
import useToken from '../../theme/useToken';

View File

@ -1,5 +1,5 @@
import * as React from 'react';
import { spyElementPrototype } from 'rc-util/lib/test/domHook';
import { spyElementPrototype } from '@rc-component/util/lib/test/domHook';
import demoTest, { rootPropsTest } from '../../../tests/shared/demoTest';

View File

@ -1,7 +1,7 @@
import React from 'react';
import omit from '@rc-component/util/lib/omit';
import classNames from 'classnames';
import ResizeObserver from 'rc-resize-observer';
import omit from 'rc-util/lib/omit';
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame';
import type { ConfigConsumerProps } from '../config-provider';

View File

@ -5,10 +5,10 @@ import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
import CloseOutlined from '@ant-design/icons/CloseOutlined';
import ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled';
import InfoCircleFilled from '@ant-design/icons/InfoCircleFilled';
import pickAttrs from '@rc-component/util/lib/pickAttrs';
import { composeRef } from '@rc-component/util/lib/ref';
import classNames from 'classnames';
import CSSMotion from 'rc-motion';
import pickAttrs from 'rc-util/lib/pickAttrs';
import { composeRef } from 'rc-util/lib/ref';
import type { ClosableType } from '../_util/hooks/useClosable';
import { replaceElement } from '../_util/reactNode';

View File

@ -1,6 +1,6 @@
import React from 'react';
import { resetWarned } from '@rc-component/util/lib/warning';
import userEvent from '@testing-library/user-event';
import { resetWarned } from 'rc-util/lib/warning';
import Alert from '..';
import { accessibilityTest } from '../../../tests/shared/accessibilityTest';

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import useEvent from '@rc-component/util/lib/hooks/useEvent';
import classNames from 'classnames';
import useEvent from 'rc-util/lib/hooks/useEvent';
import scrollIntoView from 'scroll-into-view-if-needed';
import getScroll from '../_util/getScroll';

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { resetWarned } from 'rc-util/lib/warning';
import { resetWarned } from '@rc-component/util/lib/warning';
import scrollIntoView from 'scroll-into-view-if-needed';
import Anchor from '..';

View File

@ -2,7 +2,6 @@ import React from 'react';
import userEvent from '@testing-library/user-event';
import AutoComplete from '..';
import { resetWarned } from '../../_util/warning';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { render, screen } from '../../../tests/utils';
@ -97,24 +96,4 @@ describe('AutoComplete', () => {
);
expect(screen.getByRole('combobox')).toHaveClass('custom');
});
it('deprecated dropdownClassName', () => {
resetWarned();
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
const { container } = render(
<AutoComplete
dropdownClassName="legacy"
open
options={[{ label: 'little', value: 'little' }]}
searchValue="l"
/>,
);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: AutoComplete] `dropdownClassName` is deprecated. Please use `popupClassName` instead.',
);
expect(container.querySelector('.legacy')).toBeTruthy();
errSpy.mockRestore();
});
});

View File

@ -1,8 +1,8 @@
import * as React from 'react';
import toArray from '@rc-component/util/lib/Children/toArray';
import omit from '@rc-component/util/lib/omit';
import classNames from 'classnames';
import type { BaseSelectRef } from 'rc-select';
import toArray from 'rc-util/lib/Children/toArray';
import omit from 'rc-util/lib/omit';
import { useZIndex } from '../_util/hooks/useZIndex';
import genPurePanel from '../_util/PurePanel';
@ -38,8 +38,6 @@ export interface AutoCompleteProps<
dataSource?: DataSourceItemType[];
status?: InputStatus;
popupClassName?: string;
/** @deprecated Please use `popupClassName` instead */
dropdownClassName?: string;
/** @deprecated Please use `popupMatchSelectWidth` instead */
dropdownMatchSelectWidth?: boolean | number;
popupMatchSelectWidth?: boolean | number;
@ -53,14 +51,7 @@ const AutoComplete: React.ForwardRefRenderFunction<RefSelectProps, AutoCompleteP
props,
ref,
) => {
const {
prefixCls: customizePrefixCls,
className,
popupClassName,
dropdownClassName,
children,
dataSource,
} = props;
const { prefixCls: customizePrefixCls, className, popupClassName, children, dataSource } = props;
const childNodes: React.ReactElement[] = toArray(children);
// ============================= Input =============================
@ -120,8 +111,6 @@ const AutoComplete: React.ForwardRefRenderFunction<RefSelectProps, AutoCompleteP
'usage',
'You need to control style self instead of setting `size` when using customize input.',
);
warning.deprecated(!dropdownClassName, 'dropdownClassName', 'popupClassName');
}
const { getPrefixCls } = React.useContext<ConfigConsumerProps>(ConfigContext);
@ -135,9 +124,9 @@ const AutoComplete: React.ForwardRefRenderFunction<RefSelectProps, AutoCompleteP
<Select
ref={ref}
suffixIcon={null}
{...omit(props, ['dataSource', 'dropdownClassName'])}
{...omit(props, ['dataSource'])}
prefixCls={prefixCls}
popupClassName={popupClassName || dropdownClassName}
popupClassName={popupClassName}
dropdownStyle={{
...props.dropdownStyle,
zIndex,
@ -170,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

@ -441,6 +441,7 @@ Array [
</span>
</span>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-circle"
style="color: rgb(245, 106, 0); background-color: rgb(253, 227, 207);"
>
@ -464,12 +465,14 @@ Array [
>
<div
class="ant-popover-inner"
id="test-id"
role="tooltip"
>
<div
class="ant-popover-inner-content"
>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-circle ant-avatar-icon"
style="background-color: rgb(135, 208, 104);"
>
@ -506,6 +509,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
Ant User
@ -731,6 +735,7 @@ Array [
</span>
</a>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-circle ant-avatar-icon"
style="background-color: rgb(135, 208, 104);"
>
@ -767,6 +772,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
Ant User
@ -824,6 +830,7 @@ Array [
</span>
</span>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-circle"
style="color: rgb(245, 106, 0); background-color: rgb(253, 227, 207);"
>
@ -847,12 +854,14 @@ Array [
>
<div
class="ant-popover-inner"
id="test-id"
role="tooltip"
>
<div
class="ant-popover-inner-content"
>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-circle ant-avatar-icon"
style="background-color: rgb(135, 208, 104);"
>
@ -889,6 +898,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
Ant User
@ -950,6 +960,7 @@ Array [
</span>
</span>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-lg ant-avatar-circle"
style="color: rgb(245, 106, 0); background-color: rgb(253, 227, 207);"
>
@ -973,12 +984,14 @@ Array [
>
<div
class="ant-popover-inner"
id="test-id"
role="tooltip"
>
<div
class="ant-popover-inner-content"
>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-lg ant-avatar-circle ant-avatar-icon"
style="background-color: rgb(135, 208, 104);"
>
@ -1015,6 +1028,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
Ant User
@ -1076,6 +1090,7 @@ Array [
</span>
</span>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-lg ant-avatar-circle"
style="color: rgb(245, 106, 0); background-color: rgb(253, 227, 207); cursor: pointer;"
>
@ -1099,12 +1114,14 @@ Array [
>
<div
class="ant-popover-inner"
id="test-id"
role="tooltip"
>
<div
class="ant-popover-inner-content"
>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-lg ant-avatar-circle ant-avatar-icon"
style="background-color: rgb(135, 208, 104);"
>
@ -1141,6 +1158,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
Ant User

View File

@ -437,6 +437,7 @@ Array [
</span>
</span>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-circle"
style="color:#f56a00;background-color:#fde3cf"
>
@ -632,6 +633,7 @@ Array [
</span>
</a>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-circle ant-avatar-icon"
style="background-color:#87d068"
>
@ -706,6 +708,7 @@ Array [
</span>
</span>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-circle"
style="color:#f56a00;background-color:#fde3cf"
>
@ -743,6 +746,7 @@ Array [
</span>
</span>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-lg ant-avatar-circle"
style="color:#f56a00;background-color:#fde3cf"
>
@ -780,6 +784,7 @@ Array [
</span>
</span>
<span
aria-describedby="test-id"
class="ant-avatar ant-avatar-lg ant-avatar-circle"
style="color:#f56a00;background-color:#fde3cf;cursor:pointer"
>

View File

@ -1,7 +1,7 @@
import * as React from 'react';
import { composeRef } from '@rc-component/util/lib/ref';
import classNames from 'classnames';
import ResizeObserver from 'rc-resize-observer';
import { composeRef } from 'rc-util/lib/ref';
import type { Breakpoint } from '../_util/responsiveObserver';
import { responsiveArray } from '../_util/responsiveObserver';

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import toArray from '@rc-component/util/lib/Children/toArray';
import classNames from 'classnames';
import toArray from 'rc-util/lib/Children/toArray';
import { cloneElement } from '../_util/reactNode';
import { devUseWarning } from '../_util/warning';
@ -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

@ -1,59 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders components/back-top/demo/basic.tsx extend context correctly 1`] = `
Array [
<div
class="ant-back-top"
/>,
Scroll down to see the bottom-right,
<strong
class="site-back-top-basic"
>
gray
</strong>,
button.,
]
`;
exports[`renders components/back-top/demo/basic.tsx extend context correctly 2`] = `
[
"Warning: [antd: BackTop] \`BackTop\` is deprecated. Please use \`FloatButton.BackTop\` instead.",
]
`;
exports[`renders components/back-top/demo/custom.tsx extend context correctly 1`] = `
<div
style="height: 600vh; padding: 8px;"
>
<div>
Scroll to bottom
</div>
<div>
Scroll to bottom
</div>
<div>
Scroll to bottom
</div>
<div>
Scroll to bottom
</div>
<div>
Scroll to bottom
</div>
<div>
Scroll to bottom
</div>
<div>
Scroll to bottom
</div>
<div
class="ant-back-top"
/>
</div>
`;
exports[`renders components/back-top/demo/custom.tsx extend context correctly 2`] = `
[
"Warning: [antd: BackTop] \`BackTop\` is deprecated. Please use \`FloatButton.BackTop\` instead.",
]
`;

View File

@ -1,47 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders components/back-top/demo/basic.tsx correctly 1`] = `
Array [
<div
class="ant-back-top"
/>,
Scroll down to see the bottom-right,
<strong
class="site-back-top-basic"
>
gray
</strong>,
button.,
]
`;
exports[`renders components/back-top/demo/custom.tsx correctly 1`] = `
<div
style="height:600vh;padding:8px"
>
<div>
Scroll to bottom
</div>
<div>
Scroll to bottom
</div>
<div>
Scroll to bottom
</div>
<div>
Scroll to bottom
</div>
<div>
Scroll to bottom
</div>
<div>
Scroll to bottom
</div>
<div>
Scroll to bottom
</div>
<div
class="ant-back-top"
/>
</div>
`;

View File

@ -1,7 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`BackTop rtl render component should be rendered correctly in RTL direction 1`] = `
<div
class="ant-back-top ant-back-top-rtl"
/>
`;

View File

@ -1,5 +0,0 @@
import accessibilityDemoTest from '../../../tests/shared/accessibilityTest';
describe('back-top demo a11y', () => {
accessibilityDemoTest('back-top');
});

View File

@ -1,3 +0,0 @@
import { extendTest } from '../../../tests/shared/demoTest';
extendTest('back-top');

View File

@ -1,3 +0,0 @@
import demoTest from '../../../tests/shared/demoTest';
demoTest('back-top');

View File

@ -1,55 +0,0 @@
import React from 'react';
import BackTop from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { fireEvent, render, waitFakeTimer } from '../../../tests/utils';
describe('BackTop', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
mountTest(BackTop);
rtlTest(BackTop);
it('should scroll to top after click it', async () => {
const { container } = render(<BackTop />);
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((_, y) => {
window.scrollY = y;
window.pageYOffset = y;
document.documentElement.scrollTop = y;
});
window.scrollTo(0, 400);
await waitFakeTimer();
expect(document.documentElement.scrollTop).toBe(400);
fireEvent.click(container.querySelector<HTMLDivElement>('.ant-back-top')!);
await waitFakeTimer();
expect(document.documentElement.scrollTop).toBe(0);
scrollToSpy.mockRestore();
});
it('support onClick', () => {
const onClick = jest.fn();
const { container } = render(<BackTop onClick={onClick} visibilityHeight={0} />);
fireEvent.click(container.querySelector<HTMLDivElement>('.ant-back-top')!);
expect(onClick).toHaveBeenCalled();
});
it('invalid target', () => {
const onClick = jest.fn();
const { container } = render(<BackTop onClick={onClick} target={undefined} />);
fireEvent.click(container.querySelector<HTMLDivElement>('.ant-back-top')!);
expect(onClick).toHaveBeenCalled();
});
it('should console Error', () => {
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
render(<BackTop />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: BackTop] `BackTop` is deprecated. Please use `FloatButton.BackTop` instead.',
);
errSpy.mockRestore();
});
});

View File

@ -1,13 +0,0 @@
## zh-CN
最简单的用法。
## en-US
The most basic usage.
```css
.site-back-top-basic {
color: rgba(64, 64, 64, 0.6);
}
```

View File

@ -1,13 +0,0 @@
import React from 'react';
import { BackTop } from 'antd';
const App: React.FC = () => (
<>
<BackTop />
Scroll down to see the bottom-right
<strong className="site-back-top-basic"> gray </strong>
button.
</>
);
export default App;

View File

@ -1,11 +0,0 @@
## zh-CN
可以自定义回到顶部按钮的样式,限制宽高:`40px * 40px`。
> 注意:`BackTop` 需要一个可接受 `onClick` 事件的元素作为 `children`。 如果您直接将文本作为子项放置,则该组件将无法正常运行。
## en-US
You can customize the style of the button, just note the size limit: no more than `40px * 40px`.
> Note: `BackTop` expects a element could accept `onClick` property as children. If you put a text directly as children the component will not function properly.

View File

@ -1,30 +0,0 @@
import React from 'react';
import { BackTop } from 'antd';
const style: React.CSSProperties = {
height: 40,
width: 40,
lineHeight: '40px',
borderRadius: 4,
backgroundColor: '#1088e9',
color: '#fff',
textAlign: 'center',
fontSize: 14,
};
const App: React.FC = () => (
<div style={{ height: '600vh', padding: 8 }}>
<div>Scroll to bottom</div>
<div>Scroll to bottom</div>
<div>Scroll to bottom</div>
<div>Scroll to bottom</div>
<div>Scroll to bottom</div>
<div>Scroll to bottom</div>
<div>Scroll to bottom</div>
<BackTop>
<div style={style}>UP</div>
</BackTop>
</div>
);
export default App;

View File

@ -1,128 +0,0 @@
import * as React from 'react';
import VerticalAlignTopOutlined from '@ant-design/icons/VerticalAlignTopOutlined';
import classNames from 'classnames';
import CSSMotion from 'rc-motion';
import omit from 'rc-util/lib/omit';
import getScroll from '../_util/getScroll';
import { cloneElement } from '../_util/reactNode';
import scrollTo from '../_util/scrollTo';
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame';
import { devUseWarning } from '../_util/warning';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigContext } from '../config-provider';
import useStyle from './style';
export interface BackTopProps {
visibilityHeight?: number;
onClick?: React.MouseEventHandler<HTMLElement>;
target?: () => HTMLElement | Window | Document;
prefixCls?: string;
children?: React.ReactNode;
className?: string;
rootClassName?: string;
style?: React.CSSProperties;
duration?: number;
}
const BackTop: React.FC<BackTopProps> = (props) => {
const {
prefixCls: customizePrefixCls,
className,
rootClassName,
visibilityHeight = 400,
target,
onClick,
duration = 450,
} = props;
const [visible, setVisible] = React.useState<boolean>(visibilityHeight === 0);
const ref = React.useRef<HTMLDivElement>(null);
const getDefaultTarget = (): HTMLElement | Document | Window =>
ref.current?.ownerDocument || window;
const handleScroll = throttleByAnimationFrame(
(e: React.UIEvent<HTMLElement, UIEvent> | { target: any }) => {
const scrollTop = getScroll(e.target);
setVisible(scrollTop >= visibilityHeight);
},
);
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning('BackTop');
warning.deprecated(false, 'BackTop', 'FloatButton.BackTop');
}
React.useEffect(() => {
const getTarget = target || getDefaultTarget;
const container = getTarget();
handleScroll({ target: container });
container?.addEventListener('scroll', handleScroll);
return () => {
handleScroll.cancel();
container?.removeEventListener('scroll', handleScroll);
};
}, [target]);
const scrollToTop = (e: React.MouseEvent<HTMLDivElement>) => {
scrollTo(0, { getContainer: target || getDefaultTarget, duration });
onClick?.(e);
};
const { getPrefixCls, direction } = React.useContext<ConfigConsumerProps>(ConfigContext);
const prefixCls = getPrefixCls('back-top', customizePrefixCls);
const rootPrefixCls = getPrefixCls();
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
const classString = classNames(
hashId,
cssVarCls,
prefixCls,
{
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
rootClassName,
);
// fix https://fb.me/react-unknown-prop
const divProps = omit(props, [
'prefixCls',
'className',
'rootClassName',
'children',
'visibilityHeight',
'target',
]);
const defaultElement = (
<div className={`${prefixCls}-content`}>
<div className={`${prefixCls}-icon`}>
<VerticalAlignTopOutlined />
</div>
</div>
);
return wrapCSSVar(
<div {...divProps} className={classString} onClick={scrollToTop} ref={ref}>
<CSSMotion visible={visible} motionName={`${rootPrefixCls}-fade`}>
{({ className: motionClassName }) =>
cloneElement(props.children || defaultElement, ({ className: cloneCls }) => ({
className: classNames(motionClassName, cloneCls),
}))
}
</CSSMotion>
</div>,
);
};
if (process.env.NODE_ENV !== 'production') {
BackTop.displayName = 'BackTop';
}
export default BackTop;

View File

@ -1,158 +0,0 @@
import { unit } from '@ant-design/cssinjs';
import type { CSSObject } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
/** Component only token. Which will handle additional calculation of alias token */
export interface ComponentToken {
/**
* @desc z-index
* @descEN z-index of popup
*/
zIndexPopup: number;
}
type BackTopToken = FullToken<'BackTop'> & {
/**
* @desc BackTop
* @descEN Background color of BackTop
*/
backTopBackground: string;
/**
* @desc BackTop
* @descEN Text color of BackTop
*/
backTopColor: string;
/**
* @desc BackTop
* @descEN Hover background color of BackTop
*/
backTopHoverBackground: string;
/**
* @desc BackTop
* @descEN Font size of BackTop
*/
backTopFontSize: number;
/**
* @desc BackTop
* @descEN Size of BackTop
*/
backTopSize: number;
// Position
/**
* @desc BackTop
* @descEN Bottom offset of BackTop
*/
backTopBlockEnd: number | string;
/**
* @desc BackTop
* @descEN Right offset of BackTop
*/
backTopInlineEnd: number | string;
/**
* @desc BackTop
* @descEN Right offset of BackTop on medium screens
*/
backTopInlineEndMD: number | string;
/**
* @desc BackTop
* @descEN Right offset of BackTop on small screens
*/
backTopInlineEndXS: number | string;
};
// ============================== Shared ==============================
const genSharedBackTopStyle: GenerateStyle<BackTopToken, CSSObject> = (token): CSSObject => {
const { componentCls, backTopFontSize, backTopSize, zIndexPopup } = token;
return {
[componentCls]: {
...resetComponent(token),
position: 'fixed',
insetInlineEnd: token.backTopInlineEnd,
insetBlockEnd: token.backTopBlockEnd,
zIndex: zIndexPopup,
width: 40,
height: 40,
cursor: 'pointer',
'&:empty': {
display: 'none',
},
[`${componentCls}-content`]: {
width: backTopSize,
height: backTopSize,
overflow: 'hidden',
color: token.backTopColor,
textAlign: 'center',
backgroundColor: token.backTopBackground,
borderRadius: backTopSize,
transition: `all ${token.motionDurationMid}`,
'&:hover': {
backgroundColor: token.backTopHoverBackground,
transition: `all ${token.motionDurationMid}`,
},
},
// change to .backtop .backtop-icon
[`${componentCls}-icon`]: {
fontSize: backTopFontSize,
lineHeight: unit(backTopSize),
},
},
};
};
const genMediaBackTopStyle: GenerateStyle<BackTopToken> = (token): CSSObject => {
const { componentCls, screenMD, screenXS, backTopInlineEndMD, backTopInlineEndXS } = token;
return {
[`@media (max-width: ${unit(screenMD)})`]: {
[componentCls]: {
insetInlineEnd: backTopInlineEndMD,
},
},
[`@media (max-width: ${unit(screenXS)})`]: {
[componentCls]: {
insetInlineEnd: backTopInlineEndXS,
},
},
};
};
export const prepareComponentToken: GetDefaultToken<'BackTop'> = (token) => ({
zIndexPopup: token.zIndexBase + 10,
});
// ============================== Export ==============================
export default genStyleHooks(
'BackTop',
(token) => {
const {
fontSizeHeading3,
colorTextDescription,
colorTextLightSolid,
colorText,
controlHeightLG,
calc,
} = token;
const backTopToken = mergeToken<BackTopToken>(token, {
backTopBackground: colorTextDescription,
backTopColor: colorTextLightSolid,
backTopHoverBackground: colorText,
backTopFontSize: fontSizeHeading3,
backTopSize: controlHeightLG,
backTopBlockEnd: calc(controlHeightLG).mul(1.25).equal(),
backTopInlineEnd: calc(controlHeightLG).mul(2.5).equal(),
backTopInlineEndMD: calc(controlHeightLG).mul(1.5).equal(),
backTopInlineEndXS: calc(controlHeightLG).mul(0.5).equal(),
});
return [genSharedBackTopStyle(backTopToken), genMediaBackTopStyle(backTopToken)];
},
prepareComponentToken,
);

View File

@ -9,6 +9,8 @@ import useStyle from './style/ribbon';
type RibbonPlacement = 'start' | 'end';
type SemanticName = 'root' | 'content' | 'indicator';
export interface RibbonProps {
className?: string;
prefixCls?: string;
@ -18,6 +20,8 @@ export interface RibbonProps {
children?: React.ReactNode;
placement?: RibbonPlacement;
rootClassName?: string;
classNames?: Partial<Record<SemanticName, string>>;
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
}
const Ribbon: React.FC<RibbonProps> = (props) => {
@ -30,8 +34,10 @@ const Ribbon: React.FC<RibbonProps> = (props) => {
text,
placement = 'end',
rootClassName,
styles,
classNames: ribbonClassNames,
} = props;
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const { getPrefixCls, direction, ribbon } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('ribbon', customizePrefixCls);
const wrapperCls = `${prefixCls}-wrapper`;
@ -46,6 +52,9 @@ const Ribbon: React.FC<RibbonProps> = (props) => {
[`${prefixCls}-color-${color}`]: colorInPreset,
},
className,
ribbon?.className,
ribbon?.classNames?.indicator,
ribbonClassNames?.indicator,
);
const colorStyle: React.CSSProperties = {};
@ -55,10 +64,38 @@ const Ribbon: React.FC<RibbonProps> = (props) => {
cornerColorStyle.color = color;
}
return wrapCSSVar(
<div className={classNames(wrapperCls, rootClassName, hashId, cssVarCls)}>
<div
className={classNames(
wrapperCls,
rootClassName,
hashId,
cssVarCls,
ribbonClassNames?.root,
ribbon?.classNames?.root,
)}
style={{ ...ribbon?.styles?.root, ...styles?.root }}
>
{children}
<div className={classNames(ribbonCls, hashId)} style={{ ...colorStyle, ...style }}>
<span className={`${prefixCls}-text`}>{text}</span>
<div
className={classNames(ribbonCls, hashId)}
style={{
...colorStyle,
...ribbon?.styles?.indicator,
...ribbon?.style,
...styles?.indicator,
...style,
}}
>
<span
className={classNames(
`${prefixCls}-content`,
ribbonClassNames?.content,
ribbon?.classNames?.content,
)}
style={{ ...ribbon?.styles?.content, ...styles?.content }}
>
{text}
</span>
<div className={`${prefixCls}-corner`} style={cornerColorStyle} />
</div>
</div>,

View File

@ -2315,7 +2315,7 @@ exports[`renders components/badge/demo/ribbon.tsx extend context correctly 1`] =
class="ant-ribbon ant-ribbon-placement-end"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2357,7 +2357,7 @@ exports[`renders components/badge/demo/ribbon.tsx extend context correctly 1`] =
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-pink"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2399,7 +2399,7 @@ exports[`renders components/badge/demo/ribbon.tsx extend context correctly 1`] =
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-red"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2441,7 +2441,7 @@ exports[`renders components/badge/demo/ribbon.tsx extend context correctly 1`] =
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-cyan"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2483,7 +2483,7 @@ exports[`renders components/badge/demo/ribbon.tsx extend context correctly 1`] =
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-green"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2525,7 +2525,7 @@ exports[`renders components/badge/demo/ribbon.tsx extend context correctly 1`] =
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-purple"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2567,7 +2567,7 @@ exports[`renders components/badge/demo/ribbon.tsx extend context correctly 1`] =
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-volcano"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2609,7 +2609,7 @@ exports[`renders components/badge/demo/ribbon.tsx extend context correctly 1`] =
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-magenta"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2648,7 +2648,7 @@ exports[`renders components/badge/demo/ribbon-debug.tsx extend context correctly
class="ant-ribbon ant-ribbon-placement-end"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
啦啦啦啦
</span>
@ -2677,7 +2677,7 @@ exports[`renders components/badge/demo/ribbon-debug.tsx extend context correctly
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-purple"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
啦啦啦啦
</span>
@ -2707,7 +2707,7 @@ exports[`renders components/badge/demo/ribbon-debug.tsx extend context correctly
style="background: rgb(45, 183, 245);"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
啦啦啦啦
</span>
@ -2738,7 +2738,7 @@ exports[`renders components/badge/demo/ribbon-debug.tsx extend context correctly
style="background: rgb(45, 183, 245);"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
啦啦啦啦
</span>
@ -2769,7 +2769,7 @@ exports[`renders components/badge/demo/ribbon-debug.tsx extend context correctly
style="background: rgb(45, 183, 245);"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
啦啦啦啦
</span>

View File

@ -2294,7 +2294,7 @@ exports[`renders components/badge/demo/ribbon.tsx correctly 1`] = `
class="ant-ribbon ant-ribbon-placement-end"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2336,7 +2336,7 @@ exports[`renders components/badge/demo/ribbon.tsx correctly 1`] = `
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-pink"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2378,7 +2378,7 @@ exports[`renders components/badge/demo/ribbon.tsx correctly 1`] = `
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-red"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2420,7 +2420,7 @@ exports[`renders components/badge/demo/ribbon.tsx correctly 1`] = `
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-cyan"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2462,7 +2462,7 @@ exports[`renders components/badge/demo/ribbon.tsx correctly 1`] = `
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-green"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2504,7 +2504,7 @@ exports[`renders components/badge/demo/ribbon.tsx correctly 1`] = `
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-purple"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2546,7 +2546,7 @@ exports[`renders components/badge/demo/ribbon.tsx correctly 1`] = `
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-volcano"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2588,7 +2588,7 @@ exports[`renders components/badge/demo/ribbon.tsx correctly 1`] = `
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-magenta"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
Hippies
</span>
@ -2625,7 +2625,7 @@ exports[`renders components/badge/demo/ribbon-debug.tsx correctly 1`] = `
class="ant-ribbon ant-ribbon-placement-end"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
啦啦啦啦
</span>
@ -2654,7 +2654,7 @@ exports[`renders components/badge/demo/ribbon-debug.tsx correctly 1`] = `
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-color-purple"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
啦啦啦啦
</span>
@ -2684,7 +2684,7 @@ exports[`renders components/badge/demo/ribbon-debug.tsx correctly 1`] = `
style="background:#2db7f5"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
啦啦啦啦
</span>
@ -2715,7 +2715,7 @@ exports[`renders components/badge/demo/ribbon-debug.tsx correctly 1`] = `
style="background:#2db7f5"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
啦啦啦啦
</span>
@ -2746,7 +2746,7 @@ exports[`renders components/badge/demo/ribbon-debug.tsx correctly 1`] = `
style="background:#2db7f5"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
>
啦啦啦啦
</span>

View File

@ -8,7 +8,7 @@ exports[`Ribbon rtl render component should be rendered correctly in RTL directi
class="ant-ribbon ant-ribbon-placement-end ant-ribbon-rtl"
>
<span
class="ant-ribbon-text"
class="ant-ribbon-content"
/>
<div
class="ant-ribbon-corner"

View File

@ -80,4 +80,37 @@ describe('Ribbon', () => {
expect(container.querySelectorAll('.cool').length).toEqual(1);
});
});
it('should apply custom styles to Badge.Ribbon', () => {
const customClassNames = {
root: 'custom-root',
indicator: 'custom-indicator',
content: 'custom-content',
};
const customStyles = {
root: { color: 'red' },
indicator: { color: 'green' },
content: { color: 'yellow' },
};
const { container } = render(
<Badge.Ribbon text="Hippies" color="pink" classNames={customClassNames} styles={customStyles}>
<div>and raises the spyglass.</div>
</Badge.Ribbon>,
);
const rootElement = container.querySelector('.ant-ribbon-wrapper') as HTMLElement;
const indicatorElement = container.querySelector('.ant-ribbon') as HTMLElement;
const contentElement = container.querySelector('.ant-ribbon-content') as HTMLElement;
// check classNames
expect(rootElement.classList).toContain('custom-root');
expect(indicatorElement.classList).toContain('custom-indicator');
expect(contentElement.classList).toContain('custom-content');
// check styles
expect(rootElement.style.color).toBe('red');
expect(indicatorElement.style.color).toBe('green');
expect(contentElement.style.color).toBe('yellow');
});
});

View File

@ -0,0 +1,47 @@
import React from 'react';
import { Badge, Card } from 'antd';
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
import useLocale from '../../../.dumi/hooks/useLocale';
const locales = {
cn: {
root: '根节点',
indicator: '指示器节点',
content: '文本节点',
},
en: {
root: 'Root element',
indicator: 'Indicator element',
content: 'Text element',
},
};
const BlockList = (props: any) => {
return (
<div style={{ width: '100%' }}>
<Badge.Ribbon {...props} text="Hippies" color="pink">
<Card title="Pushes open the window" size="small">
and raises the spyglass.
</Card>
</Badge.Ribbon>
</div>
);
};
const App: React.FC = () => {
const [locale] = useLocale(locales);
return (
<SemanticPreview
semantics={[
{ name: 'root', desc: locale.root, version: '6.0.0' },
{ name: 'indicator', desc: locale.indicator, version: '6.0.0' },
{ name: 'content', desc: locale.content, version: '6.0.0' },
]}
>
<BlockList />
</SemanticPreview>
);
};
export default App;

View File

@ -64,8 +64,14 @@ Common props ref[Common props](/docs/react/common-props)
## Semantic DOM
### Badge
<code src="./demo/_semantic.tsx" simplify="true"></code>
### Badge.Ribbon
<code src="./demo/_semantic_ribbon.tsx" simplify="true"></code>
## Design Token
<ComponentTokenTable component="Badge"></ComponentTokenTable>

View File

@ -65,8 +65,14 @@ group: 数据展示
## Semantic DOM
### Badge
<code src="./demo/_semantic.tsx" simplify="true"></code>
### Badge.Ribbon
<code src="./demo/_semantic_ribbon.tsx" simplify="true"></code>
## 主题变量Design Token
<ComponentTokenTable component="Badge"></ComponentTokenTable>

View File

@ -33,7 +33,7 @@ const genRibbonStyle: GenerateStyle<BadgeToken> = (token) => {
whiteSpace: 'nowrap',
backgroundColor: token.colorPrimary,
borderRadius: token.borderRadiusSM,
[`${ribbonPrefixCls}-text`]: {
[`${ribbonPrefixCls}-content`]: {
color: token.badgeTextColor,
},
[`${ribbonPrefixCls}-corner`]: {

View File

@ -1,7 +1,7 @@
import * as React from 'react';
import toArray from '@rc-component/util/lib/Children/toArray';
import pickAttrs from '@rc-component/util/lib/pickAttrs';
import classNames from 'classnames';
import toArray from 'rc-util/lib/Children/toArray';
import pickAttrs from 'rc-util/lib/pickAttrs';
import { cloneElement } from '../_util/reactNode';
import type { AnyObject } from '../_util/type';
@ -29,8 +29,6 @@ export interface BreadcrumbItemType {
/** @deprecated Please use `title` instead */
breadcrumbName?: string;
menu?: BreadcrumbItemProps['menu'];
/** @deprecated Please use `menu` instead */
overlay?: React.ReactNode;
className?: string;
dropdownProps?: DropdownProps;
onClick?: React.MouseEventHandler<HTMLAnchorElement | HTMLSpanElement>;
@ -141,7 +139,6 @@ const Breadcrumb = <T extends AnyObject = AnyObject>(props: BreadcrumbProps<T>)
key,
type,
menu,
overlay,
onClick,
className: itemClassName,
separator: itemSeparator,
@ -164,8 +161,6 @@ const Breadcrumb = <T extends AnyObject = AnyObject>(props: BreadcrumbProps<T>)
if (menu) {
itemProps.menu = menu;
} else if (overlay) {
itemProps.overlay = overlay as any;
}
let { href } = item;

View File

@ -1,7 +1,5 @@
import * as React from 'react';
import DownOutlined from '@ant-design/icons/DownOutlined';
import { devUseWarning } from '../_util/warning';
import { ConfigContext } from '../config-provider';
import type { DropdownProps } from '../dropdown/dropdown';
import Dropdown from '../dropdown/dropdown';
@ -33,24 +31,14 @@ export interface BreadcrumbItemProps extends SeparatorType {
onClick?: React.MouseEventHandler<HTMLAnchorElement | HTMLSpanElement>;
className?: string;
children?: React.ReactNode;
// Deprecated
/** @deprecated Please use `menu` instead */
overlay?: DropdownProps['overlay'];
}
export const InternalBreadcrumbItem: React.FC<BreadcrumbItemProps> = (props) => {
const { prefixCls, separator = '/', children, menu, overlay, dropdownProps, href } = props;
// Warning for deprecated usage
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning('Breadcrumb.Item');
warning.deprecated(!('overlay' in props), 'overlay', 'menu');
}
const { prefixCls, separator = '/', children, menu, dropdownProps, href } = props;
/** If overlay is have Wrap a Dropdown */
const renderBreadcrumbNode = (breadcrumbItem: React.ReactNode) => {
if (menu || overlay) {
if (menu) {
const mergeDropDownProps: DropdownProps = {
...dropdownProps,
};
@ -73,8 +61,6 @@ export const InternalBreadcrumbItem: React.FC<BreadcrumbItemProps> = (props) =>
};
}),
};
} else if (overlay) {
mergeDropDownProps.overlay = overlay;
}
return (

View File

@ -1,6 +1,4 @@
import React from 'react';
import { resetWarned } from '../../_util/warning';
import { accessibilityTest } from '../../../tests/shared/accessibilityTest';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
@ -67,39 +65,6 @@ describe('Breadcrumb', () => {
expect(asFragment().firstChild).toMatchSnapshot();
});
describe('overlay deprecation warning set', () => {
it('legacy jsx', () => {
resetWarned();
render(
<Breadcrumb>
<Breadcrumb.Item overlay={<div>menu</div>}>
<a href="">General</a>
</Breadcrumb.Item>
</Breadcrumb>,
);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: Breadcrumb.Item] `overlay` is deprecated. Please use `menu` instead.',
);
});
it('items', () => {
resetWarned();
render(
<Breadcrumb
items={[
{
overlay: <div>menu</div>,
title: 'General',
},
]}
/>,
);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: Breadcrumb.Item] `overlay` is deprecated. Please use `menu` instead.',
);
});
});
it('Breadcrumb.Item deprecation warning', () => {
render(
<Breadcrumb>
@ -122,33 +87,6 @@ describe('Breadcrumb', () => {
);
});
// https://github.com/ant-design/ant-design/issues/40204
it('wrong overlay deprecation warning in Dropdown', () => {
const menuItems = [
{
key: '1',
label: (
<a target="_blank" rel="noopener noreferrer" href="http://www.alipay.com/">
General
</a>
),
},
];
render(
<Breadcrumb
items={[
{
menu: { items: menuItems },
title: <a href="">General</a>,
},
]}
/>,
);
expect(errorSpy).not.toHaveBeenCalledWith(
'Warning: [antd: Dropdown] `overlay` is deprecated. Please use `menu` instead.',
);
});
// https://github.com/ant-design/ant-design/issues/5015
it('should allow Breadcrumb.Item is null or undefined', () => {
const { asFragment } = render(
@ -325,20 +263,6 @@ describe('Breadcrumb', () => {
expect(container.firstChild).toMatchSnapshot();
});
it('should console Error when `overlay` in props', () => {
resetWarned();
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
render(
<Breadcrumb>
<Breadcrumb.Item overlay={<div>test</div>} />
</Breadcrumb>,
);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Breadcrumb.Item] `overlay` is deprecated. Please use `menu` instead.',
);
errSpy.mockRestore();
});
it('should not console Error when `overlay` not in props', () => {
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
render(<Breadcrumb items={[{ path: '/', title: 'Test' }]} />);

View File

@ -144,6 +144,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx extend context c
tabindex="0"
>
<li
aria-describedby="test-id"
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-1"
role="menuitem"
@ -174,11 +175,13 @@ exports[`renders components/breadcrumb/demo/component-token.tsx extend context c
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
/>
</div>
</div>
<li
aria-describedby="test-id"
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-2"
role="menuitem"
@ -209,11 +212,13 @@ exports[`renders components/breadcrumb/demo/component-token.tsx extend context c
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
/>
</div>
</div>
<li
aria-describedby="test-id"
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-3"
role="menuitem"
@ -244,6 +249,7 @@ exports[`renders components/breadcrumb/demo/component-token.tsx extend context c
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
/>
</div>
@ -402,6 +408,7 @@ exports[`renders components/breadcrumb/demo/debug-routes.tsx extend context corr
tabindex="0"
>
<li
aria-describedby="test-id"
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-0"
role="menuitem"
@ -430,11 +437,13 @@ exports[`renders components/breadcrumb/demo/debug-routes.tsx extend context corr
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
/>
</div>
</div>
<li
aria-describedby="test-id"
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-1"
role="menuitem"
@ -463,6 +472,7 @@ exports[`renders components/breadcrumb/demo/debug-routes.tsx extend context corr
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
/>
</div>
@ -563,6 +573,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx extend context correctly
tabindex="0"
>
<li
aria-describedby="test-id"
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-1"
role="menuitem"
@ -593,11 +604,13 @@ exports[`renders components/breadcrumb/demo/overlay.tsx extend context correctly
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
/>
</div>
</div>
<li
aria-describedby="test-id"
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-2"
role="menuitem"
@ -628,11 +641,13 @@ exports[`renders components/breadcrumb/demo/overlay.tsx extend context correctly
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
/>
</div>
</div>
<li
aria-describedby="test-id"
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-3"
role="menuitem"
@ -663,6 +678,7 @@ exports[`renders components/breadcrumb/demo/overlay.tsx extend context correctly
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
/>
</div>

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import pickAttrs from '@rc-component/util/lib/pickAttrs';
import classNames from 'classnames';
import pickAttrs from 'rc-util/lib/pickAttrs';
import type { BreadcrumbProps, InternalRouteType, ItemType } from './Breadcrumb';

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-small"
>
<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-small"
>
<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-small"
>
<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"
/>
@ -750,7 +907,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
Large
</span>
</label>
@ -762,6 +921,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="default"
/>
@ -769,7 +929,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
Default
</span>
</label>
@ -781,6 +943,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="small"
/>
@ -788,7 +951,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
Small
</span>
</label>
@ -810,6 +975,7 @@ Array [
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-lg ant-btn-icon-only"
type="button"
>
@ -850,6 +1016,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
search
@ -896,6 +1063,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg ant-btn-icon-only"
type="button"
>
@ -936,6 +1104,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
search
@ -978,6 +1147,7 @@ Array [
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg ant-btn-icon-only"
type="button"
>
@ -1018,6 +1188,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
search
@ -1056,6 +1227,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-dashed ant-btn-color-default ant-btn-variant-dashed ant-btn-lg ant-btn-icon-only"
type="button"
>
@ -1096,6 +1268,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
search
@ -1242,6 +1415,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"
@ -1598,6 +2001,7 @@ exports[`renders components/button/demo/icon.tsx extend context correctly 1`] =
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-icon-only"
type="button"
>
@ -1638,6 +2042,7 @@ exports[`renders components/button/demo/icon.tsx extend context correctly 1`] =
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
search
@ -1684,6 +2089,7 @@ exports[`renders components/button/demo/icon.tsx extend context correctly 1`] =
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only"
type="button"
>
@ -1724,6 +2130,7 @@ exports[`renders components/button/demo/icon.tsx extend context correctly 1`] =
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
search
@ -1766,6 +2173,7 @@ exports[`renders components/button/demo/icon.tsx extend context correctly 1`] =
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only"
type="button"
>
@ -1806,6 +2214,7 @@ exports[`renders components/button/demo/icon.tsx extend context correctly 1`] =
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
search
@ -1844,6 +2253,7 @@ exports[`renders components/button/demo/icon.tsx extend context correctly 1`] =
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-dashed ant-btn-color-default ant-btn-variant-dashed ant-btn-icon-only"
type="button"
>
@ -1884,6 +2294,7 @@ exports[`renders components/button/demo/icon.tsx extend context correctly 1`] =
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
search
@ -1976,6 +2387,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="start"
/>
@ -1983,7 +2395,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
start
</span>
</label>
@ -1996,6 +2410,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="end"
/>
@ -2003,7 +2418,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
end
</span>
</label>
@ -2027,6 +2444,7 @@ Array [
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-icon-only"
type="button"
>
@ -2067,6 +2485,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
search
@ -2113,6 +2532,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only"
type="button"
>
@ -2153,6 +2573,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
search
@ -2195,6 +2616,7 @@ Array [
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only"
type="button"
>
@ -2235,6 +2657,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
search
@ -2273,6 +2696,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-dashed ant-btn-color-default ant-btn-variant-dashed ant-btn-icon-only"
type="button"
>
@ -2313,6 +2737,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
search
@ -2440,6 +2865,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-sm ant-btn-icon-only"
disabled=""
type="button"
@ -2481,6 +2907,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
Tooltip
@ -2488,6 +2915,7 @@ Array [
</div>
</div>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-sm ant-btn-icon-only"
type="button"
>
@ -2528,6 +2956,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
Tooltip
@ -2556,6 +2985,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-icon-only"
disabled=""
type="button"
@ -2597,6 +3027,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
Tooltip
@ -2604,6 +3035,7 @@ Array [
</div>
</div>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-icon-only"
type="button"
>
@ -2644,6 +3076,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
Tooltip
@ -2672,6 +3105,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-lg ant-btn-icon-only"
disabled=""
type="button"
@ -2713,6 +3147,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
Tooltip
@ -2720,6 +3155,7 @@ Array [
</div>
</div>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-lg ant-btn-icon-only"
type="button"
>
@ -2760,6 +3196,7 @@ Array [
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
>
Tooltip
@ -2925,6 +3362,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 +3472,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>
`;
@ -3080,6 +3579,7 @@ exports[`renders components/button/demo/multiple.tsx extend context correctly 1`
tabindex="0"
>
<li
aria-describedby="test-id"
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-1"
role="menuitem"
@ -3104,11 +3604,13 @@ exports[`renders components/button/demo/multiple.tsx extend context correctly 1`
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
/>
</div>
</div>
<li
aria-describedby="test-id"
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-2"
role="menuitem"
@ -3133,11 +3635,13 @@ exports[`renders components/button/demo/multiple.tsx extend context correctly 1`
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
/>
</div>
</div>
<li
aria-describedby="test-id"
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
data-menu-id="rc-menu-uuid-test-3"
role="menuitem"
@ -3162,6 +3666,7 @@ exports[`renders components/button/demo/multiple.tsx extend context correctly 1`
>
<div
class="ant-tooltip-inner"
id="test-id"
role="tooltip"
/>
</div>
@ -3192,6 +3697,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="large"
/>
@ -3199,7 +3705,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
Large
</span>
</label>
@ -3211,6 +3719,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="default"
/>
@ -3218,7 +3727,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
Default
</span>
</label>
@ -3230,6 +3741,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="small"
/>
@ -3237,7 +3749,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
Small
</span>
</label>

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-small"
>
<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-small"
>
<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-small"
>
<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"
/>
@ -734,7 +891,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
Large
</span>
</label>
@ -746,6 +905,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="default"
/>
@ -753,7 +913,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
Default
</span>
</label>
@ -765,6 +927,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="small"
/>
@ -772,7 +935,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
Small
</span>
</label>
@ -794,6 +959,7 @@ Array [
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-lg ant-btn-icon-only"
type="button"
>
@ -861,6 +1027,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg ant-btn-icon-only"
type="button"
>
@ -924,6 +1091,7 @@ Array [
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-lg ant-btn-icon-only"
type="button"
>
@ -983,6 +1151,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-dashed ant-btn-color-default ant-btn-variant-dashed ant-btn-lg ant-btn-icon-only"
type="button"
>
@ -1150,6 +1319,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"
@ -1500,6 +1899,7 @@ exports[`renders components/button/demo/icon.tsx correctly 1`] = `
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-icon-only"
type="button"
>
@ -1567,6 +1967,7 @@ exports[`renders components/button/demo/icon.tsx correctly 1`] = `
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only"
type="button"
>
@ -1630,6 +2031,7 @@ exports[`renders components/button/demo/icon.tsx correctly 1`] = `
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only"
type="button"
>
@ -1689,6 +2091,7 @@ exports[`renders components/button/demo/icon.tsx correctly 1`] = `
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-dashed ant-btn-color-default ant-btn-variant-dashed ant-btn-icon-only"
type="button"
>
@ -1800,6 +2203,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="start"
/>
@ -1807,7 +2211,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
start
</span>
</label>
@ -1820,6 +2226,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="end"
/>
@ -1827,7 +2234,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
end
</span>
</label>
@ -1851,6 +2260,7 @@ Array [
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-icon-only"
type="button"
>
@ -1918,6 +2328,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only"
type="button"
>
@ -1981,6 +2392,7 @@ Array [
class="ant-flex ant-flex-wrap-wrap ant-flex-gap-small"
>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only"
type="button"
>
@ -2040,6 +2452,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-circle ant-btn-dashed ant-btn-color-default ant-btn-variant-dashed ant-btn-icon-only"
type="button"
>
@ -2186,6 +2599,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-sm ant-btn-icon-only"
disabled=""
type="button"
@ -2215,6 +2629,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-sm ant-btn-icon-only"
type="button"
>
@ -2264,6 +2679,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-icon-only"
disabled=""
type="button"
@ -2293,6 +2709,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-icon-only"
type="button"
>
@ -2342,6 +2759,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-lg ant-btn-icon-only"
disabled=""
type="button"
@ -2371,6 +2789,7 @@ Array [
</span>
</button>
<button
aria-describedby="test-id"
class="ant-btn ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-lg ant-btn-icon-only"
type="button"
>
@ -2553,6 +2972,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 +3082,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 +3194,7 @@ Array [
<input
checked=""
class="ant-radio-button-input"
name="test-id"
type="radio"
value="large"
/>
@ -2720,7 +3202,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
Large
</span>
</label>
@ -2732,6 +3216,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="default"
/>
@ -2739,7 +3224,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
Default
</span>
</label>
@ -2751,6 +3238,7 @@ Array [
>
<input
class="ant-radio-button-input"
name="test-id"
type="radio"
value="small"
/>
@ -2758,7 +3246,9 @@ Array [
class="ant-radio-button-inner"
/>
</span>
<span>
<span
class="ant-radio-button-label"
>
Small
</span>
</label>

View File

@ -1,14 +1,15 @@
import React, { Suspense, useRef, useState } from 'react';
import { SearchOutlined } from '@ant-design/icons';
import { resetWarned } from 'rc-util/lib/warning';
import { resetWarned } from '@rc-component/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

@ -16,7 +16,7 @@ jest.mock('react-dom', () => {
return realReactDOM;
});
jest.mock('rc-util/lib/Dom/isVisible', () => {
jest.mock('@rc-component/util/lib/Dom/isVisible', () => {
const mockFn = () => true;
return mockFn;
});

View File

@ -1,7 +1,7 @@
import React, { Children, useContext, useEffect, useMemo, useRef, useState } from 'react';
import omit from '@rc-component/util/lib/omit';
import { useComposeRef } from '@rc-component/util/lib/ref';
import classNames from 'classnames';
import omit from 'rc-util/lib/omit';
import { useComposeRef } from 'rc-util/lib/ref';
import { devUseWarning } from '../_util/warning';
import Wave from '../_util/wave';
@ -19,8 +19,8 @@ import type {
ButtonVariantType,
} from './buttonHelpers';
import { isTwoCNChar, isUnBorderedButtonVariant, spaceChildren } from './buttonHelpers';
import DefaultLoadingIcon from './DefaultLoadingIcon';
import IconWrapper from './IconWrapper';
import LoadingIcon from './LoadingIcon';
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,66 @@ const App: React.FC = () => {
Link
</Button>
</Flex>
<Flex gap="small" 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="small" 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="small" 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>

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