Feedback
openstatus-dashboard/feedbackFreeComponent
A feedback component with popover form.
Install it
npx shadcn@latest add https://template.openstatus.dev/r/feedback.jsonSource
1"use client";23import { zodResolver } from "@hookform/resolvers/zod";4import { Inbox, LoaderCircle } from "lucide-react";5import { useEffect, useState, useTransition } from "react";6import { useForm } from "react-hook-form";7import { toast } from "sonner";8import { z } from "zod";9import { Button } from "@/components/ui/button";10import {11 Form,12 FormControl,13 FormField,14 FormItem,15 FormLabel,16} from "@/components/ui/form";17import {18 Popover,19 PopoverContent,20 PopoverTrigger,21} from "@/components/ui/popover";22import { Textarea } from "@/components/ui/textarea";23import { useIsMobile } from "@/hooks/use-mobile";24import { cn } from "@/lib/utils";2526const schema = z.object({27 message: z.string().min(1),28});2930export function Feedback({31 className,32 ...props33}: React.ComponentProps<typeof Button>) {34 const [open, setOpen] = useState(false);35 const isMobile = useIsMobile();36 const form = useForm<z.infer<typeof schema>>({37 resolver: zodResolver(schema),38 defaultValues: {39 message: "",40 },41 });42 const [isSuccess, setIsSuccess] = useState(false);43 const [pending, startTransition] = useTransition();4445 const onSubmit = (values: z.infer<typeof schema>) => {46 startTransition(async () => {47 const promise = new Promise<void>((resolve) => {48 setTimeout(() => {49 setIsSuccess(true);50 resolve();51 }, 1000);52 });53 console.log(values);54 toast.promise(promise, {55 loading: "Sending feedback...",56 success: "Feedback sent!",57 error: "Failed to send feedback",58 });59 await promise;60 });61 };6263 useEffect(() => {64 if (!open && isSuccess) {65 // NOTE: the popover takes 300ms to close, so we need to wait for that66 setTimeout(() => setIsSuccess(false), 300);67 }68 }, [open, isSuccess]);6970 useEffect(() => {71 const down = (e: KeyboardEvent) => {72 if (open && (e.metaKey || e.ctrlKey) && e.key === "Enter") {73 form.handleSubmit(onSubmit)();74 }7576 const target = e.target as HTMLElement;77 const isTyping =78 target.tagName === "INPUT" ||79 target.tagName === "TEXTAREA" ||80 target.isContentEditable;8182 if (isTyping) return;8384 if (!open) {85 if (e.key === "f") {86 e.preventDefault();87 setOpen(true);88 }89 return;90 }91 };92 document.addEventListener("keydown", down);93 return () => document.removeEventListener("keydown", down);94 }, [open, form, onSubmit]);9596// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from OpenStatus Dashboard
All 6 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Action Cardaction-card | OpenStatus Dashboard | Components | Free | no deps | |
| Empty stateempty-state | OpenStatus Dashboard | Components | Free | no deps | |
| Form Cardform-card | OpenStatus Dashboard | Components | Free | 1 dep | |
| Metric Cardmetric-card | OpenStatus Dashboard | Components | Free | 2 deps | |
| Sectionsection | OpenStatus Dashboard | Components | Free | no deps |
