Control for submitting user feedback.
<div class="feedback-widget" data-rating="emoji" style="--accent:#D9C8F0">
<p class="feedback-widget__prompt">How was your experience?</p>
<div class="feedback-widget__row feedback-widget__row--emoji" role="group" aria-label="Rating">
<button type="button" aria-label="Bad">😞</button>
<button type="button" aria-label="Okay">🙂</button>
<button type="button" aria-label="Great">😄</button>
</div>
<div class="feedback-widget__row feedback-widget__row--stars" role="group" aria-label="Rating">
<button type="button" aria-label="1 star">★</button>
<button type="button" aria-label="2 stars">★</button>
<button type="button" aria-label="3 stars">★</button>
<button type="button" aria-label="4 stars">★</button>
<button type="button" aria-label="5 stars">★</button>
</div>
<div class="feedback-widget__row feedback-widget__row--thumbs" role="group" aria-label="Rating">
<button type="button" aria-label="Thumbs up">👍</button>
<button type="button" aria-label="Thumbs down">👎</button>
</div>
<details class="feedback-widget__details" open>
<summary>Add a comment</summary>
<textarea class="feedback-widget__textarea" placeholder="Tell us more (optional)" rows="3"></textarea>
</details>
</div>
<style>
.feedback-widget { font: 16px/1.5 system-ui, sans-serif; color: #241430; max-width: 300px; padding: 18px; background: #FAF7F2; border: 1.5px solid #24143022; border-radius: 12px; }
.feedback-widget__prompt { margin: 0 0 12px; font-weight: 600; font-size: 14.5px; }
.feedback-widget__row { display: none; gap: 8px; margin-bottom: 14px; }
.feedback-widget[data-rating="emoji"] .feedback-widget__row--emoji,
.feedback-widget[data-rating="stars"] .feedback-widget__row--stars,
.feedback-widget[data-rating="thumbs"] .feedback-widget__row--thumbs { display: flex; }
.feedback-widget__row button { background: #fff; border: 1.5px solid #24143022; border-radius: 8px; width: 36px; height: 36px; font-size: 16px; cursor: pointer; }
.feedback-widget__row--stars button { color: #24143044; }
.feedback-widget__row button:hover, .feedback-widget__row button:focus-visible { border-color: var(--accent); outline: none; }
.feedback-widget__details summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--accent); list-style: none; }
.feedback-widget__details summary::-webkit-details-marker { display: none; }
.feedback-widget__textarea { width: 100%; box-sizing: border-box; margin-top: 8px; border: 1.5px solid #24143022; border-radius: 8px; padding: 8px 10px; font: 13.5px system-ui, sans-serif; resize: vertical; }
.feedback-widget__textarea:focus-visible { outline: 2px solid var(--accent); border-color: transparent; }
</style><div class="feedback-widget-tw max-w-[300px] p-4.5 bg-[#FAF7F2] border-[1.5px] border-[#24143022] rounded-xl font-sans text-[#241430]" data-rating="emoji" style="--accent:#D9C8F0">
<p class="m-0 mb-3 font-semibold text-sm">How was your experience?</p>
<div class="rating-row-emoji hidden gap-2 mb-3.5" role="group" aria-label="Rating">
<button type="button" class="bg-white border-[1.5px] border-[#24143022] rounded-lg w-9 h-9 text-base" aria-label="Bad">😞</button>
<button type="button" class="bg-white border-[1.5px] border-[#24143022] rounded-lg w-9 h-9 text-base" aria-label="Okay">🙂</button>
<button type="button" class="bg-white border-[1.5px] border-[#24143022] rounded-lg w-9 h-9 text-base" aria-label="Great">😄</button>
</div>
<div class="rating-row-stars hidden gap-2 mb-3.5" role="group" aria-label="Rating">
<button type="button" class="bg-white border-[1.5px] border-[#24143022] rounded-lg w-9 h-9 text-[#24143044]" aria-label="1 star">★</button>
<button type="button" class="bg-white border-[1.5px] border-[#24143022] rounded-lg w-9 h-9 text-[#24143044]" aria-label="2 stars">★</button>
<button type="button" class="bg-white border-[1.5px] border-[#24143022] rounded-lg w-9 h-9 text-[#24143044]" aria-label="3 stars">★</button>
</div>
<div class="rating-row-thumbs hidden gap-2 mb-3.5" role="group" aria-label="Rating">
<button type="button" class="bg-white border-[1.5px] border-[#24143022] rounded-lg w-9 h-9 text-base" aria-label="Thumbs up">👍</button>
<button type="button" class="bg-white border-[1.5px] border-[#24143022] rounded-lg w-9 h-9 text-base" aria-label="Thumbs down">👎</button>
</div>
<details open>
<summary class="cursor-pointer text-[13px] font-semibold list-none" style="color:#D9C8F0">Add a comment</summary>
<textarea class="w-full box-border mt-2 border-[1.5px] border-[#24143022] rounded-lg px-2.5 py-2 text-[13.5px]" placeholder="Tell us more (optional)" rows="3"></textarea>
</details>
</div>
<style>
.feedback-widget-tw[data-rating="emoji"] .rating-row-emoji,
.feedback-widget-tw[data-rating="stars"] .rating-row-stars,
.feedback-widget-tw[data-rating="thumbs"] .rating-row-thumbs { display: flex; }
.feedback-widget-tw summary::-webkit-details-marker { display: none; }
</style>import { useState } from "react";
export function FeedbackWidget({
prompt = "How was your experience?",
ratingStyle = "emoji",
placeholder = "Tell us more (optional)",
accent = "#D9C8F0",
open: initialOpen = true,
}) {
const [open, setOpen] = useState(initialOpen);
const rows = {
emoji: [["Bad", "😞"], ["Okay", "🙂"], ["Great", "😄"]],
stars: [["1 star", "★"], ["2 stars", "★"], ["3 stars", "★"], ["4 stars", "★"], ["5 stars", "★"]],
thumbs: [["Thumbs up", "👍"], ["Thumbs down", "👎"]],
}[ratingStyle] ?? [];
return (
<div style={{ fontFamily: "system-ui, sans-serif", color: "#241430", maxWidth: 300, padding: 18, background: "#FAF7F2", border: "1.5px solid #24143022", borderRadius: 12 }}>
<p style={{ margin: "0 0 12px", fontWeight: 600, fontSize: 14.5 }}>{prompt}</p>
<div role="group" aria-label="Rating" style={{ display: "flex", gap: 8, marginBottom: 14 }}>
{rows.map(([label, glyph]) => (
<button key={label} type="button" aria-label={label} style={{ background: "#fff", border: "1.5px solid #24143022", borderRadius: 8, width: 36, height: 36, fontSize: 16, cursor: "pointer" }}>{glyph}</button>
))}
</div>
<button type="button" onClick={() => setOpen((o) => !o)} style={{ background: "none", border: "none", padding: 0, cursor: "pointer", fontSize: 13, fontWeight: 600, color: accent }}>
Add a comment
</button>
{open && (
<textarea placeholder={placeholder} rows={3} style={{ width: "100%", boxSizing: "border-box", marginTop: 8, border: "1.5px solid #24143022", borderRadius: 8, padding: "8px 10px", fontSize: 13.5, resize: "vertical" }} />
)}
</div>
);
}