mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-18 11:18:14 +08:00
feat: tabs support cssVar (#45803)
* feat: tabs support cssVar * feat: optimize code * Update components/tabs/style/index.ts Co-authored-by: MadCcc <madccc@foxmail.com> Signed-off-by: kiner-tang(文辉) <1127031143@qq.com> * feat: optimize code --------- Signed-off-by: kiner-tang(文辉) <1127031143@qq.com> Co-authored-by: MadCcc <madccc@foxmail.com>
This commit is contained in:
parent
149c89259f
commit
fc62994a1e
@ -14,6 +14,8 @@ import type { SizeType } from '../config-provider/SizeContext';
|
||||
import useAnimateConfig from './hooks/useAnimateConfig';
|
||||
import useLegacyItems from './hooks/useLegacyItems';
|
||||
import useStyle from './style';
|
||||
import useCSSVar from './style/cssVar';
|
||||
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
|
||||
import TabPane, { type TabPaneProps } from './TabPane';
|
||||
|
||||
export type TabsType = 'line' | 'card' | 'editable-card';
|
||||
@ -53,7 +55,10 @@ const Tabs: React.FC<TabsProps> & { TabPane: typeof TabPane } = (props) => {
|
||||
const { prefixCls: customizePrefixCls, moreIcon = <EllipsisOutlined /> } = otherProps;
|
||||
const { direction, tabs, getPrefixCls, getPopupContainer } = React.useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('tabs', customizePrefixCls);
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
const [, hashId] = useStyle(prefixCls);
|
||||
const rootCls = useCSSVarCls(prefixCls);
|
||||
|
||||
const wrapCSSVar = useCSSVar(rootCls);
|
||||
|
||||
let editable: EditableConfig | undefined;
|
||||
if (type === 'editable-card') {
|
||||
@ -86,7 +91,7 @@ const Tabs: React.FC<TabsProps> & { TabPane: typeof TabPane } = (props) => {
|
||||
|
||||
const mergedStyle: React.CSSProperties = { ...tabs?.style, ...style };
|
||||
|
||||
return wrapSSR(
|
||||
return wrapCSSVar(
|
||||
<RcTabs
|
||||
direction={direction}
|
||||
getPopupContainer={getPopupContainer}
|
||||
@ -104,8 +109,9 @@ const Tabs: React.FC<TabsProps> & { TabPane: typeof TabPane } = (props) => {
|
||||
className,
|
||||
rootClassName,
|
||||
hashId,
|
||||
rootCls,
|
||||
)}
|
||||
popupClassName={classNames(popupClassName, hashId)}
|
||||
popupClassName={classNames(popupClassName, hashId, rootCls)}
|
||||
style={mergedStyle}
|
||||
editable={editable}
|
||||
moreIcon={moreIcon}
|
||||
|
4
components/tabs/style/cssVar.ts
Normal file
4
components/tabs/style/cssVar.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { genCSSVarRegister } from '../../theme/internal';
|
||||
import { prepareComponentToken } from '.';
|
||||
|
||||
export default genCSSVarRegister('Tabs', prepareComponentToken);
|
@ -1,6 +1,7 @@
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
import { unit, type CSSObject } from '@ant-design/cssinjs';
|
||||
|
||||
import { genFocusStyle, resetComponent, textEllipsis } from '../../style';
|
||||
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||
import genMotionStyle from './motion';
|
||||
|
||||
@ -154,7 +155,7 @@ const genCardStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
margin: 0,
|
||||
padding: tabsCardPadding,
|
||||
background: cardBg,
|
||||
border: `${token.lineWidth}px ${token.lineType} ${colorBorderSecondary}`,
|
||||
border: `${unit(token.lineWidth)} ${token.lineType} ${colorBorderSecondary}`,
|
||||
transition: `all ${token.motionDurationSlow} ${token.motionEaseInOut}`,
|
||||
},
|
||||
|
||||
@ -174,7 +175,7 @@ const genCardStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
[`${componentCls}-tab + ${componentCls}-tab`]: {
|
||||
marginLeft: {
|
||||
_skip_check_: true,
|
||||
value: `${cardGutter}px`,
|
||||
value: unit(cardGutter),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -183,7 +184,7 @@ const genCardStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
[`&${componentCls}-top`]: {
|
||||
[`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
|
||||
[`${componentCls}-tab`]: {
|
||||
borderRadius: `${token.borderRadiusLG}px ${token.borderRadiusLG}px 0 0`,
|
||||
borderRadius: `${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)} 0 0`,
|
||||
},
|
||||
|
||||
[`${componentCls}-tab-active`]: {
|
||||
@ -195,7 +196,7 @@ const genCardStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
[`&${componentCls}-bottom`]: {
|
||||
[`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
|
||||
[`${componentCls}-tab`]: {
|
||||
borderRadius: `0 0 ${token.borderRadiusLG}px ${token.borderRadiusLG}px`,
|
||||
borderRadius: `0 0 ${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)}`,
|
||||
},
|
||||
|
||||
[`${componentCls}-tab-active`]: {
|
||||
@ -208,7 +209,7 @@ const genCardStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
[`&${componentCls}-left, &${componentCls}-right`]: {
|
||||
[`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
|
||||
[`${componentCls}-tab + ${componentCls}-tab`]: {
|
||||
marginTop: `${cardGutter}px`,
|
||||
marginTop: unit(cardGutter),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -218,7 +219,7 @@ const genCardStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
[`${componentCls}-tab`]: {
|
||||
borderRadius: {
|
||||
_skip_check_: true,
|
||||
value: `${token.borderRadiusLG}px 0 0 ${token.borderRadiusLG}px`,
|
||||
value: `${unit(token.borderRadiusLG)} 0 0 ${unit(token.borderRadiusLG)}`,
|
||||
},
|
||||
},
|
||||
|
||||
@ -236,7 +237,7 @@ const genCardStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
[`${componentCls}-tab`]: {
|
||||
borderRadius: {
|
||||
_skip_check_: true,
|
||||
value: `0 ${token.borderRadiusLG}px ${token.borderRadiusLG}px 0`,
|
||||
value: `0 ${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)} 0`,
|
||||
},
|
||||
},
|
||||
|
||||
@ -274,7 +275,7 @@ const genDropdownStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject
|
||||
[`${componentCls}-dropdown-menu`]: {
|
||||
maxHeight: token.tabsDropdownHeight,
|
||||
margin: 0,
|
||||
padding: `${dropdownEdgeChildVerticalPadding}px 0`,
|
||||
padding: `${unit(dropdownEdgeChildVerticalPadding)} 0`,
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
textAlign: {
|
||||
@ -294,7 +295,7 @@ const genDropdownStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject
|
||||
alignItems: 'center',
|
||||
minWidth: token.tabsDropdownWidth,
|
||||
margin: 0,
|
||||
padding: `${token.paddingXXS}px ${token.paddingSM}px`,
|
||||
padding: `${unit(token.paddingXXS)} ${unit(token.paddingSM)}`,
|
||||
color: token.colorText,
|
||||
fontWeight: 'normal',
|
||||
fontSize: token.fontSize,
|
||||
@ -368,7 +369,7 @@ const genPositionStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject
|
||||
_skip_check_: true,
|
||||
value: 0,
|
||||
},
|
||||
borderBottom: `${token.lineWidth}px ${token.lineType} ${colorBorderSecondary}`,
|
||||
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${colorBorderSecondary}`,
|
||||
content: "''",
|
||||
},
|
||||
|
||||
@ -430,7 +431,7 @@ const genPositionStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject
|
||||
[`${componentCls}-bottom`]: {
|
||||
[`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
|
||||
order: 1,
|
||||
marginTop: `${margin}px`,
|
||||
marginTop: margin,
|
||||
marginBottom: 0,
|
||||
|
||||
'&::before': {
|
||||
@ -451,7 +452,7 @@ const genPositionStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject
|
||||
[`${componentCls}-left, ${componentCls}-right`]: {
|
||||
[`> ${componentCls}-nav, > div > ${componentCls}-nav`]: {
|
||||
flexDirection: 'column',
|
||||
minWidth: token.controlHeight * 1.25,
|
||||
minWidth: token.calc(token.controlHeight).mul(1.25).equal(),
|
||||
|
||||
// >>>>>>>>>>> Tab
|
||||
[`${componentCls}-tab`]: {
|
||||
@ -527,11 +528,11 @@ const genPositionStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject
|
||||
[`> ${componentCls}-content-holder, > div > ${componentCls}-content-holder`]: {
|
||||
marginLeft: {
|
||||
_skip_check_: true,
|
||||
value: `-${token.lineWidth}px`,
|
||||
value: `-${unit(token.lineWidth)}`,
|
||||
},
|
||||
borderLeft: {
|
||||
_skip_check_: true,
|
||||
value: `${token.lineWidth}px ${token.lineType} ${token.colorBorder}`,
|
||||
value: `${unit(token.lineWidth)} ${token.lineType} ${token.colorBorder}`,
|
||||
},
|
||||
|
||||
[`> ${componentCls}-content > ${componentCls}-tabpane`]: {
|
||||
@ -559,11 +560,11 @@ const genPositionStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject
|
||||
order: 0,
|
||||
marginRight: {
|
||||
_skip_check_: true,
|
||||
value: -token.lineWidth,
|
||||
value: token.calc(token.lineWidth).mul(-1).equal(),
|
||||
},
|
||||
borderRight: {
|
||||
_skip_check_: true,
|
||||
value: `${token.lineWidth}px ${token.lineType} ${token.colorBorder}`,
|
||||
value: `${unit(token.lineWidth)} ${token.lineType} ${token.colorBorder}`,
|
||||
},
|
||||
|
||||
[`> ${componentCls}-content > ${componentCls}-tabpane`]: {
|
||||
@ -615,19 +616,19 @@ const genSizeStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
},
|
||||
[`&${componentCls}-bottom`]: {
|
||||
[`> ${componentCls}-nav ${componentCls}-tab`]: {
|
||||
borderRadius: `0 0 ${token.borderRadius}px ${token.borderRadius}px`,
|
||||
borderRadius: `0 0 ${unit(token.borderRadius)} ${unit(token.borderRadius)}`,
|
||||
},
|
||||
},
|
||||
[`&${componentCls}-top`]: {
|
||||
[`> ${componentCls}-nav ${componentCls}-tab`]: {
|
||||
borderRadius: `${token.borderRadius}px ${token.borderRadius}px 0 0`,
|
||||
borderRadius: `${unit(token.borderRadius)} ${unit(token.borderRadius)} 0 0`,
|
||||
},
|
||||
},
|
||||
[`&${componentCls}-right`]: {
|
||||
[`> ${componentCls}-nav ${componentCls}-tab`]: {
|
||||
borderRadius: {
|
||||
_skip_check_: true,
|
||||
value: `0 ${token.borderRadius}px ${token.borderRadius}px 0`,
|
||||
value: `0 ${unit(token.borderRadius)} ${unit(token.borderRadius)} 0`,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -635,7 +636,7 @@ const genSizeStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
[`> ${componentCls}-nav ${componentCls}-tab`]: {
|
||||
borderRadius: {
|
||||
_skip_check_: true,
|
||||
value: `${token.borderRadius}px 0 0 ${token.borderRadius}px`,
|
||||
value: `${unit(token.borderRadius)} 0 0 ${unit(token.borderRadius)}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -694,7 +695,7 @@ const genTabStyle: GenerateStyle<TabsToken, CSSObject> = (token: TabsToken) => {
|
||||
flex: 'none',
|
||||
marginRight: {
|
||||
_skip_check_: true,
|
||||
value: -token.marginXXS,
|
||||
value: token.calc(token.marginXXS).mul(-1).equal(),
|
||||
},
|
||||
marginLeft: {
|
||||
_skip_check_: true,
|
||||
@ -777,18 +778,18 @@ const genRtlStyle: GenerateStyle<TabsToken, CSSObject> = (token: TabsToken) => {
|
||||
},
|
||||
marginLeft: {
|
||||
_skip_check_: true,
|
||||
value: `${token.marginSM}px`,
|
||||
value: unit(token.marginSM),
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-tab-remove`]: {
|
||||
marginRight: {
|
||||
_skip_check_: true,
|
||||
value: `${token.marginXS}px`,
|
||||
value: unit(token.marginXS),
|
||||
},
|
||||
marginLeft: {
|
||||
_skip_check_: true,
|
||||
value: `-${token.marginXXS}px`,
|
||||
value: `-${unit(token.marginXXS)}`,
|
||||
},
|
||||
|
||||
[iconCls]: {
|
||||
@ -926,7 +927,7 @@ const genTabsStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
_skip_check_: true,
|
||||
value: 0,
|
||||
},
|
||||
height: token.controlHeightLG / 8,
|
||||
height: token.calc(token.controlHeightLG).div(8).equal(),
|
||||
transform: 'translateY(100%)',
|
||||
content: "''",
|
||||
},
|
||||
@ -938,10 +939,10 @@ const genTabsStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
_skip_check_: true,
|
||||
value: cardGutter,
|
||||
},
|
||||
padding: `0 ${token.paddingXS}px`,
|
||||
padding: `0 ${unit(token.paddingXS)}`,
|
||||
background: 'transparent',
|
||||
border: `${token.lineWidth}px ${token.lineType} ${colorBorderSecondary}`,
|
||||
borderRadius: `${token.borderRadiusLG}px ${token.borderRadiusLG}px 0 0`,
|
||||
border: `${unit(token.lineWidth)} ${token.lineType} ${colorBorderSecondary}`,
|
||||
borderRadius: `${unit(token.borderRadiusLG)} ${unit(token.borderRadiusLG)} 0 0`,
|
||||
outline: 'none',
|
||||
cursor: 'pointer',
|
||||
color: token.colorText,
|
||||
@ -1005,23 +1006,54 @@ const genTabsStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
||||
};
|
||||
};
|
||||
|
||||
export const prepareComponentToken: GetDefaultToken<'Tabs'> = (token) => {
|
||||
const cardHeight = token.controlHeightLG;
|
||||
|
||||
return {
|
||||
zIndexPopup: token.zIndexPopupBase + 50,
|
||||
cardBg: token.colorFillAlter,
|
||||
cardHeight,
|
||||
// Initialize with empty string, because cardPadding will be calculated with cardHeight by default.
|
||||
cardPadding: `${
|
||||
(cardHeight - Math.round(token.fontSize * token.lineHeight)) / 2 - token.lineWidth
|
||||
}px ${token.padding}px`,
|
||||
cardPaddingSM: `${token.paddingXXS * 1.5}px ${token.padding}px`,
|
||||
cardPaddingLG: `${token.paddingXS}px ${token.padding}px ${token.paddingXXS * 1.5}px`,
|
||||
titleFontSize: token.fontSize,
|
||||
titleFontSizeLG: token.fontSizeLG,
|
||||
titleFontSizeSM: token.fontSize,
|
||||
inkBarColor: token.colorPrimary,
|
||||
horizontalMargin: `0 0 ${token.margin}px 0`,
|
||||
horizontalItemGutter: 32, // Fixed Value
|
||||
// Initialize with empty string, because horizontalItemMargin will be calculated with horizontalItemGutter by default.
|
||||
horizontalItemMargin: ``,
|
||||
horizontalItemMarginRTL: ``,
|
||||
horizontalItemPadding: `${token.paddingSM}px 0`,
|
||||
horizontalItemPaddingSM: `${token.paddingXS}px 0`,
|
||||
horizontalItemPaddingLG: `${token.padding}px 0`,
|
||||
verticalItemPadding: `${token.paddingXS}px ${token.paddingLG}px`,
|
||||
verticalItemMargin: `${token.margin}px 0 0 0`,
|
||||
itemColor: token.colorText,
|
||||
itemSelectedColor: token.colorPrimary,
|
||||
itemHoverColor: token.colorPrimaryHover,
|
||||
itemActiveColor: token.colorPrimaryActive,
|
||||
cardGutter: token.marginXXS / 2,
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook(
|
||||
'Tabs',
|
||||
(token) => {
|
||||
const tabsToken = mergeToken<TabsToken>(token, {
|
||||
// `cardPadding` is empty by default, so we could calculate with dynamic `cardHeight`
|
||||
tabsCardPadding:
|
||||
token.cardPadding ||
|
||||
`${
|
||||
(token.cardHeight - Math.round(token.fontSize * token.lineHeight)) / 2 - token.lineWidth
|
||||
}px ${token.padding}px`,
|
||||
tabsCardPadding: token.cardPadding,
|
||||
dropdownEdgeChildVerticalPadding: token.paddingXXS,
|
||||
tabsActiveTextShadow: '0 0 0.25px currentcolor',
|
||||
tabsDropdownHeight: 200,
|
||||
tabsDropdownWidth: 120,
|
||||
tabsHorizontalItemMargin: `0 0 0 ${token.horizontalItemGutter}px`,
|
||||
tabsHorizontalItemMarginRTL: `0 0 0 ${token.horizontalItemGutter}px`,
|
||||
tabsHorizontalItemMargin: `0 0 0 ${unit(token.horizontalItemGutter)}`,
|
||||
tabsHorizontalItemMarginRTL: `0 0 0 ${unit(token.horizontalItemGutter)}`,
|
||||
});
|
||||
|
||||
return [
|
||||
@ -1034,36 +1066,5 @@ export default genComponentStyleHook(
|
||||
genMotionStyle(tabsToken),
|
||||
];
|
||||
},
|
||||
(token) => {
|
||||
const cardHeight = token.controlHeightLG;
|
||||
|
||||
return {
|
||||
zIndexPopup: token.zIndexPopupBase + 50,
|
||||
cardBg: token.colorFillAlter,
|
||||
cardHeight,
|
||||
// Initialize with empty string, because cardPadding will be calculated with cardHeight by default.
|
||||
cardPadding: ``,
|
||||
cardPaddingSM: `${token.paddingXXS * 1.5}px ${token.padding}px`,
|
||||
cardPaddingLG: `${token.paddingXS}px ${token.padding}px ${token.paddingXXS * 1.5}px`,
|
||||
titleFontSize: token.fontSize,
|
||||
titleFontSizeLG: token.fontSizeLG,
|
||||
titleFontSizeSM: token.fontSize,
|
||||
inkBarColor: token.colorPrimary,
|
||||
horizontalMargin: `0 0 ${token.margin}px 0`,
|
||||
horizontalItemGutter: 32, // Fixed Value
|
||||
// Initialize with empty string, because horizontalItemMargin will be calculated with horizontalItemGutter by default.
|
||||
horizontalItemMargin: ``,
|
||||
horizontalItemMarginRTL: ``,
|
||||
horizontalItemPadding: `${token.paddingSM}px 0`,
|
||||
horizontalItemPaddingSM: `${token.paddingXS}px 0`,
|
||||
horizontalItemPaddingLG: `${token.padding}px 0`,
|
||||
verticalItemPadding: `${token.paddingXS}px ${token.paddingLG}px`,
|
||||
verticalItemMargin: `${token.margin}px 0 0 0`,
|
||||
itemColor: token.colorText,
|
||||
itemSelectedColor: token.colorPrimary,
|
||||
itemHoverColor: token.colorPrimaryHover,
|
||||
itemActiveColor: token.colorPrimaryActive,
|
||||
cardGutter: token.marginXXS / 2,
|
||||
};
|
||||
},
|
||||
prepareComponentToken,
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user