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