mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 02:59:04 +08:00
commit
6176d3cefe
@ -23,6 +23,7 @@ export default defineConfig({
|
||||
mfsu: false,
|
||||
mako: {},
|
||||
crossorigin: {},
|
||||
runtimePublicPath: {},
|
||||
outputPath: '_site',
|
||||
favicons: ['https://gw.alipayobjects.com/zos/rmsportal/rlpTLlbMzTNYuZGGCVYM.png'],
|
||||
resolve: {
|
||||
|
@ -16,6 +16,14 @@ tag: vVERSION
|
||||
|
||||
---
|
||||
|
||||
## 5.20.3
|
||||
|
||||
`2024-08-26`
|
||||
|
||||
- 🐞 Refactor Typography native css ellipsis measure logic to handle precision edge case. [#50514](https://github.com/ant-design/ant-design/pull/50514) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix ColorPicker `onChangeComplete` not correct when click directly without move on the picker panel. [#50501](https://github.com/ant-design/ant-design/pull/50501) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fix FloatButton.Group with controlled mode warning for nest updating issue. [#50500](https://github.com/ant-design/ant-design/pull/50500) [@zombieJ](https://github.com/zombieJ)
|
||||
|
||||
## 5.20.2
|
||||
|
||||
`2024-08-19`
|
||||
|
@ -15,6 +15,14 @@ tag: vVERSION
|
||||
|
||||
---
|
||||
|
||||
## 5.20.3
|
||||
|
||||
`2024-08-26`
|
||||
|
||||
- 🐞 重构 Typography 在使用 css 原生省略时的检查逻辑,以解决屏幕缩放等情况下的精度问题。[#50514](https://github.com/ant-design/ant-design/pull/50514) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 修复 ColorPicker 组件在面板上不拖拽直接点击的时候,`onChangeComplete` 返回值不正确的问题。[#50501](https://github.com/ant-design/ant-design/pull/50501) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 修复 FloatButton.Group 在受控模式下 React 会警告递归更新的问题。[#50500](https://github.com/ant-design/ant-design/pull/50500) [@zombieJ](https://github.com/zombieJ)
|
||||
|
||||
## 5.20.2
|
||||
|
||||
`2024-08-19`
|
||||
|
@ -57,6 +57,8 @@
|
||||
|
||||
## 🖥 兼容环境
|
||||
|
||||
支持范围:https://browsersl.ist/#q=defaults
|
||||
|
||||
- 现代浏览器。
|
||||
- 支持服务端渲染。
|
||||
- [Electron](https://www.electronjs.org/)
|
||||
|
7
codecov.yml
Normal file
7
codecov.yml
Normal file
@ -0,0 +1,7 @@
|
||||
coverage:
|
||||
status:
|
||||
project: #add everything under here, more options at https://docs.codecov.com/docs/commit-status
|
||||
default:
|
||||
target: 100%
|
||||
threshold: 0%
|
||||
base: auto
|
@ -45,8 +45,8 @@ A Drawer is a panel that is typically overlaid on top of a page and slides in fr
|
||||
Common props ref:[Common props](/docs/react/common-props)
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
:::info{title=注意}
|
||||
v5 use `rootClassName` & `rootStyle` to config wrapper style instead of `className` & `style` in v4 to align the API with Modal.
|
||||
:::info{title=Note}
|
||||
v5 uses `rootClassName` & `rootStyle` to configure the outermost element style, instead of `className` & `style` from v4. This is done to align the API with Modal.
|
||||
:::
|
||||
|
||||
| Props | Description | Type | Default | Version |
|
||||
|
@ -8,8 +8,8 @@ import { act, fireEvent, render, waitFakeTimer } from '../../../tests/utils';
|
||||
import Button from '../../button';
|
||||
|
||||
describe('Popconfirm', () => {
|
||||
mountTest(Popconfirm as any);
|
||||
rtlTest(Popconfirm as any);
|
||||
mountTest(() => <Popconfirm title="test" />);
|
||||
rtlTest(() => <Popconfirm title="test" />);
|
||||
|
||||
const eventObject = expect.objectContaining({
|
||||
target: expect.anything(),
|
||||
|
@ -29,8 +29,8 @@ function expectMatchChecked(container: HTMLElement, checkedList: boolean[]) {
|
||||
}
|
||||
|
||||
describe('Segmented', () => {
|
||||
mountTest(Segmented as any);
|
||||
rtlTest(Segmented as any);
|
||||
mountTest(() => <Segmented options={[]} />);
|
||||
rtlTest(() => <Segmented options={[]} />);
|
||||
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
|
@ -1,7 +1,11 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import getDesignToken from './getDesignToken';
|
||||
import type { GlobalToken, MappingAlgorithm } from './interface';
|
||||
import { defaultConfig, useToken as useInternalToken } from './internal';
|
||||
import {
|
||||
defaultConfig,
|
||||
DesignTokenContext as InternalDesignTokenContext,
|
||||
useToken as useInternalToken,
|
||||
} from './internal';
|
||||
import compactAlgorithm from './themes/compact';
|
||||
import darkAlgorithm from './themes/dark';
|
||||
import defaultAlgorithm from './themes/default';
|
||||
@ -19,15 +23,21 @@ function useToken() {
|
||||
export type { GlobalToken, MappingAlgorithm };
|
||||
|
||||
export default {
|
||||
/** @private Test Usage. Do not use in production. */
|
||||
defaultConfig,
|
||||
|
||||
/** Default seedToken */
|
||||
defaultSeed: defaultConfig.token,
|
||||
|
||||
useToken,
|
||||
defaultAlgorithm,
|
||||
darkAlgorithm,
|
||||
compactAlgorithm,
|
||||
getDesignToken,
|
||||
/**
|
||||
* @private Private variable
|
||||
* @warring 🔥 Do not use in production. 🔥
|
||||
*/
|
||||
defaultConfig,
|
||||
/**
|
||||
* @private Private variable
|
||||
* @warring 🔥 Do not use in production. 🔥
|
||||
*/
|
||||
_internalContext: InternalDesignTokenContext,
|
||||
};
|
||||
|
@ -29,7 +29,10 @@ const App: React.FC = () => (
|
||||
treeData={treeData}
|
||||
height={233}
|
||||
defaultExpandAll
|
||||
titleRender={(item) => <MemoTooltip title={item.title as any}>{item.title as any}</MemoTooltip>}
|
||||
titleRender={(item) => {
|
||||
const title = item.title as React.ReactNode;
|
||||
return <MemoTooltip title={title}>{title}</MemoTooltip>;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -224,6 +224,11 @@ export default function EllipsisMeasure(props: EllipsisProps) {
|
||||
|
||||
// ========================= Text Content =========================
|
||||
const finalContent = React.useMemo(() => {
|
||||
// Skip everything if `enableMeasure` is disabled
|
||||
if (!enableMeasure) {
|
||||
return children(nodeList, false);
|
||||
}
|
||||
|
||||
if (
|
||||
needEllipsis !== STATUS_MEASURE_NEED_ELLIPSIS ||
|
||||
!ellipsisCutIndex ||
|
||||
|
@ -25,7 +25,7 @@ import Typography from '../Typography';
|
||||
import CopyBtn from './CopyBtn';
|
||||
import Ellipsis from './Ellipsis';
|
||||
import EllipsisTooltip from './EllipsisTooltip';
|
||||
import { getEleSize } from './util';
|
||||
import { isEleEllipsis } from './util';
|
||||
|
||||
export type BaseType = 'secondary' | 'success' | 'warning' | 'danger';
|
||||
|
||||
@ -281,11 +281,7 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
|
||||
const textEle = typographyRef.current;
|
||||
|
||||
if (enableEllipsis && cssEllipsis && textEle) {
|
||||
const [offsetWidth, offsetHeight] = getEleSize(textEle);
|
||||
|
||||
const currentEllipsis = cssLineClamp
|
||||
? offsetHeight < textEle.scrollHeight
|
||||
: offsetWidth < textEle.scrollWidth;
|
||||
const currentEllipsis = isEleEllipsis(textEle);
|
||||
|
||||
if (isNativeEllipsis !== currentEllipsis) {
|
||||
setIsNativeEllipsis(currentEllipsis);
|
||||
@ -379,15 +375,7 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
|
||||
// Expand
|
||||
const renderExpand = () => {
|
||||
const { expandable, symbol } = ellipsisConfig;
|
||||
|
||||
if (!expandable) {
|
||||
return null;
|
||||
}
|
||||
if (expanded && expandable !== 'collapsible') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
return expandable ? (
|
||||
<TransButton
|
||||
key="expand"
|
||||
className={`${prefixCls}-${expanded ? 'collapse' : 'expand'}`}
|
||||
@ -396,7 +384,7 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
|
||||
>
|
||||
{typeof symbol === 'function' ? symbol(expanded) : symbol}
|
||||
</TransButton>
|
||||
);
|
||||
) : null;
|
||||
};
|
||||
|
||||
// Edit
|
||||
@ -446,7 +434,6 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
|
||||
};
|
||||
|
||||
const renderOperations = (canEllipsis: boolean) => [
|
||||
// (renderExpanded || ellipsisConfig.collapsible) && renderExpand(),
|
||||
canEllipsis && renderExpand(),
|
||||
renderEdit(),
|
||||
renderCopy(),
|
||||
|
@ -13,20 +13,38 @@ export function getNode(dom: React.ReactNode, defaultNode: React.ReactNode, need
|
||||
}
|
||||
|
||||
/**
|
||||
* Get React of element with precision.
|
||||
* ref: https://github.com/ant-design/ant-design/issues/50143
|
||||
* Check for element is native ellipsis
|
||||
* ref:
|
||||
* - https://github.com/ant-design/ant-design/issues/50143
|
||||
* - https://github.com/ant-design/ant-design/issues/50414
|
||||
*/
|
||||
export function getEleSize(ele: HTMLElement): [width: number, height: number] {
|
||||
const rect = ele.getBoundingClientRect();
|
||||
const { offsetWidth, offsetHeight } = ele;
|
||||
export function isEleEllipsis(ele: HTMLElement): boolean {
|
||||
// Create a new div to get the size
|
||||
const childDiv = document.createElement('em');
|
||||
ele.appendChild(childDiv);
|
||||
|
||||
let returnWidth = offsetWidth;
|
||||
let returnHeight = offsetHeight;
|
||||
|
||||
if (Math.abs(offsetWidth - rect.width) < 1 && Math.abs(offsetHeight - rect.height) < 1) {
|
||||
returnWidth = rect.width;
|
||||
returnHeight = rect.height;
|
||||
// For test case
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
childDiv.className = 'ant-typography-css-ellipsis-content-measure';
|
||||
}
|
||||
|
||||
return [returnWidth, returnHeight];
|
||||
const rect = ele.getBoundingClientRect();
|
||||
const childRect = childDiv.getBoundingClientRect();
|
||||
|
||||
// Reset
|
||||
ele.removeChild(childDiv);
|
||||
|
||||
// Range checker
|
||||
if (
|
||||
// Horizontal in range
|
||||
rect.left <= childRect.left &&
|
||||
childRect.right <= rect.right &&
|
||||
// Vertical in range
|
||||
rect.top <= childRect.top &&
|
||||
childRect.bottom <= rect.bottom
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -364,29 +364,48 @@ describe('Typography.Ellipsis', () => {
|
||||
describe('should tooltip support', () => {
|
||||
let domSpy: ReturnType<typeof spyElementPrototypes>;
|
||||
|
||||
let containerWidth = 100;
|
||||
let contentWidth = 200;
|
||||
let rectContainerWidth = 100;
|
||||
let containerRect = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: 100,
|
||||
bottom: 22,
|
||||
};
|
||||
let measureRect = {
|
||||
left: 200,
|
||||
top: 0,
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
domSpy = spyElementPrototypes(HTMLElement, {
|
||||
offsetWidth: {
|
||||
get: () => containerWidth,
|
||||
getBoundingClientRect() {
|
||||
if (
|
||||
(this as unknown as HTMLElement).classList.contains(
|
||||
'ant-typography-css-ellipsis-content-measure',
|
||||
)
|
||||
) {
|
||||
return {
|
||||
...measureRect,
|
||||
right: measureRect.left,
|
||||
bottom: measureRect.top + 22,
|
||||
};
|
||||
}
|
||||
|
||||
return containerRect;
|
||||
},
|
||||
scrollWidth: {
|
||||
get: () => contentWidth,
|
||||
},
|
||||
getBoundingClientRect: () => ({
|
||||
width: rectContainerWidth,
|
||||
height: 0,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
containerWidth = 100;
|
||||
contentWidth = 200;
|
||||
rectContainerWidth = 100;
|
||||
containerRect = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: 100,
|
||||
bottom: 22,
|
||||
};
|
||||
measureRect = {
|
||||
left: 200,
|
||||
top: 0,
|
||||
};
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
@ -453,22 +472,40 @@ describe('Typography.Ellipsis', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/50143
|
||||
it('precision', async () => {
|
||||
containerWidth = 100;
|
||||
contentWidth = 100;
|
||||
rectContainerWidth = 99.9;
|
||||
describe('precision', () => {
|
||||
// https://github.com/ant-design/ant-design/issues/50143
|
||||
it('should show', async () => {
|
||||
containerRect.right = 99.9;
|
||||
measureRect.left = 100;
|
||||
|
||||
const { container, baseElement } = await getWrapper({
|
||||
title: true,
|
||||
className: 'tooltip-class-name',
|
||||
});
|
||||
fireEvent.mouseEnter(container.firstChild!);
|
||||
const { container, baseElement } = await getWrapper({
|
||||
title: true,
|
||||
className: 'tooltip-class-name',
|
||||
});
|
||||
fireEvent.mouseEnter(container.firstChild!);
|
||||
|
||||
await waitFakeTimer();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(container.querySelector('.tooltip-class-name')).toBeTruthy();
|
||||
expect(baseElement.querySelector('.ant-tooltip-open')).not.toBeNull();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/50414
|
||||
it('should not show', async () => {
|
||||
containerRect.right = 48.52;
|
||||
measureRect.left = 48.52;
|
||||
|
||||
const { container, baseElement } = await getWrapper({
|
||||
title: true,
|
||||
className: 'tooltip-class-name',
|
||||
});
|
||||
fireEvent.mouseEnter(container.firstChild!);
|
||||
|
||||
await waitFakeTimer();
|
||||
|
||||
expect(container.querySelector('.tooltip-class-name')).toBeTruthy();
|
||||
expect(baseElement.querySelector('.ant-tooltip-open')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -490,22 +527,26 @@ describe('Typography.Ellipsis', () => {
|
||||
|
||||
it('should display tooltip if line clamp', async () => {
|
||||
mockRectSpy = spyElementPrototypes(HTMLElement, {
|
||||
scrollHeight: {
|
||||
get() {
|
||||
let html = (this as any).innerHTML;
|
||||
html = html.replace(/<[^>]*>/g, '');
|
||||
const lines = Math.ceil(html.length / LINE_STR_COUNT);
|
||||
return lines * 16;
|
||||
},
|
||||
},
|
||||
offsetHeight: {
|
||||
get: () => 32,
|
||||
},
|
||||
offsetWidth: {
|
||||
get: () => 100,
|
||||
},
|
||||
scrollWidth: {
|
||||
get: () => 100,
|
||||
getBoundingClientRect() {
|
||||
if (
|
||||
(this as unknown as HTMLElement).classList.contains(
|
||||
'ant-typography-css-ellipsis-content-measure',
|
||||
)
|
||||
) {
|
||||
return {
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 100,
|
||||
bottom: 122,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
left: 0,
|
||||
right: 100,
|
||||
top: 0,
|
||||
bottom: 22 * 3,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@ -527,6 +568,32 @@ describe('Typography.Ellipsis', () => {
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/46580
|
||||
it('dynamic to be ellipsis should show tooltip', async () => {
|
||||
let dynamicWidth = 100;
|
||||
|
||||
mockRectSpy = spyElementPrototypes(HTMLElement, {
|
||||
getBoundingClientRect() {
|
||||
if (
|
||||
(this as unknown as HTMLElement).classList.contains(
|
||||
'ant-typography-css-ellipsis-content-measure',
|
||||
)
|
||||
) {
|
||||
return {
|
||||
left: 0,
|
||||
right: dynamicWidth,
|
||||
top: 0,
|
||||
bottom: 22,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
left: 100,
|
||||
right: 100,
|
||||
top: 0,
|
||||
bottom: 22,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const ref = React.createRef<HTMLElement>();
|
||||
render(
|
||||
<Base ellipsis={{ tooltip: 'bamboo' }} component="p" ref={ref}>
|
||||
@ -535,8 +602,7 @@ describe('Typography.Ellipsis', () => {
|
||||
);
|
||||
|
||||
// Force to narrow
|
||||
offsetWidth = 1;
|
||||
scrollWidth = 100;
|
||||
dynamicWidth = 50;
|
||||
triggerResize(ref.current!);
|
||||
|
||||
await waitFakeTimer();
|
||||
@ -544,6 +610,8 @@ describe('Typography.Ellipsis', () => {
|
||||
fireEvent.mouseEnter(ref.current!);
|
||||
await waitFakeTimer();
|
||||
expect(document.querySelector('.ant-tooltip')).toBeTruthy();
|
||||
|
||||
mockRectSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('not force single line if expanded', async () => {
|
||||
|
@ -5,37 +5,24 @@ order: 1
|
||||
title: CSS Compatible
|
||||
---
|
||||
|
||||
Ant Design supports the last 2 versions of modern browsers. If you need to be compatible with legacy browsers, please perform downgrade processing according to actual needs:
|
||||
### Default Style Compatibility
|
||||
|
||||
## StyleProvider
|
||||
Ant Design supports the [last 2 versions of modern browsers](https://browsersl.ist/#q=defaults). If you need to be compatible with legacy browsers, please perform downgrade processing according to actual needs:
|
||||
|
||||
Please ref [`@ant-design/cssinjs`](https://github.com/ant-design/cssinjs#styleprovider).
|
||||
| Feature | antd version | Compatibility | Minimum Chrome Version | Compatibility workaround |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| [:where Selector](https://developer.mozilla.org/en-US/docs/Web/CSS/:where) | `>=5.0.0` | [caniuse](https://caniuse.com/?search=%3Awhere) | Chrome 88 | `<StyleProvider hashPriority="high">` |
|
||||
| [CSS Logical Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties) | `>=5.0.0` | [caniuse](https://caniuse.com/css-logical-props) | Chrome 89 | `<StyleProvider transformers={[legacyLogicalPropertiesTransformer]}>` |
|
||||
|
||||
## `layer` Downgrade
|
||||
If you need to support older browsers, please use [StyleProvider](https://github.com/ant-design/cssinjs#styleprovider) for degradation handling according to your actual requirements.
|
||||
|
||||
Ant Design supports configuring `layer` for unified downgrade since `5.17.0`. After the downgrade, the style of antd will always be lower than the default CSS selector priority, so that users can override the style (please be sure to check the browser compatibility of `@layer`):
|
||||
## `:where` in selector
|
||||
|
||||
```tsx
|
||||
import { StyleProvider } from '@ant-design/cssinjs';
|
||||
|
||||
export default () => (
|
||||
<StyleProvider layer>
|
||||
<MyApp />
|
||||
</StyleProvider>
|
||||
);
|
||||
```
|
||||
|
||||
antd styles will be encapsulated in `@layer` to lower the priority:
|
||||
|
||||
```diff
|
||||
++ @layer antd {
|
||||
:where(.css-bAMboO).ant-btn {
|
||||
color: #fff;
|
||||
}
|
||||
++ }
|
||||
```
|
||||
|
||||
## Compatible adjustment
|
||||
- antd version: `>=5.0.0`
|
||||
- MDN: [:where](https://developer.mozilla.org/en-US/docs/Web/CSS/:where)
|
||||
- Browser Compatibility: [caniuse](https://caniuse.com/?search=%3Awhere)
|
||||
- Minimum Chrome Version Supported: 88
|
||||
- Default Enabled: Yes
|
||||
|
||||
The CSS-in-JS feature of Ant Design uses the ":where" selector by default to lower the CSS selector specificity, reducing the additional cost of adjusting custom styles when upgrading for users. However, the compatibility of the ":where" syntax is relatively poor in older browsers ([compatibility](https://developer.mozilla.org/en-US/docs/Web/CSS/:where#browser_compatibility)). In certain scenarios, if you need to support older browsers, you can use `@ant-design/cssinjs` to disable the default lowering of specificity (please ensure version consistency with antd).
|
||||
|
||||
@ -77,6 +64,12 @@ Raise priority through plugin:
|
||||
|
||||
## CSS Logical Properties
|
||||
|
||||
- antd version: `>=5.0.0`
|
||||
- MDN:[CSS Logical Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties)
|
||||
- Browser Compatibility: [caniuse](https://caniuse.com/css-logical-props)
|
||||
- Minimum Chrome Version Supported: 89
|
||||
- Default Enabled: Yes
|
||||
|
||||
To unify LTR and RTL styles, Ant Design uses CSS logical properties. For example, the original `margin-left` is replaced by `margin-inline-start`, so that it is the starting position spacing under both LTR and RTL. If you need to be compatible with older browsers, you can configure `transformers` through the `StyleProvider` of `@ant-design/cssinjs`:
|
||||
|
||||
```tsx
|
||||
@ -102,6 +95,36 @@ When toggled, styles will downgrade CSS logical properties:
|
||||
}
|
||||
```
|
||||
|
||||
## `@layer`
|
||||
|
||||
- antd version: `>=5.17.0`
|
||||
- MDN:[CSS @layer](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer)
|
||||
- Browser Compatibility: [caniuse](https://caniuse.com/css-at-rule-layer)
|
||||
- Minimum Chrome Version Supported: 99
|
||||
- Default Enabled: No
|
||||
|
||||
Ant Design supports configuring `@layer` for unified css priority downgrade since `5.17.0`. After the downgrade, the style of antd will always be lower than the default CSS selector priority, so that users can override the style (please be sure to check the browser compatibility of `@layer`):
|
||||
|
||||
```tsx
|
||||
import { StyleProvider } from '@ant-design/cssinjs';
|
||||
|
||||
export default () => (
|
||||
<StyleProvider layer>
|
||||
<MyApp />
|
||||
</StyleProvider>
|
||||
);
|
||||
```
|
||||
|
||||
antd styles will be encapsulated in `@layer` to lower the priority:
|
||||
|
||||
```diff
|
||||
++ @layer antd {
|
||||
:where(.css-bAMboO).ant-btn {
|
||||
color: #fff;
|
||||
}
|
||||
++ }
|
||||
```
|
||||
|
||||
## Rem Adaptation
|
||||
|
||||
In responsive web development, there is a need for a convenient and flexible way to achieve page adaptation and responsive design. The `px2remTransformer` transformer can quickly and accurately convert pixel units in style sheets to rem units relative to the root element (HTML tag), enabling the implementation of adaptive and responsive layouts.
|
||||
|
@ -5,38 +5,25 @@ order: 1
|
||||
title: 样式兼容
|
||||
---
|
||||
|
||||
Ant Design 支持最近 2 个版本的现代浏览器。如果你需要兼容旧版浏览器,请根据实际需求进行降级处理:
|
||||
## 默认样式兼容性说明
|
||||
|
||||
## StyleProvider
|
||||
Ant Design 5.x 支持[最近 2 个版本的现代浏览器](https://browsersl.ist/#q=defaults)。默认情况下,我们使用了一些现代 CSS 特性来提高样式的可维护性和可扩展性,这些特性在旧版浏览器中可能不被支持,好在我们可以通过一些降级兼容方案来解决。
|
||||
|
||||
查看 [`@ant-design/cssinjs`](https://github.com/ant-design/cssinjs#styleprovider).
|
||||
| 特性 | antd 版本 | 兼容性 | 最低 Chrome 版本 | 降级兼容方案 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| [:where 选择器](https://developer.mozilla.org/en-US/docs/Web/CSS/:where) | `>=5.0.0` | [caniuse](https://caniuse.com/?search=%3Awhere) | Chrome 88 | `<StyleProvider hashPriority="high">` |
|
||||
| [CSS 逻辑属性](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties) | `>=5.0.0` | [caniuse](https://caniuse.com/css-logical-props) | Chrome 89 | `<StyleProvider transformers={[legacyLogicalPropertiesTransformer]}>` |
|
||||
|
||||
## `layer` 降权
|
||||
|
||||
Ant Design 从 `5.17.0` 起支持配置 `layer` 进行统一降权。经过降权后,antd 的样式将始终低于默认的 CSS 选择器优先级,以便于用户进行样式覆盖(请务必注意检查 `@layer` 浏览器兼容性):
|
||||
|
||||
```tsx
|
||||
import { StyleProvider } from '@ant-design/cssinjs';
|
||||
|
||||
export default () => (
|
||||
<StyleProvider layer>
|
||||
<MyApp />
|
||||
</StyleProvider>
|
||||
);
|
||||
```
|
||||
|
||||
antd 的样式会被封装在 `@layer` 中,以降低优先级:
|
||||
|
||||
```diff
|
||||
++ @layer antd {
|
||||
:where(.css-bAMboO).ant-btn {
|
||||
color: #fff;
|
||||
}
|
||||
++ }
|
||||
```
|
||||
如果你需要兼容旧版浏览器,请根据实际需求使用 [StyleProvider](https://github.com/ant-design/cssinjs#styleprovider) 降级处理。
|
||||
|
||||
## `:where` 选择器
|
||||
|
||||
- 支持版本:`>=5.0.0`
|
||||
- MDN 文档:[:where](https://developer.mozilla.org/en-US/docs/Web/CSS/:where)
|
||||
- 浏览器兼容性:[caniuse](https://caniuse.com/?search=%3Awhere)
|
||||
- Chrome 最低支持版本:88
|
||||
- 默认启用:是
|
||||
|
||||
Ant Design 的 CSS-in-JS 默认通过 `:where` 选择器降低 CSS Selector 优先级,以减少用户升级时额外调整自定义样式的成本,不过 `:where` 语法的[兼容性](https://developer.mozilla.org/en-US/docs/Web/CSS/:where#browser_compatibility)在低版本浏览器比较差。在某些场景下你如果需要支持旧版浏览器,你可以使用 `@ant-design/cssinjs` 取消默认的降权操作(请注意版本保持与 antd 一致):
|
||||
|
||||
```tsx
|
||||
@ -77,9 +64,15 @@ export default () => (
|
||||
|
||||
## CSS 逻辑属性
|
||||
|
||||
- 支持版本:`>=5.0.0`
|
||||
- MDN 文档:[:where](https://developer.mozilla.org/en-US/docs/Web/CSS/:where)
|
||||
- 浏览器兼容性:[caniuse](https://caniuse.com/css-logical-props)
|
||||
- Chrome 最低支持版本:89
|
||||
- 默认启用:是
|
||||
|
||||
为了统一 LTR 和 RTL 样式,Ant Design 使用了 CSS 逻辑属性。例如原 `margin-left` 使用 `margin-inline-start` 代替,使其在 LTR 和 RTL 下都为起始位置间距。如果你需要兼容旧版浏览器(如 360 浏览器、QQ 浏览器 等等),可以通过 `@ant-design/cssinjs` 的 `StyleProvider` 配置 `transformers` 将其转换:
|
||||
|
||||
```tsx
|
||||
```tsx | pure
|
||||
import { legacyLogicalPropertiesTransformer, StyleProvider } from '@ant-design/cssinjs';
|
||||
|
||||
// `transformers` 提供预处理功能将样式进行转换
|
||||
@ -102,11 +95,41 @@ export default () => (
|
||||
}
|
||||
```
|
||||
|
||||
## `@layer` 样式优先级降权
|
||||
|
||||
- 支持版本:`>=5.17.0`
|
||||
- MDN 文档:[@layer](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer)
|
||||
- 浏览器兼容性:[caniuse](https://caniuse.com/?search=%40layer)
|
||||
- Chrome 最低支持版本:99
|
||||
- 默认启用:否
|
||||
|
||||
Ant Design 从 `5.17.0` 起支持配置 `layer` 进行统一降权。经过降权后,antd 的样式将始终低于默认的 CSS 选择器优先级,以便于用户进行样式覆盖(请务必注意检查 `@layer` 浏览器兼容性):
|
||||
|
||||
```tsx | pure
|
||||
import { StyleProvider } from '@ant-design/cssinjs';
|
||||
|
||||
export default () => (
|
||||
<StyleProvider layer>
|
||||
<MyApp />
|
||||
</StyleProvider>
|
||||
);
|
||||
```
|
||||
|
||||
antd 的样式会被封装在 `@layer` 中,以降低优先级:
|
||||
|
||||
```diff
|
||||
++ @layer antd {
|
||||
:where(.css-bAMboO).ant-btn {
|
||||
color: #fff;
|
||||
}
|
||||
++ }
|
||||
```
|
||||
|
||||
## rem 适配
|
||||
|
||||
在响应式网页开发中,需要一种方便且灵活的方式来实现页面的适配和响应式设计。`px2remTransformer` 转换器可以快速而准确地将样式表中的像素单位转换为相对于根元素(HTML 标签)的 rem 单位,实现页面的自适应和响应式布局。
|
||||
|
||||
```tsx
|
||||
```tsx | pure
|
||||
import { px2remTransformer, StyleProvider } from '@ant-design/cssinjs';
|
||||
|
||||
const px2rem = px2remTransformer({
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "antd",
|
||||
"version": "5.20.2",
|
||||
"version": "5.20.3",
|
||||
"description": "An enterprise-class UI design language and React components implementation",
|
||||
"keywords": [
|
||||
"ant",
|
||||
@ -340,11 +340,13 @@
|
||||
"size-limit": [
|
||||
{
|
||||
"path": "./dist/antd.min.js",
|
||||
"limit": "350 KiB"
|
||||
"limit": "500 KiB",
|
||||
"gzip": true
|
||||
},
|
||||
{
|
||||
"path": "./dist/antd-with-locales.min.js",
|
||||
"limit": "400 KiB"
|
||||
"limit": "500 KiB",
|
||||
"gzip": true
|
||||
}
|
||||
],
|
||||
"title": "Ant Design",
|
||||
|
Loading…
Reference in New Issue
Block a user