@@ -4,6 +4,7 @@ import React, {
4
4
ReactNode ,
5
5
useEffect ,
6
6
ComponentProps ,
7
+ forwardRef ,
7
8
} from "react" ;
8
9
import Chevron from "./Chevron.svg" ;
9
10
import clsx from "clsx" ;
@@ -15,6 +16,7 @@ type AccordionProps = Omit<ComponentProps<"div">, "title"> & {
15
16
children : ReactNode ;
16
17
defaultOpen ?: boolean ;
17
18
isCompact ?: boolean ;
19
+ onScrollToAccordion ?: ( ) => void ;
18
20
title : string | JSX . Element ;
19
21
variant ?: AccordionVariants ;
20
22
headerClassName ?: string ;
@@ -27,80 +29,96 @@ const AccordionVariant = {
27
29
underline : "deriv-accordion--underline" ,
28
30
} as const ;
29
31
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
+ ) ;
43
52
44
- const content = useRef < HTMLDivElement | null > ( null ) ;
53
+ const content = useRef < HTMLDivElement | null > ( null ) ;
45
54
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 ] ) ;
50
59
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
+ } ;
52
68
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 (
85
70
< div
86
- ref = { content }
87
- style = { { maxHeight : setHeight } }
88
71
className = { clsx (
89
- "deriv-accordion__content" ,
72
+ "deriv-accordion" ,
73
+ AccordionVariant [ variant ] ,
90
74
{
91
- "deriv-accordion__content--active " : active ,
75
+ "deriv-accordion--compact " : isCompact ,
92
76
} ,
93
- contentClassName
77
+ className ,
94
78
) }
79
+ ref = { ref }
80
+ { ...props }
95
81
>
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 >
96
102
< 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
+ ) }
100
112
>
101
- { children }
113
+ < div
114
+ className = { clsx ( "deriv-accordion__text" , {
115
+ "deriv-accordion__text--compact" : isCompact ,
116
+ } ) }
117
+ >
118
+ { children }
119
+ </ div >
102
120
</ div >
103
121
</ div >
104
- </ div >
105
- ) ;
106
- } ;
122
+ ) ;
123
+ } ,
124
+ ) ;
0 commit comments