style: transition wrapper height
This commit is contained in:
@@ -23,6 +23,18 @@
|
||||
|
||||
.content-wrapper {
|
||||
overflow: hidden;
|
||||
transition: height 300ms ease-in-out;
|
||||
transition: all 300ms ease-in-out;
|
||||
.content {
|
||||
height: max-content;
|
||||
background-color: var(--color-white-1);
|
||||
border-radius: var(--border-radius-base);
|
||||
}
|
||||
}
|
||||
.ant-input {
|
||||
/* 只隐藏垂直滚动条轨道 */
|
||||
&::-webkit-scrollbar-track {
|
||||
width: 0px !important;
|
||||
color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import classNames from 'classnames';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
forwardRef,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
useState
|
||||
} from 'react';
|
||||
import './index.less';
|
||||
|
||||
interface TransitionWrapProps {
|
||||
@@ -7,50 +13,67 @@ interface TransitionWrapProps {
|
||||
header?: React.ReactNode;
|
||||
variant?: 'bordered' | 'filled';
|
||||
children: React.ReactNode;
|
||||
ref?: any;
|
||||
}
|
||||
const TransitionWrapper: React.FC<TransitionWrapProps> = (props) => {
|
||||
const { minHeight = 50, header, variant = 'bordered', children } = props;
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const [height, setHeight] = useState(0);
|
||||
const contentRef = useRef(null);
|
||||
const TransitionWrapper: React.FC<TransitionWrapProps> = forwardRef(
|
||||
(props, ref) => {
|
||||
const { minHeight = 50, header, variant = 'bordered', children } = props;
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const [height, setHeight] = useState(0);
|
||||
const contentRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
setHeight(contentRef?.current?.scrollHeight);
|
||||
} else {
|
||||
setHeight(0);
|
||||
}
|
||||
}, [isOpen]);
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
setHeight(contentRef?.current?.scrollHeight || 0);
|
||||
} else {
|
||||
setHeight(0);
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
const toggleOpen = () => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
const toggleOpen = () => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames('transition-wrapper', {
|
||||
bordered: variant === 'bordered',
|
||||
filled: variant === 'filled'
|
||||
})}
|
||||
>
|
||||
const setHeightByContent = () => {
|
||||
setHeight(contentRef?.current?.scrollHeight || 0);
|
||||
};
|
||||
|
||||
useImperativeHandle(ref, () => {
|
||||
return {
|
||||
setHeightByContent
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={toggleOpen}
|
||||
className="header"
|
||||
style={{
|
||||
height: minHeight
|
||||
}}
|
||||
className={classNames('transition-wrapper', {
|
||||
bordered: variant === 'bordered',
|
||||
filled: variant === 'filled'
|
||||
})}
|
||||
>
|
||||
{header}
|
||||
<div
|
||||
onClick={toggleOpen}
|
||||
className="header"
|
||||
style={{
|
||||
// when content is closed, header should have minHeight
|
||||
height: minHeight
|
||||
}}
|
||||
>
|
||||
{header}
|
||||
</div>
|
||||
<div
|
||||
className="content-wrapper"
|
||||
style={{
|
||||
minHeight: isOpen ? height : 0,
|
||||
height: isOpen ? 'auto' : 0
|
||||
}}
|
||||
ref={contentRef}
|
||||
>
|
||||
<div className="content">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="content-wrapper"
|
||||
style={{ height: height }}
|
||||
ref={contentRef}
|
||||
>
|
||||
<div className="content">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default TransitionWrapper;
|
||||
|
||||
Reference in New Issue
Block a user