Skip to content

Commit d7ef2e9

Browse files
committed
update and implement FeedbackWidget component
refactors using Chakra-UI alert-dialog
1 parent bc400d6 commit d7ef2e9

File tree

3 files changed

+114
-149
lines changed

3 files changed

+114
-149
lines changed

src/components/FeedbackWidget.tsx

Lines changed: 112 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,40 @@
11
import { useEffect, useMemo, useRef, useState } from "react"
2-
import FocusTrap from "focus-trap-react"
32
import { useRouter } from "next/router"
43
import { useTranslation } from "next-i18next"
5-
import { MdClose } from "react-icons/md"
64
import {
5+
AlertDialog,
6+
AlertDialogBody,
7+
AlertDialogCloseButton,
8+
AlertDialogContent,
9+
AlertDialogFooter,
10+
AlertDialogHeader,
11+
AlertDialogOverlay,
712
Box,
813
Button,
914
ButtonProps,
10-
Flex,
11-
Icon,
1215
ScaleFade,
16+
useDisclosure,
1317
} from "@chakra-ui/react"
1418

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"
2221

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"
2823

29-
interface FixedDotProps extends ButtonProps {
24+
import { DEFAULT_LOCALE } from "@/lib/constants"
25+
26+
import { useSurvey } from "@/hooks/useSurvey"
27+
28+
type FixedDotProps = ButtonProps & {
3029
bottomOffset: number
3130
isExpanded: boolean
3231
}
33-
const FixedDot: React.FC<FixedDotProps> = ({
32+
const FixedDot = ({
3433
children,
3534
bottomOffset,
3635
isExpanded,
3736
...props
38-
}) => {
37+
}: FixedDotProps) => {
3938
const size = "3rem"
4039
return (
4140
<Button
@@ -55,11 +54,10 @@ const FixedDot: React.FC<FixedDotProps> = ({
5554
alignItems="center"
5655
whiteSpace="normal"
5756
_hover={{
58-
cursor: "pointer",
5957
transform: "scale(1.1)",
6058
transition: "transform 0.2s ease-in-out",
6159
}}
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,
6361
border-radius 0.25s linear"
6462
{...props}
6563
>
@@ -68,29 +66,24 @@ const FixedDot: React.FC<FixedDotProps> = ({
6866
)
6967
}
7068

71-
interface FeedbackWidgetProps {
72-
location: string
73-
}
74-
const FeedbackWidget: React.FC<FeedbackWidgetProps> = ({ location = "" }) => {
69+
const FeedbackWidget = () => {
7570
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)
8376

8477
useEffect(() => {
85-
// Reset component state when path (location) changes
86-
setIsOpen(false)
78+
// Reset component state when path (asPath) changes
79+
onClose()
8780
setFeedbackSubmitted(false)
8881
setIsExpanded(false)
8982

90-
let expandTimeout = setTimeout(() => setIsExpanded(true), 30000)
83+
let expandTimeout = setTimeout(() => setIsExpanded(true), 30_000)
9184

9285
return () => clearTimeout(expandTimeout)
93-
}, [location])
86+
}, [asPath, onClose])
9487

9588
const surveyUrl = useSurvey(feedbackSubmitted)
9689

@@ -99,30 +92,33 @@ const FeedbackWidget: React.FC<FeedbackWidgetProps> = ({ location = "" }) => {
9992
const CONDITIONAL_OFFSET = 6.75
10093
let offset = 0
10194
pathsWithBottomNav.forEach((path) => {
102-
if (location.includes(path)) {
95+
if (asPath.includes(path)) {
10396
offset = CONDITIONAL_OFFSET
10497
}
10598
})
10699
return offset
107-
}, [location])
100+
}, [asPath])
108101

109102
const handleClose = (): void => {
110-
setIsOpen(false)
103+
console.log("HANDLE CLOSE TRIGGERED")
104+
onClose()
111105
trackCustomEvent({
112106
eventCategory: `FeedbackWidget toggled`,
113107
eventAction: `Clicked`,
114108
eventName: `Closed feedback widget`,
115109
})
116110
}
111+
117112
const handleOpen = (): void => {
118-
setIsOpen(true)
113+
onOpen()
119114
setIsExpanded(false)
120115
trackCustomEvent({
121116
eventCategory: `FeedbackWidget toggled`,
122117
eventAction: `Clicked`,
123118
eventName: `Opened feedback widget`,
124119
})
125120
}
121+
126122
const handleSubmit = (choice: boolean): void => {
127123
trackCustomEvent({
128124
eventCategory: `Page is helpful feedback`,
@@ -138,14 +134,13 @@ const FeedbackWidget: React.FC<FeedbackWidgetProps> = ({ location = "" }) => {
138134
eventName: "Feedback survey opened",
139135
})
140136
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
142138
setIsExpanded(false)
143139
}
144140

145-
useKeyPress(`Escape`, handleClose)
141+
// Dispay on English pages only
142+
if (locale !== DEFAULT_LOCALE) return null
146143

147-
if (locale! !== DEFAULT_LOCALE) return null
148-
const closeButtonSize = "24px"
149144
return (
150145
<>
151146
<FixedDot
@@ -175,128 +170,97 @@ const FeedbackWidget: React.FC<FeedbackWidgetProps> = ({ location = "" }) => {
175170
alignItems="center"
176171
display={{ base: "none", lg: isExpanded ? "flex" : "none" }}
177172
>
178-
<Translation id="feedback-widget-prompt" />
173+
{t("feedback-widget-prompt")}
179174
</Text>
180175
</ScaleFade>
181176
)}
182177
</Box>
183178
</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"
196199
>
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"
219206
textAlign="center"
220-
p={8}
221207
>
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>
242212

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
257225
fontWeight="bold"
258226
fontSize="xs"
259-
lineHeight={4}
227+
lineHeight="4"
260228
letterSpacing="wide"
261229
color="searchBorder"
230+
textAlign="center"
262231
>
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+
<>
268244
<Button
269-
onClick={handleSurveyOpen}
270-
aria-label={t("feedback-widget-thank-you-cta")}
245+
variant="solid"
246+
onClick={() => handleSubmit(true)}
271247
flex={1}
272248
>
273-
<Translation id="feedback-widget-thank-you-cta" />
249+
{t("yes")}
274250
</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>
300264
</>
301265
)
302266
}

src/layouts/RootLayout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Container } from "@chakra-ui/react"
66
import { Lang } from "@/lib/types"
77
import { Root } from "@/lib/interfaces"
88

9+
import FeedbackWidget from "@/components/FeedbackWidget"
910
import Footer from "@/components/Footer"
1011
import Nav from "@/components/Nav"
1112
import TranslationBanner from "@/components/TranslationBanner"
@@ -62,6 +63,7 @@ export const RootLayout = ({
6263
{children}
6364

6465
<Footer lastDeployDate={lastDeployDate} />
66+
<FeedbackWidget />
6567
</Container>
6668
)
6769
}

tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161
"./src/components/EthVideo.tsx",
6262
"./src/components/EventCard.tsx",
6363
"./src/components/ExpandableInfo.tsx",
64-
"./src/components/FeedbackWidget.tsx",
6564
"./src/components/FileContributorsCrowdin.tsx",
6665
"./src/components/FindWallet/WalletFilterSidebar/WalletFilterFeature/index.tsx",
6766
"./src/components/FindWallet/WalletFilterSidebar/WalletFilterFeature/useWalletFilterFeature.tsx",

0 commit comments

Comments
 (0)