diff --git a/components/tabs/index.tsx b/components/tabs/index.tsx index 1bf5727684..ce087131fe 100755 --- a/components/tabs/index.tsx +++ b/components/tabs/index.tsx @@ -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 & { TabPane: typeof TabPane } = (props) => { const { prefixCls: customizePrefixCls, moreIcon = } = 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 & { TabPane: typeof TabPane } = (props) => { const mergedStyle: React.CSSProperties = { ...tabs?.style, ...style }; - return wrapSSR( + return wrapCSSVar( & { TabPane: typeof TabPane } = (props) => { className, rootClassName, hashId, + rootCls, )} - popupClassName={classNames(popupClassName, hashId)} + popupClassName={classNames(popupClassName, hashId, rootCls)} style={mergedStyle} editable={editable} moreIcon={moreIcon} diff --git a/components/tabs/style/cssVar.ts b/components/tabs/style/cssVar.ts new file mode 100644 index 0000000000..73628c94fa --- /dev/null +++ b/components/tabs/style/cssVar.ts @@ -0,0 +1,4 @@ +import { genCSSVarRegister } from '../../theme/internal'; +import { prepareComponentToken } from '.'; + +export default genCSSVarRegister('Tabs', prepareComponentToken); diff --git a/components/tabs/style/index.ts b/components/tabs/style/index.ts index bcfd002fd0..4b5131e7e4 100644 --- a/components/tabs/style/index.ts +++ b/components/tabs/style/index.ts @@ -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 = (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 = (token: TabsToken): CSSObject => [`${componentCls}-tab + ${componentCls}-tab`]: { marginLeft: { _skip_check_: true, - value: `${cardGutter}px`, + value: unit(cardGutter), }, }, }, @@ -183,7 +184,7 @@ const genCardStyle: GenerateStyle = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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(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, );