From 13c0f6842a6bb8a99d0aa0b2fb3bd38a50782fec Mon Sep 17 00:00:00 2001 From: ArthurGamby Date: Thu, 19 Feb 2026 17:00:04 +0100 Subject: [PATCH 1/5] feat(docs): add "Was this helpful?" page feedback widget Adds a thumbs-up/thumbs-down widget at the bottom of every docs page. On thumbs-down, an optional textarea expands for free-text feedback. Stores state in localStorage to prevent duplicate submissions. Fires a PostHog event (docs:page_feedback) with path, vote, and comment. Co-authored-by: Cursor --- .../app/docs/(default)/[[...slug]]/page.tsx | 2 + apps/docs/src/components/page-feedback.tsx | 122 ++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 apps/docs/src/components/page-feedback.tsx diff --git a/apps/docs/src/app/docs/(default)/[[...slug]]/page.tsx b/apps/docs/src/app/docs/(default)/[[...slug]]/page.tsx index 1a70e9613e..e3e752d22d 100644 --- a/apps/docs/src/app/docs/(default)/[[...slug]]/page.tsx +++ b/apps/docs/src/app/docs/(default)/[[...slug]]/page.tsx @@ -13,6 +13,7 @@ import { PageLastUpdate, } from '@/components/layout/notebook/page'; import { TechArticleSchema, BreadcrumbSchema } from '@/components/structured-data'; +import { PageFeedback } from '@/components/page-feedback'; interface PageParams { slug?: string[]; @@ -68,6 +69,7 @@ export default async function Page({ /> )} + ); diff --git a/apps/docs/src/components/page-feedback.tsx b/apps/docs/src/components/page-feedback.tsx new file mode 100644 index 0000000000..4166a47170 --- /dev/null +++ b/apps/docs/src/components/page-feedback.tsx @@ -0,0 +1,122 @@ +'use client'; + +import { useState, useEffect, useCallback } from 'react'; +import { ThumbsUp, ThumbsDown, Send } from 'lucide-react'; +import { cn } from '@prisma-docs/ui/lib/cn'; +import { usePathname } from 'fumadocs-core/framework'; +import posthog from 'posthog-js'; + +type FeedbackState = 'idle' | 'upvoted' | 'downvoted' | 'submitted'; + +function getStorageKey(path: string) { + return `prisma-docs:page-feedback:${path}`; +} + +export function PageFeedback() { + const pathname = usePathname(); + const [state, setState] = useState('idle'); + const [comment, setComment] = useState(''); + const [showTextarea, setShowTextarea] = useState(false); + + useEffect(() => { + try { + const stored = localStorage.getItem(getStorageKey(pathname)); + if (stored) setState('submitted'); + } catch {} + }, [pathname]); + + const persist = useCallback( + (vote: 'up' | 'down', text?: string) => { + try { + localStorage.setItem(getStorageKey(pathname), JSON.stringify({ vote, text })); + } catch {} + posthog.capture('docs:page_feedback', { + path: pathname, + vote, + comment: text ?? null, + }); + }, + [pathname], + ); + + const handleUp = () => { + setState('submitted'); + persist('up'); + }; + + const handleDown = () => { + setState('downvoted'); + setShowTextarea(true); + }; + + const handleSubmitComment = () => { + setState('submitted'); + persist('down', comment || undefined); + }; + + if (state === 'submitted') { + return ( +
+ Thanks for your feedback! +
+ ); + } + + return ( +
+
+ + Was this page helpful? + +
+ + +
+
+ + {showTextarea && ( +
+