Skip to content

Commit

Permalink
refactor(Collapse): 重构折叠面板组件 (#834,#826)
Browse files Browse the repository at this point in the history
  • Loading branch information
nullptr-z authored May 19, 2022
1 parent 0c5c021 commit de91267
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 67 deletions.
3 changes: 2 additions & 1 deletion packages/react-collapse/src/Collapse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function InternalCollapse(props: CollapseProps, ref: React.ForwardedRef<HTMLDivE
}
}, [activeKey, propsActiveKey]);
return (
<CollapseWarp className={cls} {...resetProps} ref={ref}>
<CollapseWarp className={cls} {...resetProps} ref={ref} bordered={bordered}>
{React.Children.map(children, (child: any, index) => {
// 如果没有密钥提供,请使用面板顺序作为默认密钥
const key = child.key || String(index);
Expand All @@ -80,6 +80,7 @@ function InternalCollapse(props: CollapseProps, ref: React.ForwardedRef<HTMLDivE
prefixCls,
isActive,
disabled,
bordered,
showArrow,
onItemClick: disabled ? () => {} : () => onItemClick(key),
...child.props,
Expand Down
14 changes: 8 additions & 6 deletions packages/react-collapse/src/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { CSSTransition } from 'react-transition-group';
import { TransitionStatus } from 'react-transition-group/Transition';
import { IProps, HTMLDivProps } from '@uiw/utils';
import Icon, { IconProps } from '@uiw/react-icon';
import { CollapseHeader, CollapseHeaderExtra, CollapseHeaderTitle, CollapseItem } from './style';

export interface CollapsePanelProps extends IProps, HTMLDivProps {
disabled?: boolean;
Expand Down Expand Up @@ -55,13 +56,14 @@ export default function Panel(props: CollapsePanelProps) {
instance.style.height = `${instance.scrollHeight}px`;
}
}

return (
<div className={cls} {...resetProps}>
<div className={`${prefixCls}-header`} onClick={onItemClick}>
<CollapseItem {...resetProps} prefixCls={prefixCls} className={cls}>
<CollapseHeader className={`${prefixCls}-header`} isActive={isActive} disabled={disabled} onClick={onItemClick}>
{showArrow && iconRender}
<span className={`${prefixCls}-title`}>{header}</span>
{extra && <div className={`${prefixCls}-extra`}>{extra}</div>}
</div>
<CollapseHeaderTitle className={`${prefixCls}-title`}>{header}</CollapseHeaderTitle>
{extra && <CollapseHeaderExtra className={`${prefixCls}-extra`}>{extra}</CollapseHeaderExtra>}
</CollapseHeader>
<CSSTransition in={isActive} unmountOnExit={false} timeout={300} classNames={`${prefixCls}-panel`}>
{(status: TransitionStatus) =>
React.cloneElement(<div>{children}</div>, {
Expand All @@ -71,6 +73,6 @@ export default function Panel(props: CollapsePanelProps) {
})
}
</CSSTransition>
</div>
</CollapseItem>
);
}
171 changes: 111 additions & 60 deletions packages/react-collapse/src/style/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
import styled from 'styled-components';
import { getThemeVariantValue } from '@uiw/utils';
import styled, { css } from 'styled-components';
import { getThemeVariantValue, ThemeVariantValueOptions } from '@uiw/utils';

interface CollapseProps {
interface CollapseWarpProps extends ThemeVariantValueOptions {
bordered?: boolean;
defaultTheme?: Record<string, string | number>;
}

const CollapseWarp = styled.div<CollapseProps>`
interface CollapseItemWarpProps extends ThemeVariantValueOptions {
prefixCls?: string;
bordered?: boolean;
defaultTheme?: Record<string, string | number>;
}

interface CollapseHeaderProps extends ThemeVariantValueOptions {
isActive?: boolean;
disabled?: boolean;
defaultTheme?: Record<string, string | number>;
}

interface CollapseHeaderTitleProps extends ThemeVariantValueOptions {
defaultTheme?: Record<string, string | number>;
}

const CollapseWarp = styled.div<CollapseWarpProps>`
border-radius: 4px;
line-height: 16px;
font-size: ${(props) => getThemeVariantValue(props, 'fontSizeDefault')};
Expand All @@ -16,37 +33,27 @@ const CollapseWarp = styled.div<CollapseProps>`
& > .w-collapse-item:last-child {
border-radius: 0 0 5px 5px;
}
.w-collapse-title {
flex: 1;
}
.w-collapse-header {
padding: 8px 10px;
color: ${(props) => getThemeVariantValue(props, 'colorCollapseHeaderBase')};
background-color: ${(props) => getThemeVariantValue(props, 'backgroundColorCollapseHeaderBase')};
cursor: pointer;
position: relative;
transition: all 0.3s;
z-index: 1;
display: flex;
& > .w-icon:first-child {
margin-top: -2px;
margin-right: 5px;
transform: scale(0.85) rotate(-90deg);
transition: transform 0.24s;
svg {
display: block;
}
}
& > * {
vertical-align: middle;
display: inline-block;
}
& > .w-collapse-item:last-child .w-collapse-panel:after {
border-bottom: 0 solid ${(props) => getThemeVariantValue(props, 'borderColorCollapseBase')};
}
.w-collapse-active .w-collapse-header {
& > .w-icon:first-child {
transform: scale(0.85) rotate(0);
}
& > .w-collapse-item:not(.w-collapse-active):last-child .w-collapse-panel:before {
border-top: 0 solid ${(props) => getThemeVariantValue(props, 'borderColorCollapseBase')};
}
${(props) =>
props.bordered &&
css`
border: 0;
background-color: transparent;
&:after,
&:before {
border: 0;
}
`}
`;

export const CollapseItem = styled.div<CollapseItemWarpProps>`
.w-collapse-panel {
overflow: hidden;
color: ${(props) => getThemeVariantValue(props, 'colorCollapsePanelBase')};
Expand All @@ -57,6 +64,7 @@ const CollapseWarp = styled.div<CollapseProps>`
height: 10px;
display: block;
overflow: hidden;
border: 0;
}
&:before {
border-top: 1px solid ${(props) => getThemeVariantValue(props, 'borderColorCollapseBase')};
Expand All @@ -70,47 +78,90 @@ const CollapseWarp = styled.div<CollapseProps>`
z-index: 1;
position: relative;
}
}
& > .w-collapse-item:last-child .w-collapse-panel:after {
border-bottom: 0 solid ${(props) => getThemeVariantValue(props, 'borderColorCollapseBase')};
}
& > .w-collapse-item:not(.w-collapse-active):last-child .w-collapse-panel:before {
border-top: 0 solid ${(props) => getThemeVariantValue(props, 'borderColorCollapseBase')};
}
.w-collapse-disabled .w-collapse-header {
cursor: not-allowed;
color: ${(props) => getThemeVariantValue(props, 'colorCollapseHeaderDisabled')};
background-color: ${(props) => getThemeVariantValue(props, 'backgroundColorCollapseHeaderDisabled')};
}
&.w-noborder .w-collapse-header {
background-color: transparent;
}
&.w-noborder {
border: 0;
}
&.w-noborder .w-collapse-item .w-collapse-panel {
&:after,
&:before {
${(props) =>
props.bordered &&
css`
border: 0;
&:after,
&:before {
border: 0;
}
`}
&:last-child {
border: 0;
}
}
&.w-noborder .w-collapse-item:last-child {
border: 0;
`;

export const CollapseHeader = styled.div<CollapseHeaderProps>`
padding: 8px 10px;
color: ${(props) => getThemeVariantValue(props, 'colorCollapseHeaderBase')};
background-color: ${(props) => getThemeVariantValue(props, 'backgroundColorCollapseHeaderBase')};
cursor: pointer;
position: relative;
transition: all 0.3s;
z-index: 1;
display: flex;
& > .w-icon:first-child {
margin-top: -2px;
margin-right: 5px;
transform: scale(0.85) rotate(-90deg);
transition: transform 0.24s;
svg {
display: block;
}
}
& > * {
vertical-align: middle;
display: inline-block;
}
${(props) =>
props.isActive &&
css`
& > .w-icon:first-child {
transform: scale(0.85) rotate(0);
}
`}
${(props) =>
props.disabled &&
css`
cursor: not-allowed;
color: ${(props) => getThemeVariantValue(props, 'colorCollapseHeaderDisabled')};
background-color: ${(props) => getThemeVariantValue(props, 'backgroundColorCollapseHeaderDisabled')};
`}
`;

export const CollapseHeaderTitle = styled.span<CollapseHeaderTitleProps>`
flex: 1;
`;

export const CollapseHeaderExtra = styled.div``;

CollapseWarp.defaultProps = {
defaultTheme: {
fontSizeDefault: '14px',
backgroundColorBase: '#fff',
borderColorCollapseBase: '#d9d9d9',
// Header
backgroundColorCollapseHeaderBase: '#fafafa',
},
};

CollapseHeader.defaultProps = {
defaultTheme: {
colorCollapseHeaderBase: 'rgba(0, 0, 0, 0.85)',
backgroundColorCollapseHeaderDisabled: '#f7f7f7',
backgroundColorCollapseHeaderBase: '#fafafa',
colorCollapseHeaderDisabled: 'rgba(0, 0, 0, 0.25)',
// Panel
backgroundColorCollapseHeaderDisabled: '#f7f7f7',
},
};

CollapseItem.defaultProps = {
defaultTheme: {
colorCollapsePanelBase: 'rgba(0, 0, 0, 0.65)',
borderColorCollapseBase: '#d9d9d9',
},
};

export default CollapseWarp;

0 comments on commit de91267

Please sign in to comment.