From 5f0b5adeb604d5621b5178ea7f08b09ea4eba15c Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Fri, 2 Feb 2024 18:00:49 -0500 Subject: [PATCH] feature: feedback button (#423) --- .../BottomNavigationButtons.tsx | 5 +- packages/ui/app/src/components/FernButton.tsx | 107 ++++++++++++++++++ .../src/custom-docs-page/CustomDocsPage.tsx | 3 + .../ui/app/src/custom-docs-page/Feedback.tsx | 83 ++++++++++++++ 4 files changed, 195 insertions(+), 3 deletions(-) create mode 100644 packages/ui/app/src/components/FernButton.tsx create mode 100644 packages/ui/app/src/custom-docs-page/Feedback.tsx diff --git a/packages/ui/app/src/bottom-navigation-buttons/BottomNavigationButtons.tsx b/packages/ui/app/src/bottom-navigation-buttons/BottomNavigationButtons.tsx index 0c562dc298..466314dd99 100644 --- a/packages/ui/app/src/bottom-navigation-buttons/BottomNavigationButtons.tsx +++ b/packages/ui/app/src/bottom-navigation-buttons/BottomNavigationButtons.tsx @@ -10,9 +10,8 @@ export const BottomNavigationButtons: React.FC = () => { } return ( -
-
-
+
+
{leftNeighbor != null ? ( ) : ( diff --git a/packages/ui/app/src/components/FernButton.tsx b/packages/ui/app/src/components/FernButton.tsx new file mode 100644 index 0000000000..5c74149431 --- /dev/null +++ b/packages/ui/app/src/components/FernButton.tsx @@ -0,0 +1,107 @@ +import classNames from "classnames"; +import { ButtonHTMLAttributes, DetailedHTMLProps, FC, ReactNode } from "react"; +import { RemoteFontAwesomeIcon } from "../commons/FontAwesomeIcon"; + +interface FernButtonProps extends DetailedHTMLProps, HTMLButtonElement> { + icon?: string | ReactNode; + rightIcon?: string | ReactNode; + minimal?: boolean; + intent?: "none" | "primary" | "success" | "danger"; + small?: boolean; + mono?: boolean; + active?: boolean; + full?: boolean; + disabled?: boolean; +} +export const FernButton: FC = ({ + icon: leftIcon, + rightIcon, + className, + children, + minimal = false, + intent = "none", + small = false, + mono = false, + active = false, + full = false, + disabled = false, + ...props +}) => { + function renderIcon(icon: string | ReactNode | undefined) { + if (typeof icon === "string") { + return ( + + ); + } else { + return icon; + } + } + + return ( + + ); +}; diff --git a/packages/ui/app/src/custom-docs-page/CustomDocsPage.tsx b/packages/ui/app/src/custom-docs-page/CustomDocsPage.tsx index 8358f51ebf..04b9a3f8ec 100644 --- a/packages/ui/app/src/custom-docs-page/CustomDocsPage.tsx +++ b/packages/ui/app/src/custom-docs-page/CustomDocsPage.tsx @@ -5,6 +5,7 @@ import { ReactElement } from "react"; import { renderToString } from "react-dom/server"; import { BottomNavigationButtons } from "../bottom-navigation-buttons/BottomNavigationButtons"; import { MdxContent } from "../mdx/MdxContent"; +import { Feedback } from "./Feedback"; import { TableOfContents } from "./TableOfContents"; import { TableOfContentsContextProvider } from "./TableOfContentsContext"; @@ -43,6 +44,8 @@ export const CustomDocsPage: React.FC = ({ resolvedPath })
{mdxContent} + +
diff --git a/packages/ui/app/src/custom-docs-page/Feedback.tsx b/packages/ui/app/src/custom-docs-page/Feedback.tsx new file mode 100644 index 0000000000..a8d0e05773 --- /dev/null +++ b/packages/ui/app/src/custom-docs-page/Feedback.tsx @@ -0,0 +1,83 @@ +import { FC, useRef, useState } from "react"; +import { capturePosthogEvent } from "../analytics/posthog"; +import { FernButton } from "../components/FernButton"; +import { FernCollapse } from "../components/FernCollapse"; + +interface FeedbackProps {} + +export const Feedback: FC = () => { + const [sent, setSent] = useState(false); + const [feedback, setFeedback] = useState<"yes" | "no" | null>(null); + const [showFeedbackInput, setShowFeedbackInput] = useState(false); + const textareaRef = useRef(null); + const handleYes = () => { + setFeedback("yes"); + setShowFeedbackInput(true); + textareaRef.current?.focus(); + capturePosthogEvent("feedback_voted", { + satisfied: true, + }); + }; + const handleNo = () => { + setFeedback("no"); + setShowFeedbackInput(true); + textareaRef.current?.focus(); + capturePosthogEvent("feedback_voted", { + satisfied: false, + }); + }; + const handleSubmitFeedback = () => { + capturePosthogEvent("feedback_submitted", { + satisfied: feedback === "yes" ? true : false, + message: textareaRef.current?.value, + }); + setSent(true); + }; + return ( +
+ {!sent ? ( +
+ Did this page help you? +
+ + Yes + + + No + +
+
+ ) : ( +
+
Thank you for your feedback!
+
+ )} + {!sent && ( + +
+