Merge pull request #48828 from ant-design/master

chore: sync master into feature
This commit is contained in:
lijianan 2024-05-08 21:20:07 +08:00 committed by GitHub
commit 00c770537b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
53 changed files with 431 additions and 244 deletions

View File

@ -36,12 +36,11 @@ const useStyle = createStyles(({ token, css }) => ({
export interface ColorPickerProps {
id?: string;
children?: React.ReactNode;
value?: string | Color;
onChange?: (value?: Color | string) => void;
}
const DebouncedColorPicker: React.FC<ColorPickerProps> = (props) => {
const DebouncedColorPicker: React.FC<React.PropsWithChildren<ColorPickerProps>> = (props) => {
const { value: color, children, onChange } = props;
const [value, setValue] = useState(color);

View File

@ -3,11 +3,6 @@ import type { ColorInput } from '@ctrl/tinycolor';
import { TinyColor } from '@ctrl/tinycolor';
import { createStyles } from 'antd-style';
interface ColorChunkProps {
children?: React.ReactNode;
value?: ColorInput;
}
const useStyle = createStyles(({ token, css }) => ({
codeSpan: css`
padding: 0.2em 0.4em;
@ -26,7 +21,11 @@ const useStyle = createStyles(({ token, css }) => ({
`,
}));
const ColorChunk: React.FC<ColorChunkProps> = (props) => {
interface ColorChunkProps {
value?: ColorInput;
}
const ColorChunk: React.FC<React.PropsWithChildren<ColorChunkProps>> = (props) => {
const { styles } = useStyle();
const { value, children } = props;

View File

@ -2,16 +2,20 @@
* copied: https://github.com/arvinxx/dumi-theme-antd-style/tree/master/src/builtins/Container
*/
import * as React from 'react';
import type { FC, ReactNode } from 'react';
import { Alert } from 'antd';
import useStyles from './style';
const Container: FC<{
interface ContainerProps {
type: 'info' | 'warning' | 'success' | 'error';
title?: string;
children: ReactNode;
}> = ({ type, title, children }) => {
}
const Container: React.FC<React.PropsWithChildren<ContainerProps>> = ({
type,
title,
children,
}) => {
const { styles, cx } = useStyles();
return (

View File

@ -1,10 +1,9 @@
import React from 'react';
import { Image } from 'antd';
import classNames from 'classnames';
import toArray from 'rc-util/lib/Children/toArray';
import { Image } from 'antd';
interface ImagePreviewProps {
children: React.ReactNode[];
className?: string;
/** Do not show padding & background */
pure?: boolean;
@ -29,11 +28,22 @@ function isGoodBadImg(imgMeta: any): boolean {
function isCompareImg(imgMeta: any): boolean {
return isGoodBadImg(imgMeta) || imgMeta.inline;
}
const ImagePreview: React.FC<ImagePreviewProps> = (props) => {
interface MateType {
className: string;
alt: string;
description: string;
src: string;
isGood: boolean;
isBad: boolean;
inline: boolean;
}
const ImagePreview: React.FC<React.PropsWithChildren<ImagePreviewProps>> = (props) => {
const { children, className: rootClassName, pure } = props;
const imgs = toArray(children).filter((ele) => ele.type === 'img');
const imgsMeta = imgs.map((img) => {
const imgsMeta = imgs.map<Partial<MateType>>((img) => {
const { alt, description, src, className } = img.props;
return {
className,
@ -107,7 +117,7 @@ const ImagePreview: React.FC<ImagePreviewProps> = (props) => {
<div className="preview-image-title">{coverMeta.alt}</div>
<div
className="preview-image-description"
dangerouslySetInnerHTML={{ __html: coverMeta.description }}
dangerouslySetInnerHTML={{ __html: coverMeta.description ?? '' }}
/>
</div>
);

View File

@ -7,10 +7,13 @@ type LinkProps = Parameters<typeof Link>[0];
export interface LocaleLinkProps extends LinkProps {
sourceType: 'a' | 'Link';
children?: React.ReactNode;
}
const LocaleLink: React.FC<LocaleLinkProps> = ({ sourceType, to, ...props }) => {
const LocaleLink: React.FC<React.PropsWithChildren<LocaleLinkProps>> = ({
sourceType,
to,
...props
}) => {
const Component = sourceType === 'a' ? 'a' : Link;
const [, localeType] = useLocale();

View File

@ -1,4 +1,3 @@
import type { FC, ReactNode } from 'react';
import React, { Suspense } from 'react';
import { Skeleton } from 'antd';
import { createStyles } from 'antd-style';
@ -42,13 +41,12 @@ const SandpackFallback = () => {
};
interface SandpackProps {
children?: ReactNode;
dark?: boolean;
autorun?: boolean;
dependencies?: string;
}
const Sandpack: FC<SandpackProps> = ({
const Sandpack: React.FC<React.PropsWithChildren<SandpackProps>> = ({
children,
dark,
dependencies: extraDeps,

View File

@ -31,7 +31,7 @@ const useStyle = createStyles(({ token, css }) => ({
history: css`
position: absolute;
top: 0;
inset-inline-end: 0;
inset-inline-end: ${token.marginXS}px;
`,
li: css`

View File

@ -5,13 +5,14 @@ import nprogress from 'nprogress';
export interface LinkProps {
to: string | { pathname?: string; search?: string; hash?: string };
children?: React.ReactNode;
style?: React.CSSProperties;
className?: string;
onClick?: MouseEventHandler;
}
const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
nprogress.configure({ showSpinner: false });
const Link = forwardRef<HTMLAnchorElement, React.PropsWithChildren<LinkProps>>((props, ref) => {
const { to, children, ...rest } = props;
const [isPending, startTransition] = useTransition();
const navigate = useNavigate();

View File

@ -204,7 +204,6 @@ const GlobalLayout: React.FC = () => {
<StyleProvider
cache={styleCache}
linters={[legacyNotSelectorLinter, parentSelectorLinter, NaNLinter]}
layer
>
<SiteContext.Provider value={siteContextValue}>
<SiteThemeProvider theme={themeConfig}>

View File

@ -8,7 +8,9 @@ import { useRouteMeta, useTabMeta } from 'dumi';
const useStyle = createStyles(({ token, css }) => {
const { antCls } = token;
return {
toc: css`
anchorToc: css`
scrollbar-width: thin;
scrollbar-color: unset;
${antCls}-anchor {
${antCls}-anchor-link-title {
font-size: ${token.fontSizeSM}px;
@ -120,8 +122,8 @@ const DocAnchor: React.FC<DocAnchorProps> = ({ showDebug, debugDemos = [] }) =>
return (
<section className={styles.tocWrapper}>
<Anchor
className={styles.toc}
affix={false}
className={styles.anchorToc}
targetOffset={token.anchorTop}
showInkInFixed
items={anchorItems.map<AnchorLinkItemProps>(renderAnchorItem)}

View File

@ -5,10 +5,9 @@ import type { IntersectionObserverProps } from 'react-intersection-observer';
type InViewSuspenseProps = Pick<IntersectionObserverProps, 'delay'> & {
fallback?: React.ReactNode;
children?: React.ReactNode;
};
const InViewSuspense: React.FC<InViewSuspenseProps> = ({
const InViewSuspense: React.FC<React.PropsWithChildren<InViewSuspenseProps>> = ({
children,
fallback = <Skeleton.Input active size="small" />,
delay = 200,

View File

@ -124,7 +124,7 @@ const HeaderNavigation: React.FC<NavigationProps> = (props) => {
activeMenuItem = 'docs/resources';
}
let additional: MenuProps['items'];
let additional: MenuProps['items'] = [];
const additionalItems: MenuProps['items'] = [
{
@ -215,50 +215,16 @@ const HeaderNavigation: React.FC<NavigationProps> = (props) => {
},
isZhCN
? {
key: 'mirror',
label: (
<a href="https://ant-design.antgroup.com" target="_blank" rel="noreferrer">
</a>
),
key: 'mirror',
children: [
{
label: (
<a href="https://ant-design.antgroup.com" target="_blank" rel="noreferrer">
</a>
),
icon: (
<img
alt="logo"
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
width={16}
style={{ verticalAlign: 'text-bottom' }}
/>
),
key: 'antgroup',
},
{
label: (
<a href="https://ant-design.gitee.io" target="_blank" rel="noreferrer">
Gitee
</a>
),
icon: (
<img
alt="gitee"
src="https://gw.alipayobjects.com/zos/bmw-prod/9e91e124-9bab-4113-b500-301412f6b370.svg"
width={16}
style={{ verticalAlign: 'text-bottom' }}
/>
),
key: 'gitee',
},
],
}
: null,
...(additional ?? []),
];
].filter(Boolean);
return (
<Menu

View File

@ -54,12 +54,11 @@ const useStyle = createStyles(({ token, css }) => {
border: none;
}
.nav-search-wrapper {
display: flex;
flex: auto;
}
.dumi-default-search-bar {
display: inline-flex;
align-items: center;
flex: auto;
margin: 0;
border-inline-start: 1px solid rgba(0, 0, 0, 0.06);
> svg {
@ -70,6 +69,7 @@ const useStyle = createStyles(({ token, css }) => {
> input {
height: 22px;
border: 0;
max-width: calc(100vw - 768px);
&:focus {
box-shadow: none;
@ -85,6 +85,9 @@ const useStyle = createStyles(({ token, css }) => {
background-color: rgba(150, 150, 150, 0.06);
border-color: rgba(100, 100, 100, 0.2);
border-radius: ${token.borderRadiusSM}px;
position: static;
top: unset;
transform: unset;
}
.dumi-default-search-popover {
@ -103,12 +106,11 @@ const useStyle = createStyles(({ token, css }) => {
align-items: center;
margin: 0;
column-gap: ${token.paddingSM}px;
padding-inline-end: ${token.padding}px;
> * {
flex: none;
margin: 0;
&:last-child {
margin-inline-end: 40px;
}
}
`,
dataDirectionIcon: css`
@ -405,11 +407,11 @@ const Header: React.FC = () => {
<Col {...colProps[0]}>
<Logo {...sharedProps} location={location} />
</Col>
<Col {...colProps[1]} className={styles.menuRow}>
<div className="nav-search-wrapper">
<Col {...colProps[1]}>
<div className={styles.menuRow}>
<DumiSearchBar />
{!isMobile && menu}
</div>
{!isMobile && menu}
</Col>
</Row>
</header>

View File

@ -73,7 +73,6 @@ jobs:
id: site
run: npm run site
env:
SITE_ENV: development
NODE_OPTIONS: "--max_old_space_size=4096"
- name: upload site artifact

View File

@ -17,13 +17,15 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
- name: size-limit
uses: ant-design/size-limit-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
package_manager: yarn
package_manager: bun
build_script: dist
env:
NODE_OPTIONS: "--max_old_space_size=4096"
PRODUCTION_ONLY: 1
NO_DUP_CHECK: 1
CI_JOB_NUMBER: 1

View File

@ -299,7 +299,7 @@ jobs:
lib
- name: zip builds
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
if: github.repository == 'ant-design/ant-design' && github.event_name == 'push' && github.ref == 'refs/heads/master'
env:
ALI_OSS_AK_ID: ${{ secrets.ALI_OSS_AK_ID }}
ALI_OSS_AK_SECRET: ${{ secrets.ALI_OSS_AK_SECRET }}

View File

@ -42,17 +42,6 @@
[dumi-url]: https://github.com/umijs/dumi
[github-issues-url]: https://new-issue.ant.design
<!-- Copy-paste in your Readme.md file -->
<a href="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats?repo_id=34526884" target="_blank" style="display: block" align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="655" height="auto">
<img alt="Performance Stats of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="655" height="auto">
</picture>
</a>
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
</div>
[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design)
@ -166,16 +155,36 @@ $ npm start
## 🤝 参与共建 [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
<!-- Copy-paste in your Readme.md file -->
<a href="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors?repo_id=34526884&limit=30" target="_blank" style="display: block" align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=34526884&limit=30&image_size=auto&color_scheme=dark" width="655" height="auto">
<img alt="Active Contributors of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=34526884&limit=30&image_size=auto&color_scheme=light" width="655" height="auto">
</picture>
</a>
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
<table>
<tr>
<td>
<a href="https://next.ossinsight.io/widgets/official/compose-recent-top-contributors?repo_id=34526884" target="_blank" style="display: block" align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-recent-top-contributors/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="280">
<img alt="Top Contributors of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-recent-top-contributors/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="280">
</picture>
</a>
</td>
<td rowspan="2">
<a href="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats?repo_id=34526884" target="_blank" style="display: block" align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="655" height="auto">
<img alt="Performance Stats of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="655" height="auto">
</picture>
</a>
</td>
</tr>
<tr>
<td>
<a href="https://next.ossinsight.io/widgets/official/compose-org-active-contributors?period=past_28_days&activity=new&owner_id=12101536&repo_ids=34526884" target="_blank" style="display: block" align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?period=past_28_days&activity=new&owner_id=12101536&repo_ids=34526884&image_size=2x3&color_scheme=dark" width="273" height="auto">
<img alt="New participants of ant-design - past 28 days" src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?period=past_28_days&activity=new&owner_id=12101536&repo_ids=34526884&image_size=2x3&color_scheme=light" width="273" height="auto">
</picture>
</a>
</td>
</tr>
</table>
请参考[贡献指南](https://ant.design/docs/react/contributing-cn).

View File

@ -50,18 +50,6 @@ An enterprise-class UI design language and React UI library.
[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
[dumi-url]: https://github.com/umijs/dumi
[github-issues-url]: https://new-issue.ant.design
<!-- Copy-paste in your Readme.md file -->
<a href="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats?repo_id=34526884" target="_blank" style="display: block" align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="655" height="auto">
<img alt="Performance Stats of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="655" height="auto">
</picture>
</a>
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
</div>
[![](https://user-images.githubusercontent.com/507615/209472919-6f7e8561-be8c-4b0b-9976-eb3c692aa20a.png)](https://ant.design)
@ -158,22 +146,42 @@ Open your browser and visit http://127.0.0.1:8001 , see more at [Development](ht
## 🤝 Contributing [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
<!-- Copy-paste in your Readme.md file -->
<a href="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors?repo_id=34526884&limit=30" target="_blank" style="display: block" align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=34526884&limit=30&image_size=auto&color_scheme=dark" width="655" height="auto">
<img alt="Active Contributors of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=34526884&limit=30&image_size=auto&color_scheme=light" width="655" height="auto">
</picture>
</a>
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
<table>
<tr>
<td>
<a href="https://next.ossinsight.io/widgets/official/compose-recent-top-contributors?repo_id=34526884" target="_blank" style="display: block" align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-recent-top-contributors/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="280">
<img alt="Top Contributors of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-recent-top-contributors/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="280">
</picture>
</a>
</td>
<td rowspan="2">
<a href="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats?repo_id=34526884" target="_blank" style="display: block" align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=dark" width="655" height="auto">
<img alt="Performance Stats of ant-design/ant-design - Last 28 days" src="https://next.ossinsight.io/widgets/official/compose-last-28-days-stats/thumbnail.png?repo_id=34526884&image_size=auto&color_scheme=light" width="655" height="auto">
</picture>
</a>
</td>
</tr>
<tr>
<td>
<a href="https://next.ossinsight.io/widgets/official/compose-org-active-contributors?period=past_28_days&activity=new&owner_id=12101536&repo_ids=34526884" target="_blank" style="display: block" align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?period=past_28_days&activity=new&owner_id=12101536&repo_ids=34526884&image_size=2x3&color_scheme=dark" width="273" height="auto">
<img alt="New participants of ant-design - past 28 days" src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?period=past_28_days&activity=new&owner_id=12101536&repo_ids=34526884&image_size=2x3&color_scheme=light" width="273" height="auto">
</picture>
</a>
</td>
</tr>
</table>
Let's build a better antd together.
We welcome all contributions. Please read our [Contributing Guide](https://ant.design/docs/react/contributing) first. You can submit any ideas as [Pull Requests](https://github.com/ant-design/ant-design/pulls) or as [GitHub Issues](https://github.com/ant-design/ant-design/issues). If you'd like to improve code, check out the [Development Instructions](https://github.com/ant-design/ant-design/wiki/Development) and have a good time! :)
We warmly invite contributions from everyone. Before you get started, please take a moment to review our [Contributing Guide](https://ant.design/docs/react/contributing). Feel free to share your ideas through [Pull Requests](https://github.com/ant-design/ant-design/pulls) or [GitHub Issues](https://github.com/ant-design/ant-design/issues). If you're interested in enhancing our codebase, explore the [Development Instructions](https://github.com/ant-design/ant-design/wiki/Development) and enjoy your coding journey! :)
If you are a collaborator, please follow our [Pull Request Principle](https://github.com/ant-design/ant-design/wiki/PR-principle) to create a Pull Request with our [Pull Request Template](https://github.com/ant-design/ant-design/wiki/PR-principle#pull-request-template).
For collaborators, adhere to our [Pull Request Principle](https://github.com/ant-design/ant-design/wiki/PR-principle) and utilize our [Pull Request Template](https://github.com/ant-design/ant-design/wiki/PR-principle#pull-request-template) when creating a Pull Request.
[![Let's fund issues in this repository](https://raw.githubusercontent.com/BoostIO/issuehunt-materials/master/v1/issuehunt-button-v1.svg)](https://issuehunt.io/repos/34526884)

View File

@ -1,6 +1,7 @@
import React, { useEffect } from 'react';
import { SmileOutlined } from '@ant-design/icons';
import type { NotificationConfig } from 'antd/es/notification/interface';
import ConfigProvider from 'antd/es/config-provider';
import App from '..';
import mountTest from '../../../tests/shared/mountTest';
@ -211,6 +212,16 @@ describe('App', () => {
});
describe('component', () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
afterEach(() => {
errorSpy.mockReset();
});
afterAll(() => {
errorSpy.mockRestore();
});
it('replace', () => {
const { container } = render(
<App component="section">
@ -222,15 +233,25 @@ describe('App', () => {
});
it('to false', () => {
const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
const { container } = render(
<App component={false}>
<p />
</App>,
);
expect(warnSpy).not.toHaveBeenCalled();
expect(errorSpy).not.toHaveBeenCalled();
expect(container.querySelector('.ant-app')).toBeFalsy();
warnSpy.mockRestore();
});
it('should warn if component is false and cssVarCls is not empty', () => {
render(
<ConfigProvider theme={{ cssVar: true }}>
<App component={false} />
</ConfigProvider>,
);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: App] When using cssVar, ensure `component` is assigned a valid React component string.',
);
});
});
});

View File

@ -131,10 +131,16 @@ Common props ref[Common props](/docs/react/common-props)
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| component | Config render element, if `false` will not create DOM node | ComponentType | div | 5.11.0 |
| component | Config render element, if `false` will not create DOM node | ComponentType \| false | div | 5.11.0 |
| message | Global config for Message | [MessageConfig](/components/message/#messageconfig) | - | 5.3.0 |
| notification | Global config for Notification | [NotificationConfig](/components/notification/#notificationconfig) | - | 5.3.0 |
## Design Token
<ComponentTokenTable component="App"></ComponentTokenTable>
## FAQ
### CSS Var doesn't work inside `<App component={false}>`
Make sure the App `component` is a legit React component string, so when you're turning on CSS variables, there's a container to hold the CSS class name.

View File

@ -3,6 +3,7 @@ import React, { useContext } from 'react';
import classNames from 'classnames';
import type { AnyObject, CustomComponent } from '../_util/type';
import { devUseWarning } from '../_util/warning';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigContext } from '../config-provider';
import useMessage from '../message/useMessage';
@ -64,6 +65,13 @@ const App: React.FC<AppProps> & { useApp: () => useAppProps } = (props) => {
[messageApi, notificationApi, ModalApi],
);
// https://github.com/ant-design/ant-design/issues/48802#issuecomment-2097813526
devUseWarning('App')(
!(cssVarCls && component === false),
'usage',
'When using cssVar, ensure `component` is assigned a valid React component string.',
);
// ============================ Render ============================
const Component = component === false ? React.Fragment : component;
const rootProps: AppProps = {

View File

@ -132,10 +132,16 @@ export default () => {
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| component | 设置渲染元素,为 `false` 则不创建 DOM 节点 | ComponentType | div | 5.11.0 |
| component | 设置渲染元素,为 `false` 则不创建 DOM 节点 | ComponentType \| false | div | 5.11.0 |
| message | App 内 Message 的全局配置 | [MessageConfig](/components/message-cn/#messageconfig) | - | 5.3.0 |
| notification | App 内 Notification 的全局配置 | [NotificationConfig](/components/notification-cn/#notificationconfig) | - | 5.3.0 |
## 主题变量Design Token
<ComponentTokenTable component="App"></ComponentTokenTable>
## FAQ
### CSS Var 在 `<App component={false}>` 内不起作用
请确保 App 的 `component` 是一个有效的 React 组件字符串,以便在启用 CSS 变量时,有一个容器来承载 CSS 类名。

View File

@ -1532,13 +1532,12 @@ Array [
class="ant-radio-group ant-radio-group-outline"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
class="ant-radio-button-wrapper"
>
<span
class="ant-radio-button ant-radio-button-checked"
class="ant-radio-button"
>
<input
checked=""
class="ant-radio-button-input"
type="radio"
value="start"
@ -1552,12 +1551,13 @@ Array [
</span>
</label>
<label
class="ant-radio-button-wrapper"
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
>
<span
class="ant-radio-button"
class="ant-radio-button ant-radio-button-checked"
>
<input
checked=""
class="ant-radio-button-input"
type="radio"
value="end"
@ -1648,8 +1648,11 @@ Array [
class="ant-btn ant-btn-primary"
type="button"
>
<span>
Search
</span>
<span
class="ant-btn-icon"
class="ant-btn-icon ant-btn-icon-end"
>
<span
aria-label="search"
@ -1671,9 +1674,6 @@ Array [
</svg>
</span>
</span>
<span>
Search
</span>
</button>
<button
class="ant-btn ant-btn-circle ant-btn-default ant-btn-icon-only"
@ -1726,8 +1726,11 @@ Array [
class="ant-btn ant-btn-default"
type="button"
>
<span>
Search
</span>
<span
class="ant-btn-icon"
class="ant-btn-icon ant-btn-icon-end"
>
<span
aria-label="search"
@ -1749,9 +1752,6 @@ Array [
</svg>
</span>
</span>
<span>
Search
</span>
</button>
</div>
<div
@ -1808,8 +1808,11 @@ Array [
class="ant-btn ant-btn-text"
type="button"
>
<span>
Search
</span>
<span
class="ant-btn-icon"
class="ant-btn-icon ant-btn-icon-end"
>
<span
aria-label="search"
@ -1831,9 +1834,6 @@ Array [
</svg>
</span>
</span>
<span>
Search
</span>
</button>
<button
class="ant-btn ant-btn-circle ant-btn-dashed ant-btn-icon-only"
@ -1886,8 +1886,11 @@ Array [
class="ant-btn ant-btn-dashed"
type="button"
>
<span>
Search
</span>
<span
class="ant-btn-icon"
class="ant-btn-icon ant-btn-icon-end"
>
<span
aria-label="search"
@ -1909,9 +1912,6 @@ Array [
</svg>
</span>
</span>
<span>
Search
</span>
</button>
<a
class="ant-btn ant-btn-default ant-btn-icon-only"
@ -1946,8 +1946,11 @@ Array [
class="ant-btn ant-btn-primary ant-btn-loading"
type="button"
>
<span>
Loading
</span>
<span
class="ant-btn-icon ant-btn-loading-icon"
class="ant-btn-icon ant-btn-loading-icon-end"
style="width: 0px; opacity: 0; transform: scale(0);"
>
<span
@ -1970,9 +1973,6 @@ Array [
</svg>
</span>
</span>
<span>
Loading
</span>
</button>
</div>
</div>,

View File

@ -1357,13 +1357,12 @@ Array [
class="ant-radio-group ant-radio-group-outline"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
class="ant-radio-button-wrapper"
>
<span
class="ant-radio-button ant-radio-button-checked"
class="ant-radio-button"
>
<input
checked=""
class="ant-radio-button-input"
type="radio"
value="start"
@ -1377,12 +1376,13 @@ Array [
</span>
</label>
<label
class="ant-radio-button-wrapper"
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"
>
<span
class="ant-radio-button"
class="ant-radio-button ant-radio-button-checked"
>
<input
checked=""
class="ant-radio-button-input"
type="radio"
value="end"
@ -1454,8 +1454,11 @@ Array [
class="ant-btn ant-btn-primary"
type="button"
>
<span>
Search
</span>
<span
class="ant-btn-icon"
class="ant-btn-icon ant-btn-icon-end"
>
<span
aria-label="search"
@ -1477,9 +1480,6 @@ Array [
</svg>
</span>
</span>
<span>
Search
</span>
</button>
<button
class="ant-btn ant-btn-circle ant-btn-default ant-btn-icon-only"
@ -1513,8 +1513,11 @@ Array [
class="ant-btn ant-btn-default"
type="button"
>
<span>
Search
</span>
<span
class="ant-btn-icon"
class="ant-btn-icon ant-btn-icon-end"
>
<span
aria-label="search"
@ -1536,9 +1539,6 @@ Array [
</svg>
</span>
</span>
<span>
Search
</span>
</button>
</div>
<div
@ -1576,8 +1576,11 @@ Array [
class="ant-btn ant-btn-text"
type="button"
>
<span>
Search
</span>
<span
class="ant-btn-icon"
class="ant-btn-icon ant-btn-icon-end"
>
<span
aria-label="search"
@ -1599,9 +1602,6 @@ Array [
</svg>
</span>
</span>
<span>
Search
</span>
</button>
<button
class="ant-btn ant-btn-circle ant-btn-dashed ant-btn-icon-only"
@ -1635,8 +1635,11 @@ Array [
class="ant-btn ant-btn-dashed"
type="button"
>
<span>
Search
</span>
<span
class="ant-btn-icon"
class="ant-btn-icon ant-btn-icon-end"
>
<span
aria-label="search"
@ -1658,9 +1661,6 @@ Array [
</svg>
</span>
</span>
<span>
Search
</span>
</button>
<a
class="ant-btn ant-btn-default ant-btn-icon-only"
@ -1695,8 +1695,11 @@ Array [
class="ant-btn ant-btn-primary ant-btn-loading"
type="button"
>
<span>
Loading
</span>
<span
class="ant-btn-icon ant-btn-loading-icon"
class="ant-btn-icon ant-btn-loading-icon-end"
>
<span
aria-label="loading"
@ -1718,9 +1721,6 @@ Array [
</svg>
</span>
</span>
<span>
Loading
</span>
</button>
</div>
</div>,

View File

@ -88,7 +88,7 @@ describe('Button', () => {
});
it('renders Chinese characters correctly in HOC', () => {
const Text = ({ children }: { children: React.ReactNode }) => <span>{children}</span>;
const Text: React.FC<React.PropsWithChildren> = ({ children }) => <span>{children}</span>;
const { container, rerender } = render(
<Button>
<Text></Text>

View File

@ -258,16 +258,18 @@ const InternalCompoundedButton = React.forwardRef<
const kids =
children || children === 0 ? spaceChildren(children, needInserted && mergedInsertSpace) : null;
const genButtonContent = (iconComponent: React.ReactNode, kidsComponent: React.ReactNode) => {
const isRTL = direction === 'rtl';
const iconFirst = (iconPosition === 'start' && !isRTL) || (iconPosition === 'end' && isRTL);
return (
const genButtonContent = (iconComponent: React.ReactNode, kidsComponent: React.ReactNode) =>
iconPosition === 'start' ? (
<>
{iconFirst ? iconComponent : kidsComponent}
{iconFirst ? kidsComponent : iconComponent}
{iconComponent}
{kidsComponent}
</>
) : (
<>
{kidsComponent}
{iconComponent}
</>
);
};
if (linkButtonRestProps.href !== undefined) {
return wrapCSSVar(

View File

@ -3,7 +3,7 @@ import { SearchOutlined } from '@ant-design/icons';
import { Button, Divider, Flex, Radio, Space, Tooltip } from 'antd';
const App: React.FC = () => {
const [position, setPosition] = useState<'start' | 'end'>('start');
const [position, setPosition] = useState<'start' | 'end'>('end');
return (
<>

View File

@ -364,7 +364,7 @@ const genCardStyle: GenerateStyle<CardToken> = (token): CSSObject => {
},
[`${componentCls}-contain-tabs`]: {
[`> ${componentCls}-head`]: {
[`> div${componentCls}-head`]: {
minHeight: 0,
[`${componentCls}-head-title, ${componentCls}-extra`]: {
paddingTop: cardHeadPadding,

View File

@ -93,7 +93,7 @@ const cascaderOptions = [
type Placement = 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight';
const Page: React.FC<{ popupPlacement: Placement }> = ({ popupPlacement }) => {
const Page: React.FC<{ placement: Placement }> = ({ placement }) => {
const [currentStep, setCurrentStep] = useState(0);
const [modalOpen, setModalOpen] = useState(false);
const [badgeCount, setBadgeCount] = useState(5);
@ -169,7 +169,7 @@ const Page: React.FC<{ popupPlacement: Placement }> = ({ popupPlacement }) => {
options={cascaderOptions}
onChange={onCascaderChange}
placeholder="یک مورد انتخاب کنید"
popupPlacement={popupPlacement}
placement={placement}
/>
&nbsp;&nbsp;&nbsp;&nbsp;With search:&nbsp;&nbsp;
<Cascader
@ -177,7 +177,7 @@ const Page: React.FC<{ popupPlacement: Placement }> = ({ popupPlacement }) => {
options={cascaderOptions}
onChange={onCascaderChange}
placeholder="Select an item"
popupPlacement={popupPlacement}
placement={placement}
showSearch={{ filter: cascaderFilter }}
/>
</Col>
@ -495,15 +495,15 @@ const Page: React.FC<{ popupPlacement: Placement }> = ({ popupPlacement }) => {
const App: React.FC = () => {
const [direction, setDirection] = useState<DirectionType>('ltr');
const [popupPlacement, setPopupPlacement] = useState<Placement>('bottomLeft');
const [placement, setPlacement] = useState<Placement>('bottomLeft');
const changeDirection = (e: RadioChangeEvent) => {
const directionValue = e.target.value;
setDirection(directionValue);
if (directionValue === 'rtl') {
setPopupPlacement('bottomRight');
setPlacement('bottomRight');
} else {
setPopupPlacement('bottomLeft');
setPlacement('bottomLeft');
}
};
@ -521,7 +521,7 @@ const App: React.FC = () => {
</Radio.Group>
</div>
<ConfigProvider direction={direction}>
<Page popupPlacement={popupPlacement} />
<Page placement={placement} />
</ConfigProvider>
</>
);

View File

@ -16,8 +16,6 @@ import type { ConfigProviderProps } from 'antd';
type SizeType = ConfigProviderProps['componentSize'];
const { TabPane } = Tabs;
const App: React.FC = () => {
const [componentSize, setComponentSize] = useState<SizeType>('small');
@ -37,17 +35,26 @@ const App: React.FC = () => {
<ConfigProvider componentSize={componentSize}>
<Space size={[0, 16]} style={{ width: '100%' }} direction="vertical">
<Input />
<Tabs defaultActiveKey="1">
<TabPane tab="Tab 1" key="1">
Content of Tab Pane 1
</TabPane>
<TabPane tab="Tab 2" key="2">
Content of Tab Pane 2
</TabPane>
<TabPane tab="Tab 3" key="3">
Content of Tab Pane 3
</TabPane>
</Tabs>
<Tabs
defaultActiveKey="1"
items={[
{
label: 'Tab 1',
key: '1',
children: 'Content of Tab Pane 1',
},
{
label: 'Tab 2',
key: '2',
children: 'Content of Tab Pane 2',
},
{
label: 'Tab 3',
key: '3',
children: 'Content of Tab Pane 3',
},
]}
/>
<Input.Search allowClear />
<Input.TextArea allowClear />
<Select defaultValue="demo" options={[{ value: 'demo' }]} />

View File

@ -6,14 +6,16 @@ const MyFormItemContext = React.createContext<(string | number)[]>([]);
interface MyFormItemGroupProps {
prefix: string | number | (string | number)[];
children: React.ReactNode;
}
function toArr(str: string | number | (string | number)[]): (string | number)[] {
return Array.isArray(str) ? str : [str];
}
const MyFormItemGroup = ({ prefix, children }: MyFormItemGroupProps) => {
const MyFormItemGroup: React.FC<React.PropsWithChildren<MyFormItemGroupProps>> = ({
prefix,
children,
}) => {
const prefixPath = React.useContext(MyFormItemContext);
const concatPath = React.useMemo(() => [...prefixPath, ...toArr(prefix)], [prefixPath, prefix]);

View File

@ -1,7 +1,7 @@
import React from 'react';
import { Col, Divider, Row } from 'antd';
const DemoBox: React.FC<{ children: React.ReactNode; value: number }> = (props) => (
const DemoBox: React.FC<React.PropsWithChildren<{ value: number }>> = (props) => (
<p className={`height-${props.value}`}>{props.children}</p>
);

View File

@ -5,6 +5,7 @@ const App: React.FC = () => (
<Image
width={200}
preview={{
destroyOnClose: true,
imageRender: () => (
<video
muted

View File

@ -68,6 +68,7 @@ Other attributes [&lt;img>](https://developer.mozilla.org/en-US/docs/Web/HTML/El
| forceRender | Force render preview dialog | boolean | - | - |
| toolbarRender | Custom toolbar render | (originalNode: React.ReactElement, info: Omit<[ToolbarRenderInfoType](#toolbarrenderinfotype), 'current' \| 'total'>) => React.ReactNode | - | 5.7.0 |
| imageRender | Custom preview content | (originalNode: React.ReactElement, info: { transform: [TransformType](#transformtype) }) => React.ReactNode | - | 5.7.0 |
| destroyOnClose | Destroy child elements when closing preview | boolean | false | |
| onTransform | Callback when the transform of image changed | { transform: [TransformType](#transformtype), action: [TransformAction](#transformaction) } | - | 5.7.0 |
| onVisibleChange | Callback when `visible` changed | (visible: boolean, prevVisible: boolean) => void | - | - |

View File

@ -69,6 +69,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*LVQ3R5JjjJEAAA
| forceRender | 强制渲染预览图 | boolean | - | - |
| toolbarRender | 自定义工具栏 | (originalNode: React.ReactElement, info: Omit<[ToolbarRenderInfoType](#toolbarrenderinfotype), 'current' \| 'total'>) => React.ReactNode | - | 5.7.0 |
| imageRender | 自定义预览内容 | (originalNode: React.ReactElement, info: { transform: [TransformType](#transformtype) }) => React.ReactNode | - | 5.7.0 |
| destroyOnClose | 关闭预览时销毁子元素 | boolean | false | |
| onTransform | 预览图 transform 变化的回调 | { transform: [TransformType](#transformtype), action: [TransformAction](#transformaction) } | - | 5.7.0 |
| onVisibleChange | 当 `visible` 发生改变时的回调 | (visible: boolean, prevVisible: boolean) => void | - | - |

View File

@ -39,7 +39,7 @@ export const OverrideProvider = React.forwardRef<
);
const canRef = supportNodeRef(children);
const mergedRef = useComposeRef(ref, canRef ? (children as any).ref : null);
const mergedRef = useComposeRef(ref, canRef ? children.ref : null);
return (
<OverrideContext.Provider value={context}>

View File

@ -31,13 +31,12 @@ const EditableRow: React.FC<EditableRowProps> = ({ index, ...props }) => {
interface EditableCellProps {
title: React.ReactNode;
editable: boolean;
children: React.ReactNode;
dataIndex: keyof Item;
record: Item;
handleSave: (record: Item) => void;
}
const EditableCell: React.FC<EditableCellProps> = ({
const EditableCell: React.FC<React.PropsWithChildren<EditableCellProps>> = ({
title,
editable,
children,

View File

@ -25,10 +25,9 @@ interface EditableCellProps extends React.HTMLAttributes<HTMLElement> {
inputType: 'number' | 'text';
record: Item;
index: number;
children: React.ReactNode;
}
const EditableCell: React.FC<EditableCellProps> = ({
const EditableCell: React.FC<React.PropsWithChildren<EditableCellProps>> = ({
editing,
dataIndex,
title,

View File

@ -1,7 +1,7 @@
import React from 'react';
import { Button, Checkbox, Input, InputNumber, Select, Space, Tooltip } from 'antd';
const WrapperTooltip: React.FC<{ children?: React.ReactNode }> = (props) => (
const WrapperTooltip: React.FC<React.PropsWithChildren> = (props) => (
<Tooltip title="Thanks for using antd. Have a nice day!" {...props} />
);

View File

@ -116,9 +116,7 @@ describe('Watermark', () => {
const watermark = getWatermarkElement();
expect(watermark).toHaveStyle({
zIndex: '9',
});
expect(watermark).toHaveStyle({ zIndex: '9' });
// Not crash when children removed
rerender(<Watermark className="test" />);

View File

@ -80,7 +80,7 @@ const useButtonStyle = () => {
}))();
};
function GeekProvider(props: { children?: React.ReactNode }) {
function GeekProvider(props: React.PropsWithChildren) {
const { styles } = useButtonStyle();
return <ConfigProvider button={{ className: styles.btn }}>{props.children}</ConfigProvider>;
@ -92,7 +92,7 @@ function GeekProvider(props: { children?: React.ReactNode }) {
It's also easy to extend for scenarios that need to inherit `className`:
```tsx
function GeekProvider(props: { children?: React.ReactNode }) {
function GeekProvider(props: React.PropsWithChildren) {
const { button } = React.useContext(ConfigProvider.ConfigContext);
const { styles } = useButtonStyle();

View File

@ -138,7 +138,7 @@ useLayoutEffect(() => {
### Resolution
Due to the above queue operation, the DOM of the portal will be triggered in the next `useLayoutEffect` under nesting. This causes the `uesLayoutEffect` timing of the animation to start in `rc-dialog` after the node behavior is added, resulting in the element not being in the document and unable to obtain the correct coordinate information.
Due to the above queue operation, the DOM of the portal will be triggered in the next `useLayoutEffect` under nesting. This causes the `useLayoutEffect` timing of the animation to start in `rc-dialog` after the node behavior is added, resulting in the element not being in the document and unable to obtain the correct coordinate information.
Since Modal is already enabled, it does not need to be executed asynchronously through `queue`, so we only need to add a judgment if it is enabled, and execute `append` directly:

View File

@ -138,7 +138,7 @@ useLayoutEffect(() => {
### 问题分析
由于上述的队列操作,使得 portal 的 DOM 在嵌套下会在下一个 `useLayoutEffect` 触发。这导致添加节点行为后于 `rc-dialog` 启动动画的 `uesLayoutEffect` 时机,导致元素不在 document 中而无法获取正确的坐标信息。
由于上述的队列操作,使得 portal 的 DOM 在嵌套下会在下一个 `useLayoutEffect` 触发。这导致添加节点行为后于 `rc-dialog` 启动动画的 `useLayoutEffect` 时机,导致元素不在 document 中而无法获取正确的坐标信息。
由于 Modal 已经是开启状态,其实不需要通过 `queue` 异步执行,所以我们只需要加一个判断如果是开启状态,直接执行 `append` 即可:

View File

@ -1,7 +1,7 @@
---
group:
title: Basic Usage
order: 2
order: 3
title: Usage with Next.js
tag: Updated
---

View File

@ -1,7 +1,7 @@
---
group:
title: 如何使用
order: 2
order: 3
title: 在 Next.js 中使用
tag: Updated
---

View File

@ -0,0 +1,70 @@
---
group:
title: Basic Usage
order: 5
title: Usage with Rsbuild
tag: New
---
[Rsbuild](https://rsbuild.dev) is a build tool driven by Rspack. This article will try to use `Rsbuild` to create a project and import antd.
## Install and Initialization
Before all start, you may need install [yarn](https://github.com/yarnpkg/yarn) or [pnpm](https://pnpm.io) or [bun](https://bun.sh).
<InstallDependencies npm='$ npm create rsbuild' yarn='$ yarn create rsbuild' pnpm='$ pnpm create rsbuild' bun='$ bun create rsbuild'></InstallDependencies>
During the initialization process, `create-rsbuild` provides a series of templates for us to choose, We need choose the `React` template.
The tool will create and initialize environment and dependencies automatically, please try config your proxy setting or use another npm registry if any network errors happen during it.
Then we go inside project and start it.
```bash
$ cd demo
$ npm run dev
```
Open the browser at http://localhost:3000. It renders a title saying `Rsbuild with React` on the page, which is considered successful.
## Import antd
Now we install `antd` from yarn or npm or pnpm or bun.
<InstallDependencies npm='$ npm install antd --save' yarn='$ yarn add antd' pnpm='$ pnpm install antd --save' bun='$ bun add antd'></InstallDependencies>
Modify `src/App.tsx`, import Button component from `antd`.
```tsx
import React from 'react';
import { Button } from 'antd';
const App: React.FC = () => (
<div className="App">
<Button type="primary">Button</Button>
</div>
);
export default App;
```
OK, you should now see a blue primary button displayed on the page. Next you can choose any components of `antd` to develop your application. Visit other workflows of `Rsbuild` at its [Official documentation](https://rsbuild.dev).
### Customize Theme
Ref to the [Customize Theme documentation](/docs/react/customize-theme). Modify theme with ConfigProvider:
```tsx
import React from 'react';
import { ConfigProvider } from 'antd';
const App: React.FC = () => (
<ConfigProvider theme={{ token: { colorPrimary: '#00b96b' } }}>
<MyApp />
</ConfigProvider>
);
export default App;
```
We are successfully running the antd components using Rsbuild now, lets start build your own application!

View File

@ -0,0 +1,70 @@
---
group:
title: 如何使用
order: 5
title: 在 Rsbuild 中使用
tag: New
---
[Rsbuild](https://rsbuild.dev/zh) 由 Rspack 驱动的构建工具,本文会尝试使用 `Rsbuild` 创建一个项目,并引入 antd。
## 安装和初始化
在开始之前,你可能需要安装 [yarn](https://github.com/yarnpkg/yarn) 或者 [pnpm](https://pnpm.io/zh) 或者 [bun](https://bun.sh)。
<InstallDependencies npm='$ npm create rsbuild' yarn='$ yarn create rsbuild' pnpm='$ pnpm create rsbuild' bun='$ bun create rsbuild'></InstallDependencies>
在初始化的过程中,`create-rsbuild` 提供了一系列模板供我们选择,这里我们选择 `React` 模板。
工具会自动初始化一个脚手架并安装 React 项目的各种必要依赖,如果在过程中出现网络问题,请尝试配置代理或使用其他 npm registry。
然后我们进入项目并启动。
```bash
$ cd demo
$ npm run dev
```
此时访问浏览器 http://localhost:3000看到 `Rsbuild with React` 的界面就算成功了。
## 引入 antd
现在从 yarn 或 npm 或 pnpm 或 bun 安装并引入 antd。
<InstallDependencies npm='$ npm install antd --save' yarn='$ yarn add antd' pnpm='$ pnpm install antd --save' bun='$ bun add antd'></InstallDependencies>
修改 `src/App.tsx`,引入 antd 的 Button 组件。
```tsx
import React from 'react';
import { Button } from 'antd';
const App: React.FC = () => (
<div className="App">
<Button type="primary">Button</Button>
</div>
);
export default App;
```
好了,现在你应该能看到页面上已经有了 antd 的蓝色按钮组件,接下来就可以继续选用其他组件开发应用了。其它开发流程你可以参考 Rsbuild 的[官方文档](https://rsbuild.dev/zh)。
### 自定义主题
参考 [配置主题](/docs/react/customize-theme),通过 ConfigProvider 进行主题配置:
```tsx
import React from 'react';
import { ConfigProvider } from 'antd';
const App: React.FC = () => (
<ConfigProvider theme={{ token: { colorPrimary: '#00b96b' } }}>
<MyApp />
</ConfigProvider>
);
export default App;
```
我们现在已经把 antd 组件成功使用 Rsbuild 运行起来了,开始开发你的应用吧!

View File

@ -1,7 +1,7 @@
---
group:
title: Basic Usage
order: 2
order: 4
title: Usage with Umi
---

View File

@ -1,7 +1,7 @@
---
group:
title: 如何使用
order: 2
order: 4
title: 在 Umi 中使用
---

View File

@ -1,7 +1,7 @@
---
group:
title: Basic Usage
order: 3
order: 2
title: Usage with Vite
---

View File

@ -1,7 +1,7 @@
---
group:
title: 如何使用
order: 3
order: 2
title: 在 Vite 中使用
---

View File

@ -118,7 +118,7 @@
"dependencies": {
"@ant-design/colors": "^7.0.2",
"@ant-design/cssinjs": "^1.19.1",
"@ant-design/icons": "^5.3.6",
"@ant-design/icons": "^5.3.7",
"@ant-design/react-slick": "~1.1.2",
"@babel/runtime": "^7.24.5",
"@ctrl/tinycolor": "^3.6.1",
@ -150,7 +150,7 @@
"rc-rate": "~2.12.0",
"rc-resize-observer": "^1.4.0",
"rc-segmented": "~2.3.0",
"rc-select": "~14.13.1",
"rc-select": "~14.13.2",
"rc-slider": "~10.6.2",
"rc-steps": "~6.0.1",
"rc-switch": "~4.1.0",
@ -158,10 +158,10 @@
"rc-tabs": "~15.0.0 ",
"rc-textarea": "~1.6.3",
"rc-tooltip": "~6.2.0",
"rc-tree": "~5.8.5",
"rc-tree": "~5.8.7",
"rc-tree-select": "~5.20.0",
"rc-upload": "~4.5.2",
"rc-util": "^5.39.1",
"rc-util": "^5.39.3",
"scroll-into-view-if-needed": "^3.1.0",
"throttle-debounce": "^5.0.0"
},
@ -253,7 +253,7 @@
"eslint-plugin-jest": "^28.3.0",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-lodash": "^7.4.0",
"eslint-plugin-markdown": "^4.0.1",
"eslint-plugin-markdown": "^5.0.0",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-unicorn": "^52.0.0",

View File

@ -5,11 +5,7 @@ import { TriggerMockContext } from '../../../shared/demoTestContext';
let OriginPortal = jest.requireActual('rc-util/lib/Portal');
OriginPortal = OriginPortal.default ?? OriginPortal;
interface MockPortalProps {
children?: React.ReactNode
}
class MockPortal extends React.Component<MockPortalProps> {
class MockPortal extends React.Component<React.PropsWithChildren> {
container: boolean | undefined;
static contextType = TriggerMockContext;
@ -32,7 +28,7 @@ class MockPortal extends React.Component<MockPortalProps> {
}
}
const CustomPortal = React.forwardRef<PortalRef, PortalProps | MockPortalProps>((props, ref) => {
const CustomPortal = React.forwardRef<PortalRef, PortalProps | React.PropsWithChildren>((props, ref) => {
const context = React.useContext(TriggerMockContext);
if (context?.mock === false) {
return <OriginPortal {...props} ref={ref} />;