Skip to content

Commit dcf7793

Browse files
authored
Merge pull request #258 from ameerul-deriv/ameerul-add-scroll-to-accordion
Ameerul / Add Scroll To Accordion Functionality
2 parents 5017050 + 7a9638b commit dcf7793

File tree

2 files changed

+82
-64
lines changed

2 files changed

+82
-64
lines changed

src/components/Accordion/Accordion.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ $animation-duration: 0.3s;
6666
}
6767
&__content {
6868
width: 100%;
69-
overflow: auto;
69+
overflow: scroll;
7070
opacity: 0;
7171
background-color: var(--content-bg-color);
7272
transition: all $animation-duration ease;

src/components/Accordion/index.tsx

+81-63
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import React, {
44
ReactNode,
55
useEffect,
66
ComponentProps,
7+
forwardRef,
78
} from "react";
89
import Chevron from "./Chevron.svg";
910
import clsx from "clsx";
@@ -15,6 +16,7 @@ type AccordionProps = Omit<ComponentProps<"div">, "title"> & {
1516
children: ReactNode;
1617
defaultOpen?: boolean;
1718
isCompact?: boolean;
19+
onScrollToAccordion?: () => void;
1820
title: string | JSX.Element;
1921
variant?: AccordionVariants;
2022
headerClassName?: string;
@@ -27,80 +29,96 @@ const AccordionVariant = {
2729
underline: "deriv-accordion--underline",
2830
} as const;
2931

30-
export const Accordion = ({
31-
defaultOpen = false,
32-
children,
33-
isCompact = false,
34-
title,
35-
variant = "underline",
36-
className,
37-
headerClassName,
38-
contentClassName,
39-
...props
40-
}: AccordionProps) => {
41-
const [active, setActive] = useState(defaultOpen);
42-
const [setHeight, setHeightState] = useState(defaultOpen ? "auto" : "0px");
32+
export const Accordion = forwardRef<HTMLDivElement, AccordionProps>(
33+
(
34+
{
35+
defaultOpen = false,
36+
children,
37+
isCompact = false,
38+
onScrollToAccordion,
39+
title,
40+
variant = "underline",
41+
className,
42+
headerClassName,
43+
contentClassName,
44+
...props
45+
},
46+
ref,
47+
) => {
48+
const [active, setActive] = useState(defaultOpen);
49+
const [heightState, setHeightState] = useState(
50+
defaultOpen ? "auto" : "0px",
51+
);
4352

44-
const content = useRef<HTMLDivElement | null>(null);
53+
const content = useRef<HTMLDivElement | null>(null);
4554

46-
useEffect(() => {
47-
const scrollHeight = content?.current?.scrollHeight;
48-
setHeightState(active ? `${scrollHeight}px` : "0px");
49-
}, [active]);
55+
useEffect(() => {
56+
const scrollHeight = content?.current?.scrollHeight;
57+
setHeightState(active ? `${scrollHeight}px` : "0px");
58+
}, [active]);
5059

51-
const toggleAccordion = () => setActive(!active);
60+
const toggleAccordion = () => {
61+
const newActiveState = !active;
62+
setActive(newActiveState);
63+
setTimeout(() => {
64+
if (onScrollToAccordion && newActiveState)
65+
onScrollToAccordion();
66+
}, 200);
67+
};
5268

53-
return (
54-
<div
55-
className={clsx(
56-
"deriv-accordion",
57-
AccordionVariant[variant],
58-
{
59-
"deriv-accordion--compact": isCompact,
60-
},
61-
className,
62-
)}
63-
{...props}
64-
>
65-
<button
66-
className={clsx(
67-
"deriv-accordion__header",
68-
{
69-
"deriv-accordion__header--active": active,
70-
},
71-
headerClassName,
72-
)}
73-
onClick={toggleAccordion}
74-
aria-expanded={active}
75-
type="button"
76-
>
77-
{typeof title === "string" ? <p>{title}</p> : title}
78-
<img
79-
src={Chevron}
80-
className={clsx("deriv-accordion__icon", {
81-
"deriv-accordion__icon--active": active,
82-
})}
83-
/>
84-
</button>
69+
return (
8570
<div
86-
ref={content}
87-
style={{ maxHeight: setHeight }}
8871
className={clsx(
89-
"deriv-accordion__content",
72+
"deriv-accordion",
73+
AccordionVariant[variant],
9074
{
91-
"deriv-accordion__content--active": active,
75+
"deriv-accordion--compact": isCompact,
9276
},
93-
contentClassName
77+
className,
9478
)}
79+
ref={ref}
80+
{...props}
9581
>
82+
<button
83+
className={clsx(
84+
"deriv-accordion__header",
85+
{
86+
"deriv-accordion__header--active": active,
87+
},
88+
headerClassName,
89+
)}
90+
onClick={toggleAccordion}
91+
aria-expanded={active}
92+
type="button"
93+
>
94+
{typeof title === "string" ? <p>{title}</p> : title}
95+
<img
96+
src={Chevron}
97+
className={clsx("deriv-accordion__icon", {
98+
"deriv-accordion__icon--active": active,
99+
})}
100+
/>
101+
</button>
96102
<div
97-
className={clsx("deriv-accordion__text", {
98-
"deriv-accordion__text--compact": isCompact,
99-
})}
103+
ref={content}
104+
style={{ maxHeight: heightState }}
105+
className={clsx(
106+
"deriv-accordion__content",
107+
{
108+
"deriv-accordion__content--active": active,
109+
},
110+
contentClassName,
111+
)}
100112
>
101-
{children}
113+
<div
114+
className={clsx("deriv-accordion__text", {
115+
"deriv-accordion__text--compact": isCompact,
116+
})}
117+
>
118+
{children}
119+
</div>
102120
</div>
103121
</div>
104-
</div>
105-
);
106-
};
122+
);
123+
},
124+
);

0 commit comments

Comments
 (0)