diff --git a/src/components/FeedbackWidget.tsx b/src/components/FeedbackWidget.tsx
deleted file mode 100644
index 0e13b47fb4f..00000000000
--- a/src/components/FeedbackWidget.tsx
+++ /dev/null
@@ -1,276 +0,0 @@
-import { useEffect, useMemo, useRef, useState } from "react"
-import { useRouter } from "next/router"
-import { useTranslation } from "next-i18next"
-import {
- AlertDialog,
- AlertDialogBody,
- AlertDialogCloseButton,
- AlertDialogContent,
- AlertDialogFooter,
- AlertDialogHeader,
- AlertDialogOverlay,
- Box,
- Button,
- ButtonProps,
- ScaleFade,
- useDisclosure,
-} from "@chakra-ui/react"
-
-import { FeedbackGlyphIcon } from "@/components/icons"
-import Text from "@/components/OldText"
-
-import { trackCustomEvent } from "@/lib/utils/matomo"
-
-import { DEFAULT_LOCALE } from "@/lib/constants"
-
-import { useSurvey } from "@/hooks/useSurvey"
-
-type FixedDotProps = ButtonProps & {
- bottomOffset: number
- isExpanded: boolean
-}
-const FixedDot = ({
- children,
- bottomOffset,
- isExpanded,
- ...props
-}: FixedDotProps) => {
- const { t } = useTranslation("common")
- const size = "3rem"
- return (
-
- )
-}
-
-const FeedbackWidget = () => {
- const { t } = useTranslation("common")
- const { asPath, locale } = useRouter()
- const { isOpen, onOpen, onClose } = useDisclosure()
- const cancelRef = useRef(null)
- const [isExpanded, setIsExpanded] = useState(false)
- const [feedbackSubmitted, setFeedbackSubmitted] = useState(false)
-
- useEffect(() => {
- // Reset component state when path (asPath) changes
- onClose()
- setFeedbackSubmitted(false)
- setIsExpanded(false)
-
- let expandTimeout = setTimeout(() => setIsExpanded(true), 30_000)
-
- return () => clearTimeout(expandTimeout)
- }, [asPath, onClose])
-
- const surveyUrl = useSurvey(feedbackSubmitted)
-
- const bottomOffset = useMemo(() => {
- const pathsWithBottomNav = ["/staking/", "/dao/", "/defi/", "/nft/"]
- const CONDITIONAL_OFFSET = 6.75
- let offset = 0
- pathsWithBottomNav.forEach((path) => {
- if (asPath.includes(path)) {
- offset = CONDITIONAL_OFFSET
- }
- })
- return offset
- }, [asPath])
-
- const handleClose = (): void => {
- onClose()
- trackCustomEvent({
- eventCategory: `FeedbackWidget toggled`,
- eventAction: `Clicked`,
- eventName: `Closed feedback widget`,
- })
- }
-
- const handleOpen = (): void => {
- onOpen()
- setIsExpanded(false)
- trackCustomEvent({
- eventCategory: `FeedbackWidget toggled`,
- eventAction: `Clicked`,
- eventName: `Opened feedback widget`,
- })
- }
-
- const handleSubmit = (choice: boolean): void => {
- trackCustomEvent({
- eventCategory: `Page is helpful feedback`,
- eventAction: `Clicked`,
- eventName: String(choice),
- })
- setFeedbackSubmitted(true)
- }
- const handleSurveyOpen = (): void => {
- trackCustomEvent({
- eventCategory: `Feedback survey opened`,
- eventAction: `Clicked`,
- eventName: "Feedback survey opened",
- })
- window && surveyUrl && window.open(surveyUrl, "_blank")
- onClose() // Close widget without triggering redundant tracker event
- setIsExpanded(false)
- }
-
- // Display on English pages only
- if (locale !== DEFAULT_LOCALE) return null
-
- return (
- <>
-
-
-
- {isExpanded && (
-
-
- {t("feedback-widget-prompt")}
-
-
- )}
-
-
-
-
-
-
-
-
-
-
- {feedbackSubmitted
- ? t("feedback-widget-thank-you-title")
- : t("feedback-widget-prompt")}
-
-
- {/* Body: */}
- {feedbackSubmitted && (
- <>
-
- {t("feedback-widget-thank-you-subtitle")}
-
-
- {t("feedback-widget-thank-you-timing")}
-
- >
- )}
-
-
- {feedbackSubmitted ? (
-
- ) : (
- <>
-
-
- >
- )}
-
-
-
-
-
- >
- )
-}
-
-export default FeedbackWidget
diff --git a/src/components/FeedbackWidget/FeedbackWidget.stories.tsx b/src/components/FeedbackWidget/FeedbackWidget.stories.tsx
new file mode 100644
index 00000000000..273fcd627bf
--- /dev/null
+++ b/src/components/FeedbackWidget/FeedbackWidget.stories.tsx
@@ -0,0 +1,28 @@
+import * as React from "react"
+import { Box, Stack } from "@chakra-ui/react"
+import { Meta, StoryObj } from "@storybook/react"
+
+import FeedbackWidgetComponent from "./"
+
+type FeedbackWidgetType = typeof FeedbackWidgetComponent
+
+const meta = {
+ title: "FeedbackWidget",
+ parameters: {
+ layout: "fullscreen",
+ },
+ decorators: [
+ (Story) => (
+
+
+
+
+ ),
+ ],
+} satisfies Meta
+
+export default meta
+
+export const FeedbackWidget: StoryObj = {
+ render: () => ,
+}
diff --git a/src/components/FeedbackWidget/FixedDot.tsx b/src/components/FeedbackWidget/FixedDot.tsx
new file mode 100644
index 00000000000..a9a9a8d0a63
--- /dev/null
+++ b/src/components/FeedbackWidget/FixedDot.tsx
@@ -0,0 +1,60 @@
+import { useTranslation } from "next-i18next"
+import { Button, ButtonProps, ScaleFade, Text } from "@chakra-ui/react"
+
+import { FeedbackGlyphIcon } from "../icons"
+
+type FixedDotProps = ButtonProps & {
+ bottomOffset: number
+ isExpanded: boolean
+}
+const FixedDot = ({ bottomOffset, isExpanded, ...props }: FixedDotProps) => {
+ const { t } = useTranslation("common")
+ const size = "12"
+ return (
+ }
+ iconSpacing={{ base: 0, lg: "3" }}
+ sx={{
+ ".chakra-button__icon": {
+ me: !isExpanded ? 0 : undefined,
+ },
+ }}
+ {...props}
+ >
+
+
+ {t("feedback-widget-prompt")}
+
+
+
+ )
+}
+
+export default FixedDot
diff --git a/src/components/FeedbackWidget/index.tsx b/src/components/FeedbackWidget/index.tsx
new file mode 100644
index 00000000000..060581a57a3
--- /dev/null
+++ b/src/components/FeedbackWidget/index.tsx
@@ -0,0 +1,136 @@
+import { useTranslation } from "next-i18next"
+import {
+ AlertDialog,
+ AlertDialogBody,
+ AlertDialogCloseButton,
+ AlertDialogContent,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogOverlay,
+ Box,
+ Button,
+} from "@chakra-ui/react"
+
+import FixedDot from "./FixedDot"
+import { useFeedbackWidget } from "./useFeedbackWidget"
+
+const FeedbackWidget = () => {
+ const { t } = useTranslation("common")
+ const {
+ bottomOffset,
+ cancelRef,
+ feedbackSubmitted,
+ getButtonProps,
+ handleClose,
+ handleOpen,
+ handleSubmit,
+ handleSurveyOpen,
+ isExpanded,
+ isOpen,
+ } = useFeedbackWidget()
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {feedbackSubmitted
+ ? t("feedback-widget-thank-you-title")
+ : t("feedback-widget-prompt")}
+
+
+ {/* Body: */}
+ {feedbackSubmitted && (
+ <>
+
+ {t("feedback-widget-thank-you-subtitle")}
+
+
+ {t("feedback-widget-thank-you-timing")}
+
+ >
+ )}
+
+
+ {feedbackSubmitted ? (
+
+ ) : (
+ <>
+
+
+ >
+ )}
+
+
+
+
+
+ >
+ )
+}
+
+export default FeedbackWidget
diff --git a/src/components/FeedbackWidget/useFeedbackWidget.ts b/src/components/FeedbackWidget/useFeedbackWidget.ts
new file mode 100644
index 00000000000..a32efcafb67
--- /dev/null
+++ b/src/components/FeedbackWidget/useFeedbackWidget.ts
@@ -0,0 +1,94 @@
+import { useEffect, useMemo, useRef, useState } from "react"
+import { useRouter } from "next/router"
+import { useDisclosure } from "@chakra-ui/react"
+
+import { trackCustomEvent } from "@/lib/utils/matomo"
+
+import { useSurvey } from "@/hooks/useSurvey"
+
+export const useFeedbackWidget = () => {
+ const { asPath } = useRouter()
+
+ const [isExpanded, setIsExpanded] = useState(false)
+ const [feedbackSubmitted, setFeedbackSubmitted] = useState(false)
+
+ const { getButtonProps, isOpen, onClose, onOpen } = useDisclosure()
+
+ const cancelRef = useRef(null)
+
+ useEffect(() => {
+ // Reset component state when path (asPath) changes
+ onClose()
+ setFeedbackSubmitted(false)
+ setIsExpanded(false)
+
+ let expandTimeout = setTimeout(() => setIsExpanded(true), 30_000)
+
+ return () => clearTimeout(expandTimeout)
+ }, [asPath, onClose])
+
+ const surveyUrl = useSurvey(feedbackSubmitted)
+
+ const bottomOffset = useMemo(() => {
+ const pathsWithBottomNav = ["/staking", "/dao", "/defi", "/nft"]
+ const CONDITIONAL_OFFSET = 6.75
+ let offset = 0
+ pathsWithBottomNav.forEach((path) => {
+ if (asPath.includes(path)) {
+ offset = CONDITIONAL_OFFSET
+ }
+ })
+ return offset
+ }, [asPath])
+
+ const handleClose = (): void => {
+ onClose()
+ trackCustomEvent({
+ eventCategory: `FeedbackWidget toggled`,
+ eventAction: `Clicked`,
+ eventName: `Closed feedback widget`,
+ })
+ }
+
+ const handleOpen = (): void => {
+ onOpen()
+ setIsExpanded(false)
+ trackCustomEvent({
+ eventCategory: `FeedbackWidget toggled`,
+ eventAction: `Clicked`,
+ eventName: `Opened feedback widget`,
+ })
+ }
+
+ const handleSubmit = (choice: boolean): void => {
+ trackCustomEvent({
+ eventCategory: `Page is helpful feedback`,
+ eventAction: `Clicked`,
+ eventName: String(choice),
+ })
+ setFeedbackSubmitted(true)
+ }
+ const handleSurveyOpen = (): void => {
+ trackCustomEvent({
+ eventCategory: `Feedback survey opened`,
+ eventAction: `Clicked`,
+ eventName: "Feedback survey opened",
+ })
+ window && surveyUrl && window.open(surveyUrl, "_blank")
+ onClose() // Close widget without triggering redundant tracker event
+ setIsExpanded(false)
+ }
+
+ return {
+ bottomOffset,
+ cancelRef,
+ feedbackSubmitted,
+ getButtonProps,
+ handleClose,
+ handleOpen,
+ handleSubmit,
+ handleSurveyOpen,
+ isExpanded,
+ isOpen,
+ }
+}
diff --git a/src/data/crowdin/translation-buckets-dirs.json b/src/data/crowdin/translation-buckets-dirs.json
index 047969f7919..f3595190c39 100644
--- a/src/data/crowdin/translation-buckets-dirs.json
+++ b/src/data/crowdin/translation-buckets-dirs.json
@@ -115,4 +115,4 @@
"id": 8218,
"name": "Menu redesign & language picker"
}
-]
\ No newline at end of file
+]