Skip to content

Add interactive feedback form with API submission - #700

Draft
hdprajwal wants to merge 4 commits into
masterfrom
feat/feedback
Draft

Add interactive feedback form with API submission#700
hdprajwal wants to merge 4 commits into
masterfrom
feat/feedback

Conversation

@hdprajwal

Copy link
Copy Markdown
Contributor

Summary: This swaps the old mailto: feedback link for a real form inside the app. When someone submits, it sends the feedback to a Cloudflare Worker, which saves it in a D1 database. It can also show a Cloudflare Turnstile check to keep bots out, but only if a site key is set.

Changes

  • User experience
    • The "Feedback" button in the navbar now opens a small form instead of opening your email app. The form has a type dropdown, a message box, and Send and Cancel buttons.
    • The feedback is sent from inside the app. When it works, the form shows a "Thanks for your feedback!" message. If something goes wrong, it shows a short error right in the form.
    • The form closes when you press Escape or move to another page.
  • Logical changes
    • submitFeedback.ts posts the feedback to the worker and throws if the response is not OK. It turns rate-limit and verification errors into plain messages people can understand.
    • TurnstileWidget.tsx loads the Turnstile script once and shows the bot check, but only when a site key is set. It hands the solved token back to the form.
    • FeedbackForm.tsx was rewritten. It is now its own dialog with simple states: idle, submitting, success, and error. You can only send when the message is not empty, and when the Turnstile check is solved if one is shown.
  • Data
    • Two new env vars: VITE_FEEDBACK_API_URL for the worker URL, and an optional VITE_TURNSTILE_SITE_KEY. Both are written down in .env.example and src/vite-env.d.ts.
  • Refactors
    • Deleted getFeedbackEmailBody.ts. We no longer build an email body.
    • PageNavBar.tsx now holds the open and close state and shows the button. FeedbackForm takes an onClose prop.
    • Added ZIndex.FeedbackForm.

Out of scope/Future work: clicking outside the form does not close it yet. The Cloudflare Worker and D1 backend are in a separate change.

Test Plan and Screenshots

How to test the changes in this PR:

  1. Set VITE_FEEDBACK_API_URL and run the feedback worker locally, or point it at the deployed worker. If you want to test the bot check, also set VITE_TURNSTILE_SITE_KEY.
  2. Run npm run dev and click "Feedback" in the navbar.
  3. Pick a type, write a message, and click Send. Check that the success message shows and that the row appears in D1.
  4. With no env var set, check that the form shows the "not configured" error.
  5. With a Turnstile key set, check that Send stays off until the check is solved.
  6. Check that the form closes when you press Escape and when you go to another page.
Page/View with link Description of Changes Screenshot Before Screenshot After
Navbar, Feedback button mailto link replaced with an in-app form image image

Checklist

Summary

  • Clear description of what and why
  • Scope kept focused, follow-ups noted above
  • Set yourself as assignee

Testing

  • npm run lint
  • npm run build
  • npm run test
  • npm run dev, tried out the form by hand using the steps above
    • Add before and after screenshots to the table

Docs

  • The code is clear on its own, and I added comments for the Turnstile and submit parts and for the env vars.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Cloudflare Pages preview

Comment thread src/features/feedback/FeedbackForm.tsx Outdated
</select>
<div
role="dialog"
aria-label="Send feedback"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you rebase to use the PopupCard component?

If we need to add or modify any styles with the PopupCard we can.

Close
</HoverableButton>
</div>
);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a rule of thumb, files should be less than 100 lines long. Please refactor components into other files -- especially large inner components.


const SCRIPT_SRC = 'https://challenges.cloudflare.com/turnstile/v0/api.js';

interface TurnstileApi {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants