diff --git a/components/carousel/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/carousel/__tests__/__snapshots__/demo-extend.test.ts.snap
index 80ef71c3ff..ebe3c3c045 100644
--- a/components/carousel/__tests__/__snapshots__/demo-extend.test.ts.snap
+++ b/components/carousel/__tests__/__snapshots__/demo-extend.test.ts.snap
@@ -1,5 +1,316 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`renders components/carousel/demo/arrows.tsx extend context correctly 1`] = `
+Array [
+
(
+ <>
+
+
+
1
+
+
+
2
+
+
+
3
+
+
+
4
+
+
+
+
+
+
1
+
+
+
2
+
+
+
3
+
+
+
4
+
+
+ >
+);
+
+export default App;
diff --git a/components/carousel/index.en-US.md b/components/carousel/index.en-US.md
index 9027df75f8..bb8da01285 100644
--- a/components/carousel/index.en-US.md
+++ b/components/carousel/index.en-US.md
@@ -22,6 +22,7 @@ demo:
Position
Scroll automatically
Fade in
+
Arrows for switching
Component Token
## API
@@ -30,6 +31,7 @@ Common props ref:[Common props](/docs/react/common-props)
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
+| arrows | Whether to show switch arrows | boolean | false | 5.17.0 |
| autoplay | Whether to scroll automatically | boolean | false | |
| autoplaySpeed | Delay between each auto scroll (in milliseconds) | number | 3000 | |
| dotPosition | The position of the dots, which can be one of `top` `bottom` `left` `right` | string | `bottom` | |
diff --git a/components/carousel/index.tsx b/components/carousel/index.tsx
index c963d66147..915b09bdf6 100644
--- a/components/carousel/index.tsx
+++ b/components/carousel/index.tsx
@@ -35,6 +35,8 @@ const Carousel = React.forwardRef
((props, ref) => {
const {
dots = true,
arrows = false,
+ prevArrow = ,
+ nextArrow = ,
draggable = false,
waitForAnimate = false,
dotPosition = 'bottom',
@@ -115,6 +117,8 @@ const Carousel = React.forwardRef((props, ref) => {
dots={enableDots}
dotsClass={dsClass}
arrows={arrows}
+ prevArrow={prevArrow}
+ nextArrow={nextArrow}
draggable={draggable}
verticalSwiping={vertical}
waitForAnimate={waitForAnimate}
diff --git a/components/carousel/index.zh-CN.md b/components/carousel/index.zh-CN.md
index 872112885e..9061edcc1b 100644
--- a/components/carousel/index.zh-CN.md
+++ b/components/carousel/index.zh-CN.md
@@ -23,6 +23,7 @@ demo:
位置
自动切换
渐显
+切换箭头
组件 Token
## API
@@ -31,6 +32,7 @@ demo:
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
+| arrows | 是否显示箭头 | boolean | false | 5.17.0 |
| autoplay | 是否自动切换 | boolean | false | |
| autoplaySpeed | 自动切换的间隔(毫秒) | number | 3000 | |
| dotPosition | 面板指示点位置,可选 `top` `bottom` `left` `right` | string | `bottom` | |
diff --git a/components/carousel/style/index.ts b/components/carousel/style/index.ts
index 8bb5087e30..87660d6cf6 100644
--- a/components/carousel/style/index.ts
+++ b/components/carousel/style/index.ts
@@ -2,7 +2,7 @@ import { unit } from '@ant-design/cssinjs';
import { resetComponent } from '../../style';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
-import { genStyleHooks, mergeToken } from '../../theme/internal';
+import { genStyleHooks } from '../../theme/internal';
export interface ComponentToken {
/**
@@ -15,6 +15,16 @@ export interface ComponentToken {
* @descEN Height of indicator
*/
dotHeight: number;
+ /**
+ * @desc 指示点之间的间距
+ * @descEN gap between indicator
+ */
+ dotGap: number;
+ /**
+ * @desc 指示点距离边缘的距离
+ * @descEN dot offset to Carousel edge
+ */
+ dotOffset: number;
/** @deprecated Use `dotActiveWidth` instead. */
dotWidthActive: number;
/**
@@ -22,19 +32,22 @@ export interface ComponentToken {
* @descEN Width of active indicator
*/
dotActiveWidth: number;
+ /**
+ * @desc 切换箭头大小
+ * @descEN Size of arrows
+ */
+ arrowSize: number;
+ /**
+ * @desc 切换箭头边距
+ * @descEN arrows offset to Carousel edge
+ */
+ arrowOffset: number;
}
-interface CarouselToken extends FullToken<'Carousel'> {
- carouselArrowSize: string | number;
- carouselDotOffset: string | number;
- carouselDotInline: string | number;
-}
+interface CarouselToken extends FullToken<'Carousel'> {}
const genCarouselStyle: GenerateStyle = (token) => {
- const { componentCls, antCls, carouselArrowSize, carouselDotOffset, marginXXS } = token;
- const arrowOffset = token.calc(carouselArrowSize).mul(-1.25).equal();
-
- const carouselDotMargin = marginXXS;
+ const { componentCls, antCls } = token;
return {
[componentCls]: {
@@ -133,142 +146,176 @@ const genCarouselStyle: GenerateStyle = (token) => {
display: 'block',
height: 'auto',
},
+ },
+ };
+};
- '.slick-arrow.slick-hidden': {
- display: 'none',
- },
+const genArrowsStyle: GenerateStyle = (token) => {
+ const { componentCls, motionDurationSlow, arrowSize, arrowOffset } = token;
+ const arrowLength = token.calc(arrowSize).div(1.414).equal();
- // Arrows
- '.slick-prev, .slick-next': {
- position: 'absolute',
- top: '50%',
- display: 'block',
- width: carouselArrowSize,
- height: carouselArrowSize,
- marginTop: token.calc(carouselArrowSize).mul(-1).div(2).equal(),
- padding: 0,
- color: 'transparent',
- fontSize: 0,
- lineHeight: 0,
- background: 'transparent',
- border: 0,
- outline: 'none',
- cursor: 'pointer',
-
- '&:hover, &:focus': {
- color: 'transparent',
+ return [
+ {
+ [componentCls]: {
+ // Arrows
+ '.slick-prev, .slick-next': {
+ position: 'absolute',
+ top: '50%',
+ width: arrowSize,
+ height: arrowSize,
+ transform: 'translateY(-50%)',
+ color: '#fff',
+ opacity: 0.4,
background: 'transparent',
+ padding: 0,
+ lineHeight: 0,
+ border: 0,
outline: 'none',
+ cursor: 'pointer',
+ zIndex: 1,
+ transition: `opacity ${motionDurationSlow}`,
- '&::before': {
+ '&:hover, &:focus': {
opacity: 1,
},
- },
- '&.slick-disabled::before': {
- opacity: 0.25,
- },
- },
-
- '.slick-prev': {
- insetInlineStart: arrowOffset,
-
- '&::before': {
- content: '"←"',
- },
- },
-
- '.slick-next': {
- insetInlineEnd: arrowOffset,
-
- '&::before': {
- content: '"→"',
- },
- },
-
- // Dots
- '.slick-dots': {
- position: 'absolute',
- insetInlineEnd: 0,
- bottom: 0,
- insetInlineStart: 0,
- zIndex: 15,
- display: 'flex !important',
- justifyContent: 'center',
- paddingInlineStart: 0,
- margin: 0,
- listStyle: 'none',
-
- '&-bottom': {
- bottom: carouselDotOffset,
- },
-
- '&-top': {
- top: carouselDotOffset,
- bottom: 'auto',
- },
-
- li: {
- position: 'relative',
- display: 'inline-block',
- flex: '0 1 auto',
- boxSizing: 'content-box',
- width: token.dotWidth,
- height: token.dotHeight,
- marginInline: carouselDotMargin,
- padding: 0,
- textAlign: 'center',
- textIndent: -999,
- verticalAlign: 'top',
- transition: `all ${token.motionDurationSlow}`,
-
- button: {
- position: 'relative',
- display: 'block',
- width: '100%',
- height: token.dotHeight,
- padding: 0,
- color: 'transparent',
- fontSize: 0,
- background: token.colorBgContainer,
- border: 0,
- borderRadius: token.dotHeight,
- outline: 'none',
- cursor: 'pointer',
- opacity: 0.3,
- transition: `all ${token.motionDurationSlow}`,
-
- '&: hover, &:focus': {
- opacity: 0.75,
- },
-
- '&::after': {
- position: 'absolute',
- inset: token.calc(carouselDotMargin).mul(-1).equal(),
- content: '""',
- },
+ '&.slick-disabled': {
+ pointerEvents: 'none',
+ opacity: 0,
},
- '&.slick-active': {
- width: token.dotActiveWidth,
+ '&::after': {
+ boxSizing: 'border-box',
+ position: 'absolute',
+ top: token.calc(arrowSize).sub(arrowLength).div(2).equal(),
+ insetInlineStart: token.calc(arrowSize).sub(arrowLength).div(2).equal(),
+ display: 'inline-block',
+ width: arrowLength,
+ height: arrowLength,
+ border: `0 solid currentcolor`,
+ borderInlineWidth: '2px 0',
+ borderBlockWidth: '2px 0',
+ borderRadius: 1,
+ content: '""',
+ },
+ },
- '& button': {
- background: token.colorBgContainer,
- opacity: 1,
+ '.slick-prev': {
+ insetInlineStart: arrowOffset,
+
+ '&::after': {
+ transform: 'rotate(-45deg)',
+ },
+ },
+
+ '.slick-next': {
+ insetInlineEnd: arrowOffset,
+
+ '&::after': {
+ transform: 'rotate(135deg)',
+ },
+ },
+ },
+ },
+ ];
+};
+
+const genDotsStyle: GenerateStyle = (token) => {
+ const {
+ componentCls,
+ dotOffset,
+ dotWidth,
+ dotHeight,
+ dotGap,
+ colorBgContainer,
+ motionDurationSlow,
+ } = token;
+ return [
+ {
+ [componentCls]: {
+ '.slick-dots': {
+ position: 'absolute',
+ insetInlineEnd: 0,
+ bottom: 0,
+ insetInlineStart: 0,
+ zIndex: 15,
+ display: 'flex !important',
+ justifyContent: 'center',
+ paddingInlineStart: 0,
+ margin: 0,
+ listStyle: 'none',
+
+ '&-bottom': {
+ bottom: dotOffset,
+ },
+
+ '&-top': {
+ top: dotOffset,
+ bottom: 'auto',
+ },
+
+ li: {
+ position: 'relative',
+ display: 'inline-block',
+ flex: '0 1 auto',
+ boxSizing: 'content-box',
+ width: dotWidth,
+ height: dotHeight,
+ marginInline: dotGap,
+ padding: 0,
+ textAlign: 'center',
+ textIndent: -999,
+ verticalAlign: 'top',
+ transition: `all ${motionDurationSlow}`,
+
+ button: {
+ position: 'relative',
+ display: 'block',
+ width: '100%',
+ height: dotHeight,
+ padding: 0,
+ color: 'transparent',
+ fontSize: 0,
+ background: colorBgContainer,
+ border: 0,
+ borderRadius: dotHeight,
+ outline: 'none',
+ cursor: 'pointer',
+ opacity: 0.2,
+ transition: `all ${motionDurationSlow}`,
+
+ '&: hover, &:focus': {
+ opacity: 0.75,
+ },
+
+ '&::after': {
+ position: 'absolute',
+ inset: token.calc(dotGap).mul(-1).equal(),
+ content: '""',
+ },
},
- '&: hover, &:focus': {
- opacity: 1,
+ '&.slick-active': {
+ width: token.dotActiveWidth,
+
+ '& button': {
+ background: colorBgContainer,
+ opacity: 1,
+ },
+
+ '&: hover, &:focus': {
+ opacity: 1,
+ },
},
},
},
},
},
- };
+ ];
};
const genCarouselVerticalStyle: GenerateStyle = (token) => {
- const { componentCls, carouselDotOffset, marginXXS } = token;
+ const { componentCls, dotOffset, arrowOffset, marginXXS } = token;
const reverseSizeOfDot = {
width: token.dotHeight,
@@ -277,6 +324,26 @@ const genCarouselVerticalStyle: GenerateStyle = (token) => {
return {
[`${componentCls}-vertical`]: {
+ '.slick-prev, .slick-next': {
+ insetInlineStart: '50%',
+ marginBlockStart: 'unset',
+ transform: 'translateX(-50%)',
+ },
+ '.slick-prev': {
+ insetBlockStart: arrowOffset,
+ insetInlineStart: '50%',
+
+ '&::after': {
+ transform: 'rotate(45deg)',
+ },
+ },
+ '.slick-next': {
+ insetBlockStart: 'auto',
+ insetBlockEnd: arrowOffset,
+ '&::after': {
+ transform: 'rotate(-135deg)',
+ },
+ },
'.slick-dots': {
top: '50%',
bottom: 'auto',
@@ -288,11 +355,11 @@ const genCarouselVerticalStyle: GenerateStyle = (token) => {
'&-left': {
insetInlineEnd: 'auto',
- insetInlineStart: carouselDotOffset,
+ insetInlineStart: dotOffset,
},
'&-right': {
- insetInlineEnd: carouselDotOffset,
+ insetInlineEnd: dotOffset,
insetInlineStart: 'auto',
},
@@ -343,12 +410,16 @@ const genCarouselRtlStyle: GenerateStyle = (token) => {
];
};
-export const prepareComponentToken: GetDefaultToken<'Carousel'> = () => {
+export const prepareComponentToken: GetDefaultToken<'Carousel'> = (token) => {
const dotActiveWidth = 24;
return {
+ arrowSize: 16,
+ arrowOffset: token.marginXS,
dotWidth: 16,
dotHeight: 3,
+ dotGap: token.marginXXS,
+ dotOffset: 12,
dotWidthActive: dotActiveWidth,
dotActiveWidth,
};
@@ -357,19 +428,13 @@ export const prepareComponentToken: GetDefaultToken<'Carousel'> = () => {
// ============================== Export ==============================
export default genStyleHooks(
'Carousel',
- (token) => {
- const { controlHeightLG, controlHeightSM } = token;
- const carouselToken = mergeToken(token, {
- carouselArrowSize: token.calc(controlHeightLG).div(2).equal(),
- carouselDotOffset: token.calc(controlHeightSM).div(2).equal(),
- });
-
- return [
- genCarouselStyle(carouselToken),
- genCarouselVerticalStyle(carouselToken),
- genCarouselRtlStyle(carouselToken),
- ];
- },
+ (token) => [
+ genCarouselStyle(token),
+ genArrowsStyle(token),
+ genDotsStyle(token),
+ genCarouselVerticalStyle(token),
+ genCarouselRtlStyle(token),
+ ],
prepareComponentToken,
{
deprecatedTokens: [['dotWidthActive', 'dotActiveWidth']],
diff --git a/components/date-picker/style/panel.ts b/components/date-picker/style/panel.ts
index fc3188562a..128fd9716c 100644
--- a/components/date-picker/style/panel.ts
+++ b/components/date-picker/style/panel.ts
@@ -308,10 +308,8 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
width: pickerControlIconSize,
height: pickerControlIconSize,
border: `0 solid currentcolor`,
- borderBlockStartWidth: pickerControlIconBorderWidth,
- borderBlockEndWidth: 0,
- borderInlineStartWidth: pickerControlIconBorderWidth,
- borderInlineEndWidth: 0,
+ borderBlockWidth: `${unit(pickerControlIconBorderWidth)} 0`,
+ borderInlineWidth: `${unit(pickerControlIconBorderWidth)} 0`,
content: '""',
},
},
@@ -326,10 +324,8 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
width: pickerControlIconSize,
height: pickerControlIconSize,
border: '0 solid currentcolor',
- borderBlockStartWidth: pickerControlIconBorderWidth,
- borderBlockEndWidth: 0,
- borderInlineStartWidth: pickerControlIconBorderWidth,
- borderInlineEndWidth: 0,
+ borderBlockWidth: `${unit(pickerControlIconBorderWidth)} 0`,
+ borderInlineWidth: `${unit(pickerControlIconBorderWidth)} 0`,
content: '""',
},
},