refactor:collapse (#6266)

* refactor:collapse

* fix collapse props version

* docs:update & refactor: collapse type & fix collapsible
pull/6265/head^2
果冻橙 2023-02-15 15:28:52 +08:00 committed by GitHub
parent dc9987aea8
commit 2f51f2d3af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 406 additions and 271 deletions

View File

@ -17,6 +17,9 @@ import useConfigInject from '../config-provider/hooks/useConfigInject';
import type { CollapsePanelProps } from './CollapsePanel'; import type { CollapsePanelProps } from './CollapsePanel';
import collapseMotion from '../_util/collapseMotion'; import collapseMotion from '../_util/collapseMotion';
// CSSINJS
import useStyle from './style';
type Key = number | string; type Key = number | string;
function getActiveKeysArray(activeKey: Key | Key[]) { function getActiveKeysArray(activeKey: Key | Key[]) {
@ -39,7 +42,7 @@ export default defineComponent({
destroyInactivePanel: false, destroyInactivePanel: false,
bordered: true, bordered: true,
openAnimation: collapseMotion('ant-motion-collapse', false), openAnimation: collapseMotion('ant-motion-collapse', false),
expandIconPosition: 'left', expandIconPosition: 'start',
}), }),
slots: ['expandIcon'], slots: ['expandIcon'],
// emits: ['change', 'update:activeKey'], // emits: ['change', 'update:activeKey'],
@ -56,12 +59,16 @@ export default defineComponent({
{ deep: true }, { deep: true },
); );
const { prefixCls, direction } = useConfigInject('collapse', props); const { prefixCls, direction } = useConfigInject('collapse', props);
// style
const [wrapSSR, hashId] = useStyle(prefixCls);
const iconPosition = computed(() => { const iconPosition = computed(() => {
const { expandIconPosition } = props; const { expandIconPosition } = props;
if (expandIconPosition !== undefined) { if (expandIconPosition !== undefined) {
return expandIconPosition; return expandIconPosition;
} }
return direction.value === 'rtl' ? 'right' : 'left'; return direction.value === 'rtl' ? 'end' : 'start';
}); });
const renderExpandIcon = (panelProps: CollapsePanelProps) => { const renderExpandIcon = (panelProps: CollapsePanelProps) => {
@ -73,7 +80,12 @@ export default defineComponent({
); );
return ( return (
<div> <div
class={`${prefixCls.value}-expand-icon`}
onClick={() =>
['header', 'icon'].includes(props.collapsible) && onClickItem(panelProps.panelKey)
}
>
{isValidElement(Array.isArray(expandIcon) ? icon[0] : icon) {isValidElement(Array.isArray(expandIcon) ? icon[0] : icon)
? cloneElement( ? cloneElement(
icon, icon,
@ -162,15 +174,18 @@ export default defineComponent({
return () => { return () => {
const { accordion, bordered, ghost } = props; const { accordion, bordered, ghost } = props;
const collapseClassName = classNames({ const collapseClassName = classNames(
[prefixCls.value]: true, prefixCls.value,
{
[`${prefixCls.value}-borderless`]: !bordered, [`${prefixCls.value}-borderless`]: !bordered,
[`${prefixCls.value}-icon-position-${iconPosition.value}`]: true, [`${prefixCls.value}-icon-position-${iconPosition.value}`]: true,
[`${prefixCls.value}-rtl`]: direction.value === 'rtl', [`${prefixCls.value}-rtl`]: direction.value === 'rtl',
[`${prefixCls.value}-ghost`]: !!ghost, [`${prefixCls.value}-ghost`]: !!ghost,
[attrs.class as string]: !!attrs.class, [attrs.class as string]: !!attrs.class,
}); },
return ( hashId.value,
);
return wrapSSR(
<div <div
class={collapseClassName} class={collapseClassName}
{...getDataAndAriaProps(attrs)} {...getDataAndAriaProps(attrs)}
@ -178,7 +193,7 @@ export default defineComponent({
role={accordion ? 'tablist' : null} role={accordion ? 'tablist' : null}
> >
{getItems()} {getItems()}
</div> </div>,
); );
}; };
}, },

View File

@ -57,6 +57,7 @@ export default defineComponent({
const headerCls = classNames(`${prefixClsValue}-header`, { const headerCls = classNames(`${prefixClsValue}-header`, {
[headerClass]: headerClass, [headerClass]: headerClass,
[`${prefixClsValue}-header-collapsible-only`]: collapsible === 'header', [`${prefixClsValue}-header-collapsible-only`]: collapsible === 'header',
[`${prefixClsValue}-icon-collapsible-only`]: collapsible === 'icon',
}); });
const itemCls = classNames({ const itemCls = classNames({
[`${prefixClsValue}-item`]: true, [`${prefixClsValue}-item`]: true,
@ -91,20 +92,19 @@ export default defineComponent({
<div {...attrs} class={itemCls}> <div {...attrs} class={itemCls}>
<div <div
class={headerCls} class={headerCls}
onClick={() => collapsible !== 'header' && handleItemClick()} onClick={() => !['header', 'icon'].includes(collapsible) && handleItemClick()}
role={accordion ? 'tab' : 'button'} role={accordion ? 'tab' : 'button'}
tabindex={disabled ? -1 : 0} tabindex={disabled ? -1 : 0}
aria-expanded={isActive} aria-expanded={isActive}
onKeypress={handleKeyPress} onKeypress={handleKeyPress}
> >
{showArrow && icon} {showArrow && icon}
{collapsible === 'header' ? ( <span
<span onClick={handleItemClick} class={`${prefixClsValue}-header-text`}> onClick={() => collapsible === 'header' && handleItemClick()}
class={`${prefixClsValue}-header-text`}
>
{header} {header}
</span> </span>
) : (
header
)}
{extra && <div class={`${prefixClsValue}-extra`}>{extra}</div>} {extra && <div class={`${prefixClsValue}-extra`}>{extra}</div>}
</div> </div>
<Transition {...transitionProps}> <Transition {...transitionProps}>

View File

@ -1,9 +1,8 @@
import type { PropType } from 'vue';
import type { Key } from '../_util/type'; import type { Key } from '../_util/type';
import { tuple } from '../_util/type'; import { tuple, booleanType, someType, stringType, functionType } from '../_util/type';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
export type CollapsibleType = 'header' | 'disabled'; export type CollapsibleType = 'header' | 'icon' | 'disabled';
export type ActiveKeyType = Array<string | number> | string | number; export type ActiveKeyType = Array<string | number> | string | number;
@ -20,18 +19,18 @@ export interface PanelProps {
const collapseProps = () => ({ const collapseProps = () => ({
prefixCls: String, prefixCls: String,
activeKey: { type: [Array, Number, String] as PropType<ActiveKeyType> }, activeKey: someType<ActiveKeyType>([Array, Number, String]),
defaultActiveKey: { type: [Array, Number, String] as PropType<ActiveKeyType> }, defaultActiveKey: someType<ActiveKeyType>([Array, Number, String]),
accordion: { type: Boolean, default: undefined }, accordion: booleanType(),
destroyInactivePanel: { type: Boolean, default: undefined }, destroyInactivePanel: booleanType(),
bordered: { type: Boolean, default: undefined }, bordered: booleanType(),
expandIcon: Function as PropType<(panelProps: PanelProps) => any>, expandIcon: functionType<(panelProps: PanelProps) => any>(),
openAnimation: PropTypes.object, openAnimation: PropTypes.object,
expandIconPosition: PropTypes.oneOf(tuple('left', 'right')), expandIconPosition: PropTypes.oneOf(tuple('start', 'end')),
collapsible: { type: String as PropType<CollapsibleType> }, collapsible: stringType<CollapsibleType>(),
ghost: { type: Boolean, default: undefined }, ghost: booleanType(),
onChange: Function as PropType<(key: Key | Key[]) => void>, onChange: functionType<(key: Key | Key[]) => void>(),
'onUpdate:activeKey': Function as PropType<(key: Key | Key[]) => void>, 'onUpdate:activeKey': functionType<(key: Key | Key[]) => void>(),
}); });
const collapsePanelProps = () => ({ const collapsePanelProps = () => ({
@ -39,19 +38,19 @@ const collapsePanelProps = () => ({
prefixCls: String, prefixCls: String,
header: PropTypes.any, header: PropTypes.any,
headerClass: String, headerClass: String,
showArrow: { type: Boolean, default: undefined }, showArrow: booleanType(),
isActive: { type: Boolean, default: undefined }, isActive: booleanType(),
destroyInactivePanel: { type: Boolean, default: undefined }, destroyInactivePanel: booleanType(),
/** @deprecated Use `collapsible="disabled"` instead */ /** @deprecated Use `collapsible="disabled"` instead */
disabled: { type: Boolean, default: undefined }, disabled: booleanType(),
accordion: { type: Boolean, default: undefined }, accordion: booleanType(),
forceRender: { type: Boolean, default: undefined }, forceRender: booleanType(),
expandIcon: Function as PropType<(panelProps: PanelProps) => any>, expandIcon: functionType<(panelProps: PanelProps) => any>(),
extra: PropTypes.any, extra: PropTypes.any,
panelKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), panelKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
collapsible: { type: String as PropType<CollapsibleType> }, collapsible: stringType<CollapsibleType>(),
role: String, role: String,
onItemClick: { type: Function as PropType<(panelKey: Key) => void> }, onItemClick: functionType<(panelKey: Key) => void>(),
}); });
export { collapseProps, collapsePanelProps }; export { collapseProps, collapsePanelProps };

View File

@ -0,0 +1,55 @@
<docs>
---
order: 7
title:
zh-CN: 可折叠触发区域
en-US: Collapsible
---
## zh-CN
通过 `collapsible` 属性可以设置面板的可折叠触发区域
## en-US
Specify the trigger area of collapsible by `collapsible`.
</docs>
<template>
<a-space direction="vertical">
<a-collapse collapsible="header" v-model:activeKey="activeKey">
<a-collapse-panel header="This panel can only be collapsed by clicking text" key="1">
<p>{{ text }}</p>
</a-collapse-panel>
</a-collapse>
<a-collapse collapsible="icon" v-model:activeKey="activeKey">
<a-collapse-panel header="This panel can only be collapsed by clicking icon" key="1">
<p>{{ text }}</p>
</a-collapse-panel>
</a-collapse>
<a-collapse collapsible="disabled">
<a-collapse-panel header="This panel can't be collapsed" key="1">
<p>{{ text }}</p>
</a-collapse-panel>
</a-collapse>
</a-space>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const activeKey = ref(['1']);
const text = `A dog is a type of domesticated animal. Known for its loyalty and faithfulness, it can be found as a welcome guest in many households across the world.`;
return {
activeKey,
text,
};
},
});
</script>
<style>
.ant-space {
width: 100%;
}
</style>

View File

@ -17,7 +17,11 @@ Customize the background, border and margin styles and icon for each panel.
</docs> </docs>
<template> <template>
<a-collapse v-model:activeKey="activeKey" :bordered="false"> <a-collapse
v-model:activeKey="activeKey"
:bordered="false"
style="background: rgb(255, 255, 255)"
>
<template #expandIcon="{ isActive }"> <template #expandIcon="{ isActive }">
<caret-right-outlined :rotate="isActive ? 90 : 0" /> <caret-right-outlined :rotate="isActive ? 90 : 0" />
</template> </template>

View File

@ -34,8 +34,8 @@ More than one panel can be expanded at a time, the first panel is initialized to
<br /> <br />
<span>Expand Icon Position:</span> <span>Expand Icon Position:</span>
<a-select v-model:value="expandIconPosition"> <a-select v-model:value="expandIconPosition">
<a-select-option value="left">left</a-select-option> <a-select-option value="start">start</a-select-option>
<a-select-option value="right">right</a-select-option> <a-select-option value="end">end</a-select-option>
</a-select> </a-select>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -50,7 +50,7 @@ export default defineComponent({
setup() { setup() {
const text = `A dog is a type of domesticated animal.Known for its loyalty and faithfulness,it can be found as a welcome guest in many households across the world.`; const text = `A dog is a type of domesticated animal.Known for its loyalty and faithfulness,it can be found as a welcome guest in many households across the world.`;
const activeKey = ref(['1']); const activeKey = ref(['1']);
const expandIconPosition = ref<CollapseProps['expandIconPosition']>('left'); const expandIconPosition = ref<CollapseProps['expandIconPosition']>('start');
const handleClick = (event: MouseEvent) => { const handleClick = (event: MouseEvent) => {
// If you don't want click extra trigger collapse, you can prevent this: // If you don't want click extra trigger collapse, you can prevent this:

View File

@ -8,6 +8,7 @@
<Noarrow /> <Noarrow />
<Extra /> <Extra />
<Ghost /> <Ghost />
<Collapsible />
</demo-sort> </demo-sort>
</template> </template>
@ -20,6 +21,7 @@ import Mix from './mix.vue';
import Noarrow from './noarrow.vue'; import Noarrow from './noarrow.vue';
import Extra from './extra.vue'; import Extra from './extra.vue';
import Ghost from './ghost.vue'; import Ghost from './ghost.vue';
import Collapsible from './collapsible.vue';
import CN from '../index.zh-CN.md'; import CN from '../index.zh-CN.md';
import US from '../index.en-US.md'; import US from '../index.en-US.md';
@ -35,6 +37,7 @@ export default {
Noarrow, Noarrow,
Extra, Extra,
Ghost, Ghost,
Collapsible,
}, },
}; };
</script> </script>

View File

@ -2,7 +2,7 @@
category: Components category: Components
type: Data Display type: Data Display
title: Collapse title: Collapse
cover: https://gw.alipayobjects.com/zos/alicdn/IxH16B9RD/Collapse.svg cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*B7HKR5OBe8gAAAAAAAAAAAAADrJ8AQ/original
--- ---
A content area which can be collapsed and expanded. A content area which can be collapsed and expanded.
@ -19,12 +19,12 @@ A content area which can be collapsed and expanded.
| Property | Description | Type | Default | Version | | Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| accordion | If `true`, `Collapse` renders as `Accordion` | boolean | `false` | | | accordion | If `true`, `Collapse` renders as `Accordion` | boolean | `false` | |
| activeKey(v-model) | Key of the active panel | string\[]\|string | No default value. In `accordion` mode, it's the key of the first panel. | | | activeKey(v-model) | Key of the active panel | string\[] \| string <br> number\[] \| number | No default value. In `accordion` mode, it's the key of the first panel. | |
| bordered | Toggles rendering of the border around the collapse block | boolean | `true` | | | bordered | Toggles rendering of the border around the collapse block | boolean | `true` | |
| collapsible | Specify whether the panels of children be collapsible or the trigger area of collapsible | `header` \| `disabled` | - | 3.0 | | collapsible | Specify whether the panels of children be collapsible or the trigger area of collapsible | `header` \| `icon` \| `disabled` | - | 4.0 |
| destroyInactivePanel | Destroy Inactive Panel | boolean | `false` | | | destroyInactivePanel | Destroy Inactive Panel | boolean | `false` | |
| expandIcon | allow to customize collapse icon | Function(props):VNode \| v-slot:expandIcon="props" | | | | expandIcon | allow to customize collapse icon | Function(props):VNode \| v-slot:expandIcon="props" | | |
| expandIconPosition | Set expand icon position: `left`, `right` | `left` | - | 1.5.0 | | expandIconPosition | Set expand icon position | `start` \| `end` | - | 4.0 |
| ghost | Make the collapse borderless and its background transparent | boolean | false | 3.0 | | ghost | Make the collapse borderless and its background transparent | boolean | false | 3.0 |
### events ### events

View File

@ -3,7 +3,7 @@ category: Components
type: 数据展示 type: 数据展示
title: Collapse title: Collapse
subtitle: 折叠面板 subtitle: 折叠面板
cover: https://gw.alipayobjects.com/zos/alicdn/IxH16B9RD/Collapse.svg cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*B7HKR5OBe8gAAAAAAAAAAAAADrJ8AQ/original
--- ---
可以折叠/展开的内容区域。 可以折叠/展开的内容区域。
@ -20,12 +20,12 @@ cover: https://gw.alipayobjects.com/zos/alicdn/IxH16B9RD/Collapse.svg
| 参数 | 说明 | 类型 | 默认值 | 版本 | | 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| accordion | 手风琴模式 | boolean | `false` | | | accordion | 手风琴模式 | boolean | `false` | |
| activeKey(v-model) | 当前激活 tab 面板的 key | string\[]\|string | 默认无accordion 模式下默认第一个元素 | | | activeKey(v-model) | 当前激活 tab 面板的 key | string\[] \| string <br> number\[] \| number | 默认无accordion 模式下默认第一个元素 | |
| bordered | 带边框风格的折叠面板 | boolean | `true` | | | bordered | 带边框风格的折叠面板 | boolean | `true` | |
| collapsible | 所有子面板是否可折叠或指定可折叠触发区域 | `header` \| `disabled` | - | 3.0 | | collapsible | 所有子面板是否可折叠或指定可折叠触发区域 | `header` \| `icon` \| `disabled` | - | 4.0 |
| destroyInactivePanel | 销毁折叠隐藏的面板 | boolean | `false` | | | destroyInactivePanel | 销毁折叠隐藏的面板 | boolean | `false` | |
| expandIcon | 自定义切换图标 | Function(props):VNode \| slot="expandIcon" slot-scope="props"\|#expandIcon="props" | | | | expandIcon | 自定义切换图标 | Function(props):VNode \| slot="expandIcon" slot-scope="props"\|#expandIcon="props" | | |
| expandIconPosition | 设置图标位置 `left`, `right` | `left` | - | 1.5.0 | | expandIconPosition | 设置图标位置 | `start` \| `end` | - | 4.0 |
| ghost | 使折叠面板透明且无边框 | boolean | false | 3.0 | | ghost | 使折叠面板透明且无边框 | boolean | false | 3.0 |
### 事件 ### 事件

View File

@ -1,162 +0,0 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@collapse-prefix-cls: ~'@{ant-prefix}-collapse';
.@{collapse-prefix-cls} {
.reset-component();
background-color: @collapse-header-bg;
border: @border-width-base @border-style-base @border-color-base;
border-bottom: 0;
border-radius: @collapse-panel-border-radius;
& > &-item {
border-bottom: @border-width-base @border-style-base @border-color-base;
&:last-child {
&,
& > .@{collapse-prefix-cls}-header {
border-radius: 0 0 @collapse-panel-border-radius @collapse-panel-border-radius;
}
}
> .@{collapse-prefix-cls}-header {
position: relative; // Compatible with old version of antd, should remove in next version
display: flex;
flex-wrap: nowrap;
align-items: flex-start;
padding: @collapse-header-padding;
color: @heading-color;
line-height: @line-height-base;
cursor: pointer;
transition: all 0.3s, visibility 0s;
.@{collapse-prefix-cls}-arrow {
display: inline-block;
margin-right: @margin-sm;
font-size: @font-size-sm;
vertical-align: -1px;
& svg {
transition: transform 0.24s;
}
}
.@{collapse-prefix-cls}-extra {
margin-left: auto;
}
&:focus {
outline: none;
}
}
.@{collapse-prefix-cls}-header-collapsible-only {
cursor: default;
.@{collapse-prefix-cls}-header-text {
cursor: pointer;
}
}
&.@{collapse-prefix-cls}-no-arrow {
> .@{collapse-prefix-cls}-header {
padding-left: @padding-sm;
}
}
}
// Expand Icon right
&-icon-position-right {
& > .@{collapse-prefix-cls}-item {
> .@{collapse-prefix-cls}-header {
position: relative;
padding: @collapse-header-padding;
padding-right: @collapse-header-padding-extra;
.@{collapse-prefix-cls}-arrow {
position: absolute;
top: 50%;
right: @padding-md;
left: auto;
margin: 0;
transform: translateY(-50%);
}
}
}
}
&-content {
color: @text-color;
background-color: @collapse-content-bg;
border-top: @border-width-base @border-style-base @border-color-base;
& > &-box {
padding: @collapse-content-padding;
}
&-hidden {
display: none;
}
}
&-item:last-child {
> .@{collapse-prefix-cls}-content {
border-radius: 0 0 @collapse-panel-border-radius @collapse-panel-border-radius;
}
}
&-borderless {
background-color: @collapse-header-bg;
border: 0;
}
&-borderless > &-item {
border-bottom: 1px solid @border-color-base;
}
&-borderless > &-item:last-child,
&-borderless > &-item:last-child &-header {
border-radius: 0;
}
// hide the last border-bottom in borderless mode
&-borderless > &-item:last-child {
border-bottom: 0;
}
&-borderless > &-item > &-content {
background-color: transparent;
border-top: 0;
}
&-borderless > &-item > &-content > &-content-box {
padding-top: 4px;
}
&-ghost {
background-color: transparent;
border: 0;
> .@{collapse-prefix-cls}-item {
border-bottom: 0;
> .@{collapse-prefix-cls}-content {
background-color: transparent;
border-top: 0;
> .@{collapse-prefix-cls}-content-box {
padding-top: 12px;
padding-bottom: 12px;
}
}
}
}
& &-item-disabled > &-header {
&,
& > .arrow {
color: @disabled-color;
cursor: not-allowed;
}
}
}
@import './rtl';

View File

@ -1,2 +1,271 @@
import '../../style/index.less'; import { genCollapseMotion } from '../../_style/motion';
import './index.less'; import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { resetComponent, resetIcon } from '../../_style';
export interface ComponentToken {}
type CollapseToken = FullToken<'Collapse'> & {
collapseContentBg: string;
collapseHeaderBg: string;
collapseHeaderPadding: string;
collapsePanelBorderRadius: number;
collapseContentPaddingHorizontal: number;
};
export const genBaseStyle: GenerateStyle<CollapseToken> = token => {
const {
componentCls,
collapseContentBg,
padding,
collapseContentPaddingHorizontal,
collapseHeaderBg,
collapseHeaderPadding,
collapsePanelBorderRadius,
lineWidth,
lineType,
colorBorder,
colorText,
colorTextHeading,
colorTextDisabled,
fontSize,
lineHeight,
marginSM,
paddingSM,
motionDurationSlow,
fontSizeIcon,
} = token;
const borderBase = `${lineWidth}px ${lineType} ${colorBorder}`;
return {
[componentCls]: {
...resetComponent(token),
backgroundColor: collapseHeaderBg,
border: borderBase,
borderBottom: 0,
borderRadius: `${collapsePanelBorderRadius}px`,
[`&-rtl`]: {
direction: 'rtl',
},
[`& > ${componentCls}-item`]: {
borderBottom: borderBase,
[`&:last-child`]: {
[`
&,
& > ${componentCls}-header`]: {
borderRadius: `0 0 ${collapsePanelBorderRadius}px ${collapsePanelBorderRadius}px`,
},
},
[`> ${componentCls}-header`]: {
position: 'relative', // Compatible with old version of antd, should remove in next version
display: 'flex',
flexWrap: 'nowrap',
alignItems: 'flex-start',
padding: collapseHeaderPadding,
color: colorTextHeading,
lineHeight,
cursor: 'pointer',
transition: `all ${motionDurationSlow}, visibility 0s`,
[`> ${componentCls}-header-text`]: {
flex: 'auto',
},
'&:focus': {
outline: 'none',
},
// >>>>> Arrow
[`${componentCls}-expand-icon`]: {
height: fontSize * lineHeight,
display: 'flex',
alignItems: 'center',
paddingInlineEnd: marginSM,
},
[`${componentCls}-arrow`]: {
...resetIcon(),
fontSize: fontSizeIcon,
svg: {
transition: `transform ${motionDurationSlow}`,
},
},
// >>>>> Text
[`${componentCls}-header-text`]: {
marginInlineEnd: 'auto',
},
},
[`${componentCls}-header-collapsible-only`]: {
cursor: 'default',
[`${componentCls}-header-text`]: {
flex: 'none',
cursor: 'pointer',
},
[`${componentCls}-expand-icon`]: {
cursor: 'pointer',
},
},
[`${componentCls}-icon-collapsible-only`]: {
cursor: 'default',
[`${componentCls}-expand-icon`]: {
cursor: 'pointer',
},
},
[`&${componentCls}-no-arrow`]: {
[`> ${componentCls}-header`]: {
paddingInlineStart: paddingSM,
},
},
},
[`${componentCls}-content`]: {
color: colorText,
backgroundColor: collapseContentBg,
borderTop: borderBase,
[`& > ${componentCls}-content-box`]: {
padding: `${padding}px ${collapseContentPaddingHorizontal}px`,
},
[`&-hidden`]: {
display: 'none',
},
},
[`${componentCls}-item:last-child`]: {
[`> ${componentCls}-content`]: {
borderRadius: `0 0 ${collapsePanelBorderRadius}px ${collapsePanelBorderRadius}px`,
},
},
[`& ${componentCls}-item-disabled > ${componentCls}-header`]: {
[`
&,
& > .arrow
`]: {
color: colorTextDisabled,
cursor: 'not-allowed',
},
},
// ========================== Icon Position ==========================
[`&${componentCls}-icon-position-end`]: {
[`& > ${componentCls}-item`]: {
[`> ${componentCls}-header`]: {
[`${componentCls}-expand-icon`]: {
order: 1,
paddingInlineEnd: 0,
paddingInlineStart: marginSM,
},
},
},
},
},
};
};
const genArrowStyle: GenerateStyle<CollapseToken> = token => {
const { componentCls } = token;
const fixedSelector = `> ${componentCls}-item > ${componentCls}-header ${componentCls}-arrow svg`;
return {
[`${componentCls}-rtl`]: {
[fixedSelector]: {
transform: `rotate(180deg)`,
},
},
};
};
const genBorderlessStyle: GenerateStyle<CollapseToken> = token => {
const {
componentCls,
collapseHeaderBg,
paddingXXS,
colorBorder,
} = token;
return {
[`${componentCls}-borderless`]: {
backgroundColor: collapseHeaderBg,
border: 0,
[`> ${componentCls}-item`]: {
borderBottom: `1px solid ${colorBorder}`,
},
[`
> ${componentCls}-item:last-child,
> ${componentCls}-item:last-child ${componentCls}-header
`]: {
borderRadius: 0,
},
[`> ${componentCls}-item:last-child`]: {
borderBottom: 0,
},
[`> ${componentCls}-item > ${componentCls}-content`]: {
backgroundColor: 'transparent',
borderTop: 0,
},
[`> ${componentCls}-item > ${componentCls}-content > ${componentCls}-content-box`]: {
paddingTop: paddingXXS,
},
},
};
};
const genGhostStyle: GenerateStyle<CollapseToken> = token => {
const { componentCls, paddingSM } = token;
return {
[`${componentCls}-ghost`]: {
backgroundColor: 'transparent',
border: 0,
[`> ${componentCls}-item`]: {
borderBottom: 0,
[`> ${componentCls}-content`]: {
backgroundColor: 'transparent',
border: 0,
[`> ${componentCls}-content-box`]: {
paddingBlock: paddingSM,
},
},
},
},
};
};
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),
];
});

View File

@ -1,48 +0,0 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@collapse-prefix-cls: ~'@{ant-prefix}-collapse';
.@{collapse-prefix-cls} {
&-rtl {
direction: rtl;
}
& > &-item {
> .@{collapse-prefix-cls}-header {
.@{collapse-prefix-cls}-rtl & {
padding: @collapse-header-padding;
padding-right: @collapse-header-padding-extra;
}
.@{collapse-prefix-cls}-arrow {
.@{collapse-prefix-cls}-rtl& {
margin-right: 0;
margin-left: @margin-sm;
}
& svg {
.@{collapse-prefix-cls}-rtl& {
transform: rotate(180deg);
}
}
}
.@{collapse-prefix-cls}-extra {
.@{collapse-prefix-cls}-rtl& {
margin-right: auto;
margin-left: 0;
}
}
}
&.@{collapse-prefix-cls}-no-arrow {
> .@{collapse-prefix-cls}-header {
.@{collapse-prefix-cls}-rtl& {
padding-right: @padding-sm;
padding-left: 0;
}
}
}
}
}

View File

@ -18,7 +18,7 @@ import './tabs/style';
// import './dropdown/style'; // import './dropdown/style';
// import './divider/style'; // import './divider/style';
// import './card/style'; // import './card/style';
import './collapse/style'; // import './collapse/style';
// import './carousel/style'; // import './carousel/style';
// import './notification/style'; // import './notification/style';
// import './message/style'; // import './message/style';

View File

@ -9,7 +9,7 @@ import type { ComponentToken as CardComponentToken } from '../../card/style';
import type { ComponentToken as CarouselComponentToken } from '../../carousel/style'; import type { ComponentToken as CarouselComponentToken } from '../../carousel/style';
// import type { ComponentToken as CascaderComponentToken } from '../../cascader/style'; // import type { ComponentToken as CascaderComponentToken } from '../../cascader/style';
import type { ComponentToken as CheckboxComponentToken } from '../../checkbox/style'; import type { ComponentToken as CheckboxComponentToken } from '../../checkbox/style';
// import type { ComponentToken as CollapseComponentToken } from '../../collapse/style'; import type { ComponentToken as CollapseComponentToken } from '../../collapse/style';
import type { ComponentToken as DatePickerComponentToken } from '../../date-picker/style'; import type { ComponentToken as DatePickerComponentToken } from '../../date-picker/style';
import type { ComponentToken as DividerComponentToken } from '../../divider/style'; import type { ComponentToken as DividerComponentToken } from '../../divider/style';
import type { ComponentToken as DropdownComponentToken } from '../../dropdown/style'; import type { ComponentToken as DropdownComponentToken } from '../../dropdown/style';
@ -63,7 +63,7 @@ export interface ComponentTokenMap {
Carousel?: CarouselComponentToken; Carousel?: CarouselComponentToken;
// Cascader?: CascaderComponentToken; // Cascader?: CascaderComponentToken;
Checkbox?: CheckboxComponentToken; Checkbox?: CheckboxComponentToken;
// Collapse?: CollapseComponentToken; Collapse?: CollapseComponentToken;
Comment?: {}; Comment?: {};
DatePicker?: DatePickerComponentToken; DatePicker?: DatePickerComponentToken;
Descriptions?: {}; Descriptions?: {};