DEV Community

David Groechel
David Groechel

Posted on

Create A Feedback Widget for Your React App

You've created a new web app, launched successfully and acquired new users. Now what? You wonder are there bugs I'm missing? Are users enjoying the app? What features do they want added?

This is a great time to add a feedback widget to your app. In Part 1, we'll show how to create a widget in react with NextJs, react-popper, and Tailwind

Setting up our project

Step 1: Create a new NextJs app

Note: If you already have a react app you can skip to step 2

npx create-next-app -e with-tailwindcss feedback-widget

Open up the new app in your code editor, open up the pages/index.js file and delete out the contents. You should end up with:

import Head from "next/head";

export default function Home() {
  return (
    <div className="flex flex-col items-center justify-center min-h-screen py-2">
      <Head>
        <title>React Feedback Widget Example</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      Hello!
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Create feedback button

For this tutorial, we'll create a floating action button to trigger the feedback popup. This button will "float" at the bottom right of your page and will always be visible for the visitor/user to leave feedback.

Note: You can create any type of button that fits your project.

import Head from "next/head";

export default function Home() {
  return (
    <div className="flex flex-col items-center justify-center min-h-screen py-2">
      <Head>
        <title>React Feedback Widget Example</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <button
        className="absolute bottom-4 right-4 p-2 rounded-l-lg rounded-t-lg bg-blue-700 hover:bg-blue-600 shadow-md hover:shadow-lg text-white"
        type="button"
      >
        Feedback?
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

We should now have something that looks like this:

React Feedback Button

Next, we are ready to create the feedback widget.

Step 3: Install react-popper

npm i react-popper @popperjs/core

After installing, we'll need to import both usePopper and useState at the top of our component.

import { useState } from 'react';
import { usePopper } from 'react-popper';
Enter fullscreen mode Exit fullscreen mode

Next, we'll set the popper reference and element. Full Code:

import { useState } from "react";
import { usePopper } from "react-popper";
import Head from "next/head";

export default function Home() {
  const [referenceElement, setReferenceElement] = useState(null);
  const [popperElement, setPopperElement] = useState(null);
   const { styles, attributes } = usePopper(referenceElement, popperElement, {
    modifiers: [{ name: "offset", options: { offset: [10, 10] } }],
  });
  return (
    <div className="flex flex-col items-center justify-center min-h-screen py-2">
      <Head>
        <title>React Feedback Widget Example</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <button
        ref={setReferenceElement}
        className="absolute bottom-4 right-4 p-2 rounded-l-lg rounded-t-lg bg-blue-700 hover:bg-blue-600 shadow-md hover:shadow-lg text-white"
        type="button"
      >
        Feedback?
      </button>

      <div ref={setPopperElement}
style={styles.popper}
 {...attributes.popper}>
        Feedback Widget
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

We should now have both the button and popper element visible:

React Feedback Widget Example

Now let's add some styles to the popper.

Step 4: Adding styles to the widget

Right now your widget doesn't have any styleing. We'll add some styling to make it look more like a widget.

Add the classname below to the popper element:

className="bg-white p-2 rounded-md shadow-lg"

Feel free to add different styling to make it your own!

Step 5: Adding a feedback form to the widget

Now that we've created the widget, we'll need to create a form for the user to submit feedback. We want a text area where users can type their feedback, a label for the text area, and a submit button.

...
 <div
        className="bg-white p-2 rounded-md shadow-lg"
        ref={setPopperElement}
        style={styles.popper}
        {...attributes.popper}
      >
        <form>
          <label for="feedback">How can we improve?</label>
          <div className="flex flex-col space-y-2">
            <textarea
              id="feedback"
              className="p-2 h-24 w-64 border border-gray-400 rounded-md"
              type="textarea"
            ></textarea>
            <button
              className="p-2 ml-auto rounded-lg bg-blue-700 hover:bg-blue-600 shadow-md hover:shadow-lg text-white"
              type="submit"
            >
              Send Feedback
            </button>
          </div>
        </form>
      </div>
...
Enter fullscreen mode Exit fullscreen mode

Now our widget should look like this:

React feedback widget

Step 6: Showing and hiding the widget

So we have our widget but now need to hide it on button click. We'll use useState for this:

 const [showWidget, setShowWidget] = useState(false)
Enter fullscreen mode Exit fullscreen mode

The feedback button will need a click handler to show and hide the widget:

... 
 <button
        onClick={() => setShowWidget(!showWidget)}
        ref={setReferenceElement}
        className="absolute bottom-4 right-4 p-2 rounded-l-lg rounded-t-lg bg-blue-700 hover:bg-blue-600 shadow-md hover:shadow-lg text-white"
        type="button"
      >
        Feedback?
      </button>
...
Enter fullscreen mode Exit fullscreen mode

Now we'll need to conditionally show the widget when showWidget = true

      {showWidget && (
        <div
          className="bg-white p-2 rounded-md shadow-lg"
          ref={setPopperElement}
          style={styles.popper}
          {...attributes.popper}
        >
          <form>
            <label for="feedback">How can we improve?</label>
            <div className="flex flex-col space-y-2">
              <textarea
                id="feedback"
                className="p-2 h-24 w-64 border border-gray-400 rounded-md"
                type="textarea"
              ></textarea>
              <button
                className="p-2 ml-auto rounded-lg bg-blue-700 hover:bg-blue-600 shadow-md hover:shadow-lg text-white"
                type="submit"
              >
                Send Feedback
              </button>
            </div>
          </form>
        </div>
      )}
Enter fullscreen mode Exit fullscreen mode

Now we have a "functioning" feedback widget built with react, react-popper, and tailwind!

Of course you'll need to create a backend to collect feedback and save it to your database. Don't have time for that? Use SerVoice and start collecting feedback within minutes.

Full Code:

import { useState } from "react";
import { usePopper } from "react-popper";
import Head from "next/head";

export default function Home() {
  const [showWidget, setShowWidget] = useState(false);
  const [referenceElement, setReferenceElement] = useState(null);
  const [popperElement, setPopperElement] = useState(null);
  const { styles, attributes } = usePopper(referenceElement, popperElement, {
    modifiers: [{ name: "offset", options: { offset: [10, 10] } }],
  });
  return (
    <div className="flex flex-col items-center justify-center min-h-screen py-2">
      <Head>
        <title>React Feedback Widget Example</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <button
        onClick={() => setShowWidget(!showWidget)}
        ref={setReferenceElement}
        className="absolute bottom-4 right-4 p-2 rounded-l-lg rounded-t-lg bg-blue-700 hover:bg-blue-600 shadow-md hover:shadow-lg text-white"
        type="button"
      >
        Feedback?
      </button>
      {showWidget && (
        <div
          className="bg-white p-2 rounded-md shadow-lg"
          ref={setPopperElement}
          style={styles.popper}
          {...attributes.popper}
        >
          <form>
            <label for="feedback">How can we improve?</label>
            <div className="flex flex-col space-y-2">
              <textarea
                id="feedback"
                className="p-2 h-24 w-64 border border-gray-400 rounded-md"
                type="textarea"
              ></textarea>
              <button
                className="p-2 ml-auto rounded-lg bg-blue-700 hover:bg-blue-600 shadow-md hover:shadow-lg text-white"
                type="submit"
              >
                Send Feedback
              </button>
            </div>
          </form>
        </div>
      )}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Github Repo

Want a part 2 where we create a backend? Leave a comment below.

Oldest comments (2)

Collapse
 
mrpaulishaili profile image
Paul C. Ishaili

Hi, would love to explore your backend of this project with you.

Collapse
 
marcin_codes profile image
Marcin

Hi David, great article. I made a product that bootstrap your feedback widget without worrying about backend. Here is a link: happyreact.com/

It's 100% styling agnostic, so you can make experience matching your brand. It has integration next.js, docusaurus, Nuxt and much more. I could be biased but for me, it's the easiest way to build feedback widget.