1
1
// Libraries
2
2
import React , { ComponentType , ReactNode , SVGProps , useState } from "react"
3
- import styled from "@emotion/styled"
4
- import { motion } from "framer-motion"
5
3
6
4
// Components
7
5
import Translation from "./Translation"
8
6
9
7
// Utils
10
8
import { trackCustomEvent } from "../utils/matomo"
11
-
12
- const Card = styled . div `
13
- border: 1px solid ${ ( props ) => props . theme . colors . border } ;
14
- border-radius: 2px;
15
- padding: 1.5rem;
16
- display: flex;
17
- flex-direction: column;
18
- margin-bottom: 1rem;
19
- cursor: pointer;
20
- &:hover {
21
- background-color: ${ ( props ) => props . theme . colors . ednBackground } ;
22
- }
23
- `
24
-
25
- const Content = styled . div `
26
- display: flex;
27
- align-items: center;
28
- justify-content: space-between;
29
-
30
- @media (max-width: ${ ( props ) => props . theme . breakpoints . s } ) {
31
- flex-direction: column;
32
- }
33
- `
34
-
35
- const Title = styled . h3 `
36
- margin-top: 0rem;
37
- font-size: 1.25rem;
38
- font-weight: 600;
39
- margin-bottom: 0.5rem;
40
- `
41
-
42
- const TextPreview = styled . p `
43
- font-size: 0.875rem;
44
- font-weight: 400;
45
- color: ${ ( props ) => props . theme . colors . text200 } ;
46
- margin-bottom: 0rem;
47
- `
48
-
49
- const Text = styled ( motion . div ) `
50
- font-size: 1rem;
51
- font-weight: 400;
52
- color: ${ ( props ) => props . theme . colors . text } ;
53
- margin-top: 2rem;
54
- border-top: 1px solid ${ ( props ) => props . theme . colors . border } ;
55
- padding-top: 1.5rem;
56
- `
57
-
58
- const Question = styled . div `
59
- margin-right: 1rem;
60
-
61
- @media (max-width: ${ ( props ) => props . theme . breakpoints . s } ) {
62
- margin-right: 0;
63
- margin-bottom: 0.5rem;
64
- }
65
- `
66
-
67
- const Header = styled . div `
68
- display: flex;
69
- width: 100%;
70
- margin: 1rem 0;
71
- align-items: center;
72
- svg {
73
- margin-right: 1.5rem;
74
- }
75
- `
76
-
77
- const ButtonContainer = styled . div `
78
- margin-left: 1rem;
79
-
80
- @media (max-width: ${ ( props ) => props . theme . breakpoints . s } ) {
81
- margin-left: 0;
82
- }
83
- `
84
-
85
- const ButtonLink = styled . button `
86
- border: 0;
87
- cursor: pointer;
88
- background-color: transparent;
89
- color: ${ ( props ) => props . theme . colors . primary } ;
90
- `
9
+ import {
10
+ Accordion ,
11
+ AccordionButton ,
12
+ AccordionItem ,
13
+ AccordionPanel ,
14
+ Box ,
15
+ Heading ,
16
+ Text ,
17
+ } from "@chakra-ui/react"
91
18
92
19
export interface IProps {
93
20
children ?: React . ReactNode
@@ -107,111 +34,113 @@ const ExpandableCard: React.FC<IProps> = ({
107
34
eventName = "" ,
108
35
} ) => {
109
36
const [ isVisible , setIsVisible ] = useState ( false )
110
-
111
- const expandCollapse = {
112
- collapsed : {
113
- height : 0 ,
114
- transition : {
115
- when : "afterChildren" ,
116
- } ,
117
- } ,
118
- expanded : {
119
- height : "100%" ,
120
- transition : {
121
- when : "beforeChildren" ,
122
- } ,
123
- } ,
124
- }
125
-
126
- const showHide = {
127
- collapsed : {
128
- display : "none" ,
129
- } ,
130
- expanded : {
131
- display : "inline-block" ,
132
- } ,
133
- }
134
-
135
- const fadeInOut = {
136
- collapsed : {
137
- opacity : 0 ,
138
- transition : {
139
- duration : 0.1 ,
140
- } ,
141
- } ,
142
- expanded : {
143
- opacity : 1 ,
144
- transition : {
145
- duration : 0.4 ,
146
- } ,
147
- } ,
148
- }
149
37
const matomo = {
150
38
eventAction : `Clicked` ,
151
39
eventCategory : `ExpandableCard${ eventCategory } ` ,
152
40
eventName,
153
41
}
42
+ const onClick = ( ) => {
43
+ // Card will not collapse if clicking on a link or selecting text
44
+ if (
45
+ window . getSelection ( ) ?. toString ( ) . length === 0 &&
46
+ ! ( window . event ?. target as HTMLDivElement ) ?. className . includes (
47
+ "ExternalLink"
48
+ )
49
+ ) {
50
+ ! isVisible && trackCustomEvent ( matomo )
51
+ setIsVisible ( ! isVisible )
52
+ }
53
+ }
54
+
154
55
return (
155
- < Card
156
- onClick = { ( ) => {
157
- // Card will not collapse if clicking on a link or selecting text
158
- if (
159
- window . getSelection ( ) ?. toString ( ) . length === 0 &&
160
- ! ( window . event ?. target as HTMLDivElement ) ?. className . includes (
161
- "ExternalLink"
162
- )
163
- ) {
164
- ! isVisible && trackCustomEvent ( matomo )
165
- setIsVisible ( ! isVisible )
166
- }
56
+ < Accordion
57
+ border = "1px solid"
58
+ borderColor = "border"
59
+ borderRadius = "sm"
60
+ h3
61
+ display = "flex"
62
+ flex-direction = "column"
63
+ marginBottom = "4"
64
+ cursor = "pointer"
65
+ _hover = { {
66
+ backgroundColor : "ednBackground" ,
167
67
} }
68
+ borderBottomWidth = "0"
69
+ index = { isVisible ? [ 0 ] : [ ] }
168
70
>
169
- < Content >
170
- < Question >
171
- < Header >
172
- { ! ! Svg && < Svg /> }
173
- < Title > { title } </ Title >
174
- </ Header >
175
- < TextPreview > { contentPreview } </ TextPreview >
176
- </ Question >
177
- < ButtonContainer
178
- onClick = { ( ) => {
179
- trackCustomEvent ( matomo )
180
- setIsVisible ( ! isVisible )
181
- } }
182
- >
183
- { ! isVisible && (
184
- < ButtonLink onClick = { ( ) => setIsVisible ( true ) } >
185
- < Translation id = "more" />
186
- </ ButtonLink >
187
- ) }
188
- { isVisible && (
189
- < ButtonLink onClick = { ( ) => setIsVisible ( false ) } >
190
- < Translation id = "less" />
191
- </ ButtonLink >
192
- ) }
193
- </ ButtonContainer >
194
- </ Content >
195
- < motion . div
196
- variants = { expandCollapse }
197
- animate = { isVisible ? "expanded" : "collapsed" }
198
- initial = { false }
199
- >
200
- < motion . div
201
- variants = { showHide }
202
- animate = { isVisible ? "expanded" : "collapsed" }
203
- initial = { false }
71
+ < AccordionItem borderTopWidth = "0" flex = "1" >
72
+ < Heading as = "h3" m = { 0 } >
73
+ < AccordionButton
74
+ width = "100%"
75
+ p = { 6 }
76
+ flex = "1"
77
+ onClick = { onClick }
78
+ _hover = { {
79
+ backgroundColor : "ednBackground" ,
80
+ } }
81
+ >
82
+ < Box
83
+ display = "flex"
84
+ width = "100%"
85
+ alignItems = "center"
86
+ flexDir = { { base : "column" , sm : "row" } }
87
+ >
88
+ < Box
89
+ marginBottom = { { base : 2 , sm : 0 } }
90
+ marginRight = { { base : 0 , sm : 4 } }
91
+ >
92
+ < Box
93
+ display = "flex"
94
+ alignItems = "center"
95
+ sx = { {
96
+ svg : { marginRight : "1.5rem" } ,
97
+ } }
98
+ my = "4"
99
+ >
100
+ { ! ! Svg && < Svg /> }
101
+ < Text fontSize = "xl" fontWeight = "semibold" flex = "1" m = "0" >
102
+ { title }
103
+ </ Text >
104
+ </ Box >
105
+ < Text
106
+ fontSize = "sm"
107
+ color = "text200"
108
+ marginBottom = "0"
109
+ width = "fit-content"
110
+ >
111
+ { contentPreview }
112
+ </ Text >
113
+ </ Box >
114
+ < Text
115
+ fontSize = "md"
116
+ color = "primary"
117
+ ml = { { base : undefined , sm : "auto" } }
118
+ mt = "auto"
119
+ mb = "auto"
120
+ >
121
+ < Translation id = { isVisible ? "less" : "more" } />
122
+ </ Text >
123
+ </ Box >
124
+ </ AccordionButton >
125
+ </ Heading >
126
+ < AccordionPanel
127
+ paddingX = "6"
128
+ paddingBottom = "6"
129
+ paddingTop = "0"
130
+ onClick = { onClick }
204
131
>
205
- < Text
206
- variants = { fadeInOut }
207
- animate = { isVisible ? "expanded" : "collapsed" }
208
- initial = { false }
132
+ < Box
133
+ fontSize = "md"
134
+ color = "text"
135
+ paddingTop = "6"
136
+ borderTop = "1px solid"
137
+ borderColor = "border"
209
138
>
210
139
{ children }
211
- </ Text >
212
- </ motion . div >
213
- </ motion . div >
214
- </ Card >
140
+ </ Box >
141
+ </ AccordionPanel >
142
+ </ AccordionItem >
143
+ </ Accordion >
215
144
)
216
145
}
217
146
0 commit comments