From 304a98cf4994954d7e7b7a08117d6423e52afcdf Mon Sep 17 00:00:00 2001 From: nishu Date: Tue, 29 Apr 2025 17:14:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20QIANXING1-787=20collapse=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20css=20var?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/collapse/Collapse.tsx | 6 +- components/collapse/style/index.tsx | 219 ++++++++++++++++++++-------- 2 files changed, 160 insertions(+), 65 deletions(-) diff --git a/components/collapse/Collapse.tsx b/components/collapse/Collapse.tsx index be6377ee6b..f2d5828127 100644 --- a/components/collapse/Collapse.tsx +++ b/components/collapse/Collapse.tsx @@ -19,6 +19,7 @@ import collapseMotion from '../_util/collapseMotion'; import type { CustomSlotsType } from '../_util/type'; // CSSINJS +import useCSSVarCls from '../config-provider/hooks/useCssVarCls'; import useStyle from './style'; type Key = number | string; @@ -63,7 +64,8 @@ export default defineComponent({ const { prefixCls, direction, rootPrefixCls } = useConfigInject('collapse', props); // style - const [wrapSSR, hashId] = useStyle(prefixCls); + const rootCls = useCSSVarCls(prefixCls); + const [wrapSSR, hashId, cssVarCls] = useStyle(prefixCls, rootCls); const iconPosition = computed(() => { const { expandIconPosition } = props; @@ -186,6 +188,8 @@ export default defineComponent({ [`${prefixCls.value}-ghost`]: !!ghost, [attrs.class as string]: !!attrs.class, }, + cssVarCls.value, + rootCls.value, hashId.value, ); return wrapSSR( diff --git a/components/collapse/style/index.tsx b/components/collapse/style/index.tsx index 3d9b433026..08000c06a4 100644 --- a/components/collapse/style/index.tsx +++ b/components/collapse/style/index.tsx @@ -1,26 +1,63 @@ -import { genCollapseMotion } from '../../style/motion'; -import type { FullToken, GenerateStyle } from '../../theme/internal'; -import { genComponentStyleHook, mergeToken } from '../../theme/internal'; -import { resetComponent, resetIcon } from '../../style'; +import type { CSSProperties } from 'vue'; +import { unit } from '../../_util/cssinjs'; -export interface ComponentToken {} +import { genFocusStyle, resetComponent, resetIcon } from '../../style'; +import { genCollapseMotion } from '../../style/motion'; +import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal'; +import { genStyleHooks, mergeToken } from '../../theme/internal'; + +/** Component only token. Which will handle additional calculation of alias token */ +export interface ComponentToken { + // Component token here + /** + * @desc 折叠面板头部内边距 + * @descEN Padding of header + */ + headerPadding: CSSProperties['padding']; + /** + * @desc 折叠面板头部背景 + * @descEN Background of header + */ + headerBg: string; + /** + * @desc 折叠面板内容内边距 + * @descEN Padding of content + */ + contentPadding: CSSProperties['padding']; + /** + * @desc 折叠面板内容背景 + * @descEN Background of content + */ + contentBg: string; +} type CollapseToken = FullToken<'Collapse'> & { - collapseContentBg: string; - collapseHeaderBg: string; - collapseHeaderPadding: string; + /** + * @desc 小号折叠面板头部内边距 + * @descEN Padding of small header + */ + collapseHeaderPaddingSM: string; + /** + * @desc 大号折叠面板头部内边距 + * @descEN Padding of large header + */ + collapseHeaderPaddingLG: string; + /** + * @desc 折叠面板边框圆角 + * @descEN Border radius of collapse panel + */ collapsePanelBorderRadius: number; - collapseContentPaddingHorizontal: number; }; export const genBaseStyle: GenerateStyle = token => { const { componentCls, - collapseContentBg, + contentBg, padding, - collapseContentPaddingHorizontal, - collapseHeaderBg, - collapseHeaderPadding, + headerBg, + headerPadding, + collapseHeaderPaddingSM, + collapseHeaderPaddingLG, collapsePanelBorderRadius, lineWidth, @@ -29,35 +66,52 @@ export const genBaseStyle: GenerateStyle = token => { colorText, colorTextHeading, colorTextDisabled, - fontSize, + fontSizeLG, lineHeight, + lineHeightLG, marginSM, paddingSM, + paddingLG, + paddingXS, motionDurationSlow, fontSizeIcon, + contentPadding, + fontHeight, + fontHeightLG, } = token; - const borderBase = `${lineWidth}px ${lineType} ${colorBorder}`; + const borderBase = `${unit(lineWidth)} ${lineType} ${colorBorder}`; return { [componentCls]: { ...resetComponent(token), - backgroundColor: collapseHeaderBg, + backgroundColor: headerBg, border: borderBase, - borderBottom: 0, - borderRadius: `${collapsePanelBorderRadius}px`, + borderRadius: collapsePanelBorderRadius, - [`&-rtl`]: { + '&-rtl': { direction: 'rtl', }, [`& > ${componentCls}-item`]: { borderBottom: borderBase, - [`&:last-child`]: { + '&:first-child': { + [` + &, + & > ${componentCls}-header`]: { + borderRadius: `${unit(collapsePanelBorderRadius)} ${unit( + collapsePanelBorderRadius, + )} 0 0`, + }, + }, + + '&:last-child': { [` &, & > ${componentCls}-header`]: { - borderRadius: `0 0 ${collapsePanelBorderRadius}px ${collapsePanelBorderRadius}px`, + borderRadius: `0 0 ${unit(collapsePanelBorderRadius)} ${unit( + collapsePanelBorderRadius, + )}`, }, }, @@ -66,23 +120,20 @@ export const genBaseStyle: GenerateStyle = token => { display: 'flex', flexWrap: 'nowrap', alignItems: 'flex-start', - padding: collapseHeaderPadding, + padding: headerPadding, color: colorTextHeading, lineHeight, cursor: 'pointer', transition: `all ${motionDurationSlow}, visibility 0s`, + ...genFocusStyle(token), [`> ${componentCls}-header-text`]: { flex: 'auto', }, - '&:focus': { - outline: 'none', - }, - // >>>>> Arrow [`${componentCls}-expand-icon`]: { - height: fontSize * lineHeight, + height: fontHeight, display: 'flex', alignItems: 'center', paddingInlineEnd: marginSM, @@ -91,7 +142,9 @@ export const genBaseStyle: GenerateStyle = token => { [`${componentCls}-arrow`]: { ...resetIcon(), fontSize: fontSizeIcon, - + // when `transform: rotate()` is applied to icon's root element + transition: `transform ${motionDurationSlow}`, + // when `transform: rotate()` is applied to icon's child element svg: { transition: `transform ${motionDurationSlow}`, }, @@ -103,50 +156,79 @@ export const genBaseStyle: GenerateStyle = token => { }, }, - [`${componentCls}-header-collapsible-only`]: { + [`${componentCls}-collapsible-header`]: { cursor: 'default', - [`${componentCls}-header-text`]: { flex: 'none', cursor: 'pointer', }, - [`${componentCls}-expand-icon`]: { - cursor: 'pointer', - }, }, - [`${componentCls}-icon-collapsible-only`]: { - cursor: 'default', + [`${componentCls}-collapsible-icon`]: { + cursor: 'unset', [`${componentCls}-expand-icon`]: { cursor: 'pointer', }, }, - - [`&${componentCls}-no-arrow`]: { - [`> ${componentCls}-header`]: { - paddingInlineStart: paddingSM, - }, - }, }, [`${componentCls}-content`]: { color: colorText, - backgroundColor: collapseContentBg, + backgroundColor: contentBg, borderTop: borderBase, [`& > ${componentCls}-content-box`]: { - padding: `${padding}px ${collapseContentPaddingHorizontal}px`, + padding: contentPadding, }, - [`&-hidden`]: { + '&-hidden': { display: 'none', }, }, + '&-small': { + [`> ${componentCls}-item`]: { + [`> ${componentCls}-header`]: { + padding: collapseHeaderPaddingSM, + paddingInlineStart: paddingXS, + + [`> ${componentCls}-expand-icon`]: { + // Arrow offset + marginInlineStart: token.calc(paddingSM).sub(paddingXS).equal(), + }, + }, + [`> ${componentCls}-content > ${componentCls}-content-box`]: { + padding: paddingSM, + }, + }, + }, + + '&-large': { + [`> ${componentCls}-item`]: { + fontSize: fontSizeLG, + lineHeight: lineHeightLG, + [`> ${componentCls}-header`]: { + padding: collapseHeaderPaddingLG, + paddingInlineStart: padding, + + [`> ${componentCls}-expand-icon`]: { + height: fontHeightLG, + // Arrow offset + marginInlineStart: token.calc(paddingLG).sub(padding).equal(), + }, + }, + [`> ${componentCls}-content > ${componentCls}-content-box`]: { + padding: paddingLG, + }, + }, + }, + [`${componentCls}-item:last-child`]: { + borderBottom: 0, + [`> ${componentCls}-content`]: { - borderRadius: `0 0 ${collapsePanelBorderRadius}px ${collapsePanelBorderRadius}px`, + borderRadius: `0 0 ${unit(collapsePanelBorderRadius)} ${unit(collapsePanelBorderRadius)}`, }, }, @@ -179,7 +261,7 @@ export const genBaseStyle: GenerateStyle = token => { const genArrowStyle: GenerateStyle = token => { const { componentCls } = token; - const fixedSelector = `> ${componentCls}-item > ${componentCls}-header ${componentCls}-arrow svg`; + const fixedSelector = `> ${componentCls}-item > ${componentCls}-header ${componentCls}-arrow`; return { [`${componentCls}-rtl`]: { @@ -193,7 +275,7 @@ const genArrowStyle: GenerateStyle = token => { const genBorderlessStyle: GenerateStyle = token => { const { componentCls, - collapseHeaderBg, + headerBg, paddingXXS, colorBorder, @@ -201,7 +283,7 @@ const genBorderlessStyle: GenerateStyle = token => { return { [`${componentCls}-borderless`]: { - backgroundColor: collapseHeaderBg, + backgroundColor: headerBg, border: 0, [`> ${componentCls}-item`]: { @@ -252,20 +334,29 @@ const genGhostStyle: GenerateStyle = token => { }; }; -export default genComponentStyleHook('Collapse', token => { - const collapseToken = mergeToken(token, { - collapseContentBg: token.colorBgContainer, - collapseHeaderBg: token.colorFillAlter, - collapseHeaderPadding: `${token.paddingSM}px ${token.padding}px`, - collapsePanelBorderRadius: token.borderRadiusLG, - collapseContentPaddingHorizontal: 16, // Fixed value - }); - - return [ - genBaseStyle(collapseToken), - genBorderlessStyle(collapseToken), - genGhostStyle(collapseToken), - genArrowStyle(collapseToken), - genCollapseMotion(collapseToken), - ]; +export const prepareComponentToken: GetDefaultToken<'Collapse'> = token => ({ + headerPadding: `${token.paddingSM}px ${token.padding}px`, + headerBg: token.colorFillAlter, + contentPadding: `${token.padding}px 16px`, // Fixed Value + contentBg: token.colorBgContainer, }); + +export default genStyleHooks( + 'Collapse', + token => { + const collapseToken = mergeToken(token, { + collapseHeaderPaddingSM: `${unit(token.paddingXS)} ${unit(token.paddingSM)}`, + collapseHeaderPaddingLG: `${unit(token.padding)} ${unit(token.paddingLG)}`, + collapsePanelBorderRadius: token.borderRadiusLG, + }); + + return [ + genBaseStyle(collapseToken), + genBorderlessStyle(collapseToken), + genGhostStyle(collapseToken), + genArrowStyle(collapseToken), + genCollapseMotion(collapseToken), + ]; + }, + prepareComponentToken, +);