This component no longer exists. It was in ruixen-ui’s manifest when we first indexed it and is not there now — the registry served its inventory on 2026-08-12 and this item was not on it. The install command below will fail. It is kept here because a tutorial somewhere still tells people to run it.
Centered Feedback Drawer
ruixen-ui/centered-feedback-drawerRemovedComponent
Centered feedback panel — three SVG faces, contextual comment, spring selection, auto-dismiss thank-you state.
Live preview
live · rendered by the registry
Rendered by ruixen-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ruixen.com/r/centered-feedback-drawer.jsonSource
1"use client";23import { useRef, useState } from "react";4import { motion, AnimatePresence } from "motion/react";56/**7 * Centered Feedback Drawer — three emoji, one question.8 *9 * Not a form. Not a survey. Three faces —10 * 🙁 😐 😊 — universally understood in an instant.11 * Click one. It springs up, the others dim. A contextual12 * textarea slides in: "What went wrong?" or "What did you13 * enjoy?" — the interface reads your mood. Submit. Done.14 *15 * The faces are the interface.16 */1718/* ── Types ── */1920export interface FeedbackData {21 rating: number;22 label: string;23 message: string;24}2526export interface CenteredFeedbackDrawerProps {27 open: boolean;28 onOpenChange: (open: boolean) => void;29 onSubmit?: (feedback: FeedbackData) => void;30 sound?: boolean;31}3233/* ── Constants ── */3435const RATINGS = [36 { label: "Not great", placeholder: "What went wrong?" },37 { label: "Okay", placeholder: "What could be better?" },38 { label: "Great", placeholder: "What did you enjoy?" },39];4041/* ── Audio ── */4243let _ctx: AudioContext | null = null;44let _buf: AudioBuffer | null = null;4546function audioCtx() {47 if (!_ctx) {48 _ctx = new (window.AudioContext ||49 (window as unknown as { webkitAudioContext: typeof AudioContext })50 .webkitAudioContext)();51 }52 if (_ctx.state === "suspended") _ctx.resume();53 return _ctx;54}5556function ensureBuf(ac: AudioContext): AudioBuffer {57 if (_buf && _buf.sampleRate === ac.sampleRate) return _buf;58 const rate = ac.sampleRate;59 const len = Math.floor(rate * 0.003);60 const buf = ac.createBuffer(1, len, rate);61 const ch = buf.getChannelData(0);62 for (let i = 0; i < len; i++) {63 const t = i / len;64 ch[i] = (Math.random() * 2 - 1) * (1 - t) ** 4;65 }66 _buf = buf;67 return buf;68}6970function playTick(last: React.MutableRefObject<number>) {71 const now = performance.now();72 if (now - last.current < 80) return;73 last.current = now;74 try {75 const ac = audioCtx();76 const buf = ensureBuf(ac);77 const src = ac.createBufferSource();78 const gain = ac.createGain();79 src.buffer = buf;80 src.playbackRate.value = 1.15;81 gain.gain.value = 0.03;82 src.connect(gain);83 gain.connect(ac.destination);84 src.start();85 } catch {86 /* silent */87 }88}8990/* ── Emoji Faces ── */9192const EMOJIS = ["🙁", "😐", "😊"];9394/* ── Component ── */9596export function CenteredFeedbackDrawer({97 open,98 onOpenChange,99 onSubmit,100 sound = true,101// … truncated
What it pulls in
npm packages
