mirror of
https://github.com/QuivrHQ/quivr.git
synced 2024-12-15 09:32:22 +03:00
Feature: Add animations to foldable section (#2202)
# Description Refactored the foldable section. The design is inspired by [Material Design's expansion panel](https://m1.material.io/components/expansion-panels.html#). The existing design has the chevron alternating from pointing down to pointing right. This is misleading because there is no subordinate information to the right. Also, this PR animates the arrow and foldable section, creating a delightful experience. ## Checklist before requesting a review - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have commented hard-to-understand areas - [x] New and existing unit tests pass locally with my changes - [x] Any dependent changes have been merged ## Screenshots (if appropriate): [expansion.webm](https://github.com/QuivrHQ/quivr/assets/1273463/71ef2c98-c0ed-4374-840e-0bf16bf4da55) ### Update [expansion2.webm](https://github.com/QuivrHQ/quivr/assets/1273463/0be769d2-93b4-42e3-938d-3bc0a63e0e06)
This commit is contained in:
parent
7212e62859
commit
ec5679072f
@ -2,6 +2,7 @@
|
|||||||
@use "@/styles/Radius.module.scss";
|
@use "@/styles/Radius.module.scss";
|
||||||
@use "@/styles/Spacings.module.scss";
|
@use "@/styles/Spacings.module.scss";
|
||||||
@use "@/styles/Typography.module.scss";
|
@use "@/styles/Typography.module.scss";
|
||||||
|
@use "@/styles/Transitions.module.scss";
|
||||||
|
|
||||||
.foldable_section_wrapper {
|
.foldable_section_wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -11,6 +12,15 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-size: Typography.$small;
|
font-size: Typography.$small;
|
||||||
|
|
||||||
|
.contentWrapper {
|
||||||
|
overflow: hidden;
|
||||||
|
transition: max-height 0.3s Transitions.$easeOutBack;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contentCollapsed {
|
||||||
|
max-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
&.hide_border {
|
&.hide_border {
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
}
|
}
|
||||||
@ -37,4 +47,16 @@
|
|||||||
background-color: Colors.$lightest-black;
|
background-color: Colors.$lightest-black;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.iconRotate {
|
||||||
|
transition: transform 0.3s Transitions.$easeOutBack;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconRotateDown {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconRotateRight {
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
import { iconList } from "@/lib/helpers/iconList";
|
import { iconList } from "@/lib/helpers/iconList";
|
||||||
|
|
||||||
@ -16,11 +16,16 @@ interface FoldableSectionProps {
|
|||||||
|
|
||||||
export const FoldableSection = (props: FoldableSectionProps): JSX.Element => {
|
export const FoldableSection = (props: FoldableSectionProps): JSX.Element => {
|
||||||
const [folded, setFolded] = useState<boolean>(false);
|
const [folded, setFolded] = useState<boolean>(false);
|
||||||
|
const contentRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setFolded(props.foldedByDefault ?? false);
|
setFolded(props.foldedByDefault ?? false);
|
||||||
}, [props.foldedByDefault]);
|
}, [props.foldedByDefault]);
|
||||||
|
|
||||||
|
const getContentHeight = (): string => {
|
||||||
|
return folded ? "0" : `${contentRef.current?.scrollHeight}px`;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`
|
className={`
|
||||||
@ -35,12 +40,22 @@ export const FoldableSection = (props: FoldableSectionProps): JSX.Element => {
|
|||||||
<p className={styles.header_title}>{props.label}</p>
|
<p className={styles.header_title}>{props.label}</p>
|
||||||
</div>
|
</div>
|
||||||
<Icon
|
<Icon
|
||||||
name={folded ? "chevronDown" : "chevronRight"}
|
name="chevronDown"
|
||||||
size="normal"
|
size="normal"
|
||||||
color="black"
|
color="black"
|
||||||
|
classname={`${styles.iconRotate} ${
|
||||||
|
folded ? styles.iconRotateDown : styles.iconRotateRight
|
||||||
|
}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ height: folded ? "0" : "auto" }}>{props.children}</div>
|
<div
|
||||||
|
ref={contentRef}
|
||||||
|
className={`${styles.contentWrapper} ${
|
||||||
|
folded ? styles.contentCollapsed : styles.contentExpanded
|
||||||
|
}`}
|
||||||
|
style={{ maxHeight: getContentHeight() }}
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
2
frontend/styles/_Transitions.module.scss
Normal file
2
frontend/styles/_Transitions.module.scss
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Transition animations
|
||||||
|
$easeOutBack: cubic-bezier(0.65, 0.05, 0.36, 1);
|
Loading…
Reference in New Issue
Block a user