Vanishing feedback button with FastAPI and hyperscript
Table of contents
Feedback is one of the most importante things when you are creating a product (probably the most important one!), so it should be easy for users to give feedback. In this post we’ll see how to implement a feedback button easily. This exact code is what I’m using at drwn.io, a little project I’m working on with a friend.
The button does the following: after you use it, it will change its text to “Thank you!”, then it will fade out we will have our backend handle the message. Let’s see it in action:
The first thing we need is an html button, it’s styled using Tailwind CSS. Notice the _="on click ..."
, this is where we will put our hyperscript
code. To use hyperscript, add this to your page’s <head>
.
(Now I’m using version 0.0.3, make sure to update it if you are reading it in the future)
<script src="https://unpkg.com/[email protected]"></script>
And now our HTML button with hyperscript:
<div
id="get-feedback-div"
class="inline-flex ml-3 transition-opacity duration-500 ease-in rounded-md shadow"
>
<button
id="get-feedback-button"
_="on click call getFeedback() then set #get-feedback-button.innerText to 'Thank you!' then wait 1000ms then toggle .opacity-0 on #get-feedback-div then wait 600ms then toggle .hidden on #get-feedback-div"
class="inline-flex items-center justify-center px-5 py-3 text-base font-medium text-blue-600 bg-white border border-transparent rounded-md hover:bg-blue-50"
>
Give us feedback
</button>
</div>
We can go step-by-step with hyperscript:
on click call getFeedback()
: when the button is clicked, execute the functiongetFeedback()
(explained later).then set #get-feedback-button.innerText to 'Thank you!'
: after that, get the element with idget-feedback-button
and change the innerText to'Thank you!'
then wait 1000ms
: self-explanatory I guessthen toggle .opacity-0 on #get-feedback-div
: toggle the CSS classopacity-0
in the element with idget-feedback-div
then wait 600ms then toggle .hidden on #get-feedback-div
: finally, wait again and toggle the classhidden
on the element
What I love about hyperscript is:
- The code is all in one place, I don’t have to go back and forth between javascript and html files
- It feels like I’m writing in a declarative language. I tell it what I want, and it does it.
Now our getFeedback()
function. It’s straightforward, use prompt()
to get a message, if the user writes something, send a JSON request to the /feedback_prompt
endpoint.
function getFeedback() {
var message = prompt("Write your message here:", "");
if (message != "") {
const data = { msg: message };
fetch("/feedback_prompt", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
.then()
.catch((error) => {
alert("There was an error sending your message, please try it later.");
});
}
}
And now our backed with FastAPI to wrap everything up. We have an endpoint that reads the message and passes it to a notify()
function. This function can be whatever you want, in my projects it’s usually sending the message to telegram, slack and/or email.
from pydantic import BaseModel
from fastapi import FastAPI
app = FastAPI()
# whatever you want to do with the feedback message
# save to the database, send to telegram, slack, email...
def notify(message: str):
return message
class FeedBackPrompData(BaseModel):
msg: str
@app.post("/feedback_prompt")
async def feedback_post(data: FeedBackPrompData):
content = f"Feeback from drwn.io:\n\n{data.msg}"
notify(content)
return
And that’s it, we now have a working full-stack system to have a feedback button.