diff --git a/package-lock.json b/package-lock.json index 8e1099e9a5bd3b2..9431c067c969538 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@codingheads/sticky-header": "1.0.2", "@expressive-code/plugin-collapsible-sections": "0.38.3", "@iarna/toml": "2.2.5", - "@iconify-json/material-symbols": "1.2.13", + "@marsidev/react-turnstile": "1.1.0", "@stoplight/json-schema-tree": "4.0.0", "@types/hast": "3.0.4", "@types/he": "1.2.3", @@ -62,6 +62,7 @@ "puppeteer": "24.1.1", "react": "19.0.0", "react-dom": "19.0.0", + "react-icons": "5.4.0", "react-markdown": "9.0.3", "redirects-in-workers": "0.0.5", "rehype": "13.0.2", @@ -3258,16 +3259,6 @@ "dev": true, "license": "ISC" }, - "node_modules/@iconify-json/material-symbols": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@iconify-json/material-symbols/-/material-symbols-1.2.13.tgz", - "integrity": "sha512-7sVem5paCT87e1Hvk9tA2CHcmTSCwlJj6UlhouyNfgAqoC0W/Yj2vA9NFOdjviHgvoHT9kDCEfKxT5tpEMH6qA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@iconify/types": "*" - } - }, "node_modules/@iconify/tools": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/@iconify/tools/-/tools-4.1.1.tgz", @@ -3824,6 +3815,17 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@marsidev/react-turnstile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@marsidev/react-turnstile/-/react-turnstile-1.1.0.tgz", + "integrity": "sha512-X7bP9ZYutDd+E+klPYF+/BJHqEyyVkN4KKmZcNRr84zs3DcMoftlMAuoKqNSnqg0HE7NQ1844+TLFSJoztCdSA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": "^17.0.2 || ^18.0.0 || ^19.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0" + } + }, "node_modules/@mdx-js/mdx": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", @@ -16659,6 +16661,16 @@ "react": "^19.0.0" } }, + "node_modules/react-icons": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz", + "integrity": "sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/package.json b/package.json index 7ebcc4e85c54b4f..f619253b513cfb9 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@codingheads/sticky-header": "1.0.2", "@expressive-code/plugin-collapsible-sections": "0.38.3", "@iarna/toml": "2.2.5", - "@iconify-json/material-symbols": "1.2.13", + "@marsidev/react-turnstile": "1.1.0", "@stoplight/json-schema-tree": "4.0.0", "@types/hast": "3.0.4", "@types/he": "1.2.3", @@ -80,6 +80,7 @@ "puppeteer": "24.1.1", "react": "19.0.0", "react-dom": "19.0.0", + "react-icons": "5.4.0", "react-markdown": "9.0.3", "redirects-in-workers": "0.0.5", "rehype": "13.0.2", diff --git a/src/components/FeedbackPrompt.astro b/src/components/FeedbackPrompt.astro deleted file mode 100644 index 892a5714ecbf3d6..000000000000000 --- a/src/components/FeedbackPrompt.astro +++ /dev/null @@ -1,231 +0,0 @@ ---- -import { AstroIcon } from "~/components"; ---- - - -
-

Was this helpful?

-
- - -
-
- - - - -
- - - - diff --git a/src/components/FeedbackPrompt.tsx b/src/components/FeedbackPrompt.tsx new file mode 100644 index 000000000000000..1c1b3151686eb58 --- /dev/null +++ b/src/components/FeedbackPrompt.tsx @@ -0,0 +1,134 @@ +import { useState } from "react"; +import { Turnstile } from "@marsidev/react-turnstile"; +import { MdOutlineThumbUp, MdOutlineThumbDown } from "react-icons/md"; + +type SetState = React.Dispatch>; + +const questions = { + yes: Object.entries({ + Accurate: "accurate", + "Easy to understand": "easy-to-understand", + "Solved my problem": "solved-my-problem", + "Helped me decide to use the product": + "helped-me-decide-to-use-the-product", + Other: "other-yes", + }), + no: Object.entries({ + "Hard to understand": "hard-to-understand", + "Incorrect information": "incorrect-information", + "Missing the information": "missing-the-information", + Other: "other-no", + }), +} as const; + +function Buttons({ + setTitle, + setOption, +}: { + setTitle: SetState; + setOption: SetState<"yes" | "no" | undefined>; +}) { + return ( + <> + + + + ); +} + +function Form({ + option, + setTitle, + setSubmitted, +}: { + option?: "yes" | "no"; + setTitle: SetState; + setSubmitted: SetState; +}) { + if (!option) { + return null; + } + + const [selectedReason, setSelectedReason] = useState(false); + const [passedTurnstile, setPassedTurnstile] = useState(false); + + function submit(formData: FormData) { + formData.set("option", option!); + + formData.set("page", document.location.pathname); + formData.set("referrer", document.referrer); + + fetch("https://feedback.developers.cloudflare.com", { + method: "POST", + body: formData, + }); + + setTitle("Thank you for helping improve Cloudflare's documentation!"); + setSubmitted(true); + } + + return ( +
+ {questions[option].map(([label, value]) => ( + + ))} +