SerVoice logo
Published on

Create A Feedback Widget for Your React App

Authors

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>
  );
}

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>
  );
}

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 @popperjavascript/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';

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>
  );
}

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>
...

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);

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>
...

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>
  );
}

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

SerVoice-Feedback-Gif

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>
  );
}

Github Repo