1
1
import { useEffect , useMemo , useRef , useState } from "react"
2
- import FocusTrap from "focus-trap-react"
3
2
import { useRouter } from "next/router"
4
3
import { useTranslation } from "next-i18next"
5
- import { MdClose } from "react-icons/md"
6
4
import {
5
+ AlertDialog ,
6
+ AlertDialogBody ,
7
+ AlertDialogCloseButton ,
8
+ AlertDialogContent ,
9
+ AlertDialogFooter ,
10
+ AlertDialogHeader ,
11
+ AlertDialogOverlay ,
7
12
Box ,
8
13
Button ,
9
14
ButtonProps ,
10
- Flex ,
11
- Icon ,
12
15
ScaleFade ,
16
+ useDisclosure ,
13
17
} from "@chakra-ui/react"
14
18
15
- import { useKeyPress } from "../hooks/useKeyPress"
16
- // Hook imports
17
- import { useOnClickOutside } from "../hooks/useOnClickOutside"
18
- import { useSurvey } from "../hooks/useSurvey"
19
- import { DEFAULT_LOCALE } from "../lib/constants"
20
- // Utility imports
21
- import { trackCustomEvent } from "../utils/matomo"
19
+ import { FeedbackGlyphIcon } from "@/components/icons"
20
+ import Text from "@/components/OldText"
22
21
23
- // SVG imports
24
- import { FeedbackGlyphIcon } from "./icons"
25
- import Text from "./OldText"
26
- // Component imports
27
- import Translation from "./Translation"
22
+ import { trackCustomEvent } from "@/lib/utils/matomo"
28
23
29
- interface FixedDotProps extends ButtonProps {
24
+ import { DEFAULT_LOCALE } from "@/lib/constants"
25
+
26
+ import { useSurvey } from "@/hooks/useSurvey"
27
+
28
+ type FixedDotProps = ButtonProps & {
30
29
bottomOffset : number
31
30
isExpanded : boolean
32
31
}
33
- const FixedDot : React . FC < FixedDotProps > = ( {
32
+ const FixedDot = ( {
34
33
children,
35
34
bottomOffset,
36
35
isExpanded,
37
36
...props
38
- } ) => {
37
+ } : FixedDotProps ) => {
39
38
const size = "3rem"
40
39
return (
41
40
< Button
@@ -55,11 +54,10 @@ const FixedDot: React.FC<FixedDotProps> = ({
55
54
alignItems = "center"
56
55
whiteSpace = "normal"
57
56
_hover = { {
58
- cursor : "pointer" ,
59
57
transform : "scale(1.1)" ,
60
58
transition : "transform 0.2s ease-in-out" ,
61
59
} }
62
- transition = "transform 0.2s ease-in-out, width 0.25s linear ,
60
+ transition = "transform 0.2s ease-in-out, width 0.25s ease-in-out ,
63
61
border-radius 0.25s linear"
64
62
{ ...props }
65
63
>
@@ -68,29 +66,24 @@ const FixedDot: React.FC<FixedDotProps> = ({
68
66
)
69
67
}
70
68
71
- interface FeedbackWidgetProps {
72
- location : string
73
- }
74
- const FeedbackWidget : React . FC < FeedbackWidgetProps > = ( { location = "" } ) => {
69
+ const FeedbackWidget = ( ) => {
75
70
const { t } = useTranslation ( "common" )
76
- const { locale } = useRouter ( )
77
-
78
- const containerRef = useRef < HTMLInputElement > ( null )
79
- useOnClickOutside ( containerRef , ( ) => handleClose ( ) , [ `mousedown` ] )
80
- const [ isOpen , setIsOpen ] = useState < boolean > ( false )
81
- const [ isExpanded , setIsExpanded ] = useState < boolean > ( false )
82
- const [ feedbackSubmitted , setFeedbackSubmitted ] = useState < boolean > ( false )
71
+ const { asPath, locale } = useRouter ( )
72
+ const { isOpen, onOpen, onClose } = useDisclosure ( )
73
+ const cancelRef = useRef < HTMLButtonElement > ( null )
74
+ const [ isExpanded , setIsExpanded ] = useState ( false )
75
+ const [ feedbackSubmitted , setFeedbackSubmitted ] = useState ( false )
83
76
84
77
useEffect ( ( ) => {
85
- // Reset component state when path (location ) changes
86
- setIsOpen ( false )
78
+ // Reset component state when path (asPath ) changes
79
+ onClose ( )
87
80
setFeedbackSubmitted ( false )
88
81
setIsExpanded ( false )
89
82
90
- let expandTimeout = setTimeout ( ( ) => setIsExpanded ( true ) , 30000 )
83
+ let expandTimeout = setTimeout ( ( ) => setIsExpanded ( true ) , 30_000 )
91
84
92
85
return ( ) => clearTimeout ( expandTimeout )
93
- } , [ location ] )
86
+ } , [ asPath , onClose ] )
94
87
95
88
const surveyUrl = useSurvey ( feedbackSubmitted )
96
89
@@ -99,30 +92,33 @@ const FeedbackWidget: React.FC<FeedbackWidgetProps> = ({ location = "" }) => {
99
92
const CONDITIONAL_OFFSET = 6.75
100
93
let offset = 0
101
94
pathsWithBottomNav . forEach ( ( path ) => {
102
- if ( location . includes ( path ) ) {
95
+ if ( asPath . includes ( path ) ) {
103
96
offset = CONDITIONAL_OFFSET
104
97
}
105
98
} )
106
99
return offset
107
- } , [ location ] )
100
+ } , [ asPath ] )
108
101
109
102
const handleClose = ( ) : void => {
110
- setIsOpen ( false )
103
+ console . log ( "HANDLE CLOSE TRIGGERED" )
104
+ onClose ( )
111
105
trackCustomEvent ( {
112
106
eventCategory : `FeedbackWidget toggled` ,
113
107
eventAction : `Clicked` ,
114
108
eventName : `Closed feedback widget` ,
115
109
} )
116
110
}
111
+
117
112
const handleOpen = ( ) : void => {
118
- setIsOpen ( true )
113
+ onOpen ( )
119
114
setIsExpanded ( false )
120
115
trackCustomEvent ( {
121
116
eventCategory : `FeedbackWidget toggled` ,
122
117
eventAction : `Clicked` ,
123
118
eventName : `Opened feedback widget` ,
124
119
} )
125
120
}
121
+
126
122
const handleSubmit = ( choice : boolean ) : void => {
127
123
trackCustomEvent ( {
128
124
eventCategory : `Page is helpful feedback` ,
@@ -138,14 +134,13 @@ const FeedbackWidget: React.FC<FeedbackWidgetProps> = ({ location = "" }) => {
138
134
eventName : "Feedback survey opened" ,
139
135
} )
140
136
window && surveyUrl && window . open ( surveyUrl , "_blank" )
141
- setIsOpen ( false ) // Close widget without triggering redundant tracker event
137
+ onClose ( ) // Close widget without triggering redundant tracker event
142
138
setIsExpanded ( false )
143
139
}
144
140
145
- useKeyPress ( `Escape` , handleClose )
141
+ // Dispay on English pages only
142
+ if ( locale !== DEFAULT_LOCALE ) return null
146
143
147
- if ( locale ! !== DEFAULT_LOCALE ) return null
148
- const closeButtonSize = "24px"
149
144
return (
150
145
< >
151
146
< FixedDot
@@ -175,128 +170,97 @@ const FeedbackWidget: React.FC<FeedbackWidgetProps> = ({ location = "" }) => {
175
170
alignItems = "center"
176
171
display = { { base : "none" , lg : isExpanded ? "flex" : "none" } }
177
172
>
178
- < Translation id = "feedback-widget-prompt" />
173
+ { t ( "feedback-widget-prompt" ) }
179
174
</ Text >
180
175
</ ScaleFade >
181
176
) }
182
177
</ Box >
183
178
</ FixedDot >
184
- { isOpen && (
185
- < Box
186
- display = "block"
187
- position = "fixed"
188
- inset = { 0 }
189
- bgColor = "blackAlpha.400"
190
- zIndex = { 1001 } /* Above the nav bar */
191
- >
192
- < FocusTrap
193
- focusTrapOptions = { {
194
- fallbackFocus : `#dot` ,
195
- } }
179
+
180
+ < AlertDialog
181
+ isOpen = { isOpen }
182
+ leastDestructiveRef = { cancelRef }
183
+ onClose = { handleClose }
184
+ >
185
+ < AlertDialogOverlay >
186
+ < AlertDialogContent
187
+ position = "fixed"
188
+ insetEnd = { { base : 4 , sm : 8 } }
189
+ insetStart = { { base : 4 , sm : "auto" } }
190
+ bottom = { { base : `${ bottomOffset + 5 } rem` , lg : 20 } }
191
+ w = { { base : "auto" , sm : "300px" } }
192
+ bgColor = "ednBackground"
193
+ border = "1px"
194
+ borderColor = "buttonColor"
195
+ boxShadow = "tableItemBox"
196
+ borderRadius = "base"
197
+ py = "4"
198
+ px = "2"
196
199
>
197
- < Flex
198
- id = "modal"
199
- ref = { containerRef }
200
- boxSizing = "border-box"
201
- w = { { base : "auto" , sm : "300px" } }
202
- bgColor = "ednBackground"
203
- border = "1px"
204
- borderColor = "buttonColor"
205
- boxShadow = "tableItemBox"
206
- borderRadius = "base" /* 0.25rem */
207
- position = "fixed"
208
- insetEnd = { { base : 4 , sm : 8 } }
209
- insetStart = { { base : 4 , sm : "auto" } }
210
- bottom = { { base : `${ bottomOffset + 5 } rem` , lg : 20 } }
211
- zIndex = { 1002 } /* Above the modal background */
212
- _hover = { {
213
- transform : "scale(1.02)" ,
214
- transition : "transform 0.2s ease-in-out" ,
215
- } }
216
- transition = "transform 0.2s ease-in-out"
217
- direction = "column"
218
- alignItems = "center"
200
+ < AlertDialogCloseButton />
201
+
202
+ < AlertDialogHeader
203
+ fontSize = "xl"
204
+ fontWeight = "bold"
205
+ lineHeight = "6"
219
206
textAlign = "center"
220
- p = { 8 }
221
207
>
222
- < Button
223
- variant = "ghost"
224
- onClick = { handleClose }
225
- aria-label = { t ( "close" ) }
226
- position = "absolute"
227
- insetEnd = { 2 }
228
- top = { 2 }
229
- cursor = "pointer"
230
- h = { closeButtonSize }
231
- w = { closeButtonSize }
232
- minW = { closeButtonSize }
233
- minH = { closeButtonSize }
234
- _hover = { {
235
- transform : "scale(1.1)" ,
236
- transition : "transform 0.2s ease-in-out" ,
237
- } }
238
- transition = "transform 0.2s ease-in-out"
239
- >
240
- < Icon as = { MdClose } h = { closeButtonSize } w = { closeButtonSize } />
241
- </ Button >
208
+ { feedbackSubmitted
209
+ ? t ( "feedback-widget-thank-you-title" )
210
+ : t ( "feedback-widget-prompt" ) }
211
+ </ AlertDialogHeader >
242
212
243
- < Text fontWeight = "bold" fontSize = "xl" lineHeight = { 6 } >
244
- { feedbackSubmitted ? (
245
- < Translation id = "feedback-widget-thank-you-title" />
246
- ) : (
247
- < Translation id = "feedback-widget-prompt" />
248
- ) }
249
- </ Text >
250
- { feedbackSubmitted && (
251
- < Text fontWeight = "normal" fontSize = "md" lineHeight = { 5 } >
252
- < Translation id = "feedback-widget-thank-you-subtitle" />
253
- </ Text >
254
- ) }
255
- { feedbackSubmitted && (
256
- < Text
213
+ { /* Body: */ }
214
+ { feedbackSubmitted && (
215
+ < >
216
+ < AlertDialogBody
217
+ fontWeight = "normal"
218
+ fontSize = "md"
219
+ lineHeight = "5"
220
+ textAlign = "center"
221
+ >
222
+ { t ( "feedback-widget-thank-you-subtitle" ) }
223
+ </ AlertDialogBody >
224
+ < AlertDialogBody
257
225
fontWeight = "bold"
258
226
fontSize = "xs"
259
- lineHeight = { 4 }
227
+ lineHeight = "4"
260
228
letterSpacing = "wide"
261
229
color = "searchBorder"
230
+ textAlign = "center"
262
231
>
263
- < Translation id = "feedback-widget-thank-you-timing" />
264
- </ Text >
265
- ) }
266
- < Flex flexWrap = "nowrap" gap = { 6 } width = "full" >
267
- { feedbackSubmitted ? (
232
+ { t ( "feedback-widget-thank-you-timing" ) }
233
+ </ AlertDialogBody >
234
+ </ >
235
+ ) }
236
+
237
+ < AlertDialogFooter display = "flex" gap = "6" >
238
+ { feedbackSubmitted ? (
239
+ < Button onClick = { handleSurveyOpen } flex = { 1 } >
240
+ { t ( "feedback-widget-thank-you-cta" ) }
241
+ </ Button >
242
+ ) : (
243
+ < >
268
244
< Button
269
- onClick = { handleSurveyOpen }
270
- aria-label = { t ( "feedback-widget-thank-you-cta" ) }
245
+ variant = "solid"
246
+ onClick = { ( ) => handleSubmit ( true ) }
271
247
flex = { 1 }
272
248
>
273
- < Translation id = "feedback-widget-thank-you-cta" />
249
+ { t ( "yes" ) }
274
250
</ Button >
275
- ) : (
276
- < >
277
- < Button
278
- variant = "solid"
279
- onClick = { ( ) => handleSubmit ( true ) }
280
- aria-label = { t ( "yes" ) }
281
- flex = { 1 }
282
- >
283
- < Translation id = "yes" />
284
- </ Button >
285
- < Button
286
- variant = "solid"
287
- onClick = { ( ) => handleSubmit ( false ) }
288
- aria-label = { t ( "no" ) }
289
- flex = { 1 }
290
- >
291
- < Translation id = "no" />
292
- </ Button >
293
- </ >
294
- ) }
295
- </ Flex >
296
- </ Flex >
297
- </ FocusTrap >
298
- </ Box >
299
- ) }
251
+ < Button
252
+ variant = "solid"
253
+ onClick = { ( ) => handleSubmit ( false ) }
254
+ flex = { 1 }
255
+ >
256
+ { t ( "no" ) }
257
+ </ Button >
258
+ </ >
259
+ ) }
260
+ </ AlertDialogFooter >
261
+ </ AlertDialogContent >
262
+ </ AlertDialogOverlay >
263
+ </ AlertDialog >
300
264
</ >
301
265
)
302
266
}
0 commit comments