Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion components/collapse/Collapse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand Down
219 changes: 155 additions & 64 deletions components/collapse/style/index.tsx
Original file line number Diff line number Diff line change
@@ -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<CollapseToken> = token => {
const {
componentCls,
collapseContentBg,
contentBg,
padding,
collapseContentPaddingHorizontal,
collapseHeaderBg,
collapseHeaderPadding,
headerBg,
headerPadding,
collapseHeaderPaddingSM,
collapseHeaderPaddingLG,
collapsePanelBorderRadius,

lineWidth,
Expand All @@ -29,35 +66,52 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = 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,
)}`,
},
},

Expand All @@ -66,23 +120,20 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = 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,
Expand All @@ -91,7 +142,9 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = 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}`,
},
Expand All @@ -103,50 +156,79 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = 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)}`,
},
},

Expand Down Expand Up @@ -179,7 +261,7 @@ export const genBaseStyle: GenerateStyle<CollapseToken> = token => {
const genArrowStyle: GenerateStyle<CollapseToken> = token => {
const { componentCls } = token;

const fixedSelector = `> ${componentCls}-item > ${componentCls}-header ${componentCls}-arrow svg`;
const fixedSelector = `> ${componentCls}-item > ${componentCls}-header ${componentCls}-arrow`;

return {
[`${componentCls}-rtl`]: {
Expand All @@ -193,15 +275,15 @@ const genArrowStyle: GenerateStyle<CollapseToken> = token => {
const genBorderlessStyle: GenerateStyle<CollapseToken> = token => {
const {
componentCls,
collapseHeaderBg,
headerBg,
paddingXXS,

colorBorder,
} = token;

return {
[`${componentCls}-borderless`]: {
backgroundColor: collapseHeaderBg,
backgroundColor: headerBg,
border: 0,

[`> ${componentCls}-item`]: {
Expand Down Expand Up @@ -252,20 +334,29 @@ const genGhostStyle: GenerateStyle<CollapseToken> = token => {
};
};

export default genComponentStyleHook('Collapse', token => {
const collapseToken = mergeToken<CollapseToken>(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<CollapseToken>(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,
);