import { useState } from "react";
import { toggleReaction } from "~/fns/reactions";
import { useAction } from "~/hooks/use-action";
import { REACTION_CONTENTS, REACTION_EMOJI } from "~/lib/reactions";
import type { ReactionSubject, ReactionSummary } from "~/lib/reactions";
import { cn } from "~/utils/cn";
import { useDismiss } from "~/hooks/use-dismiss";
type Props = {
owner: string;
repo: string;
subjectType: ReactionSubject;
subjectId: string;
reactions: ReactionSummary[];
canReact: boolean;
};
/** Reaction pills plus an emoji picker; reusable on issues, PRs, comments, review comments and discussions. */
export function ReactionBar({ owner, repo, subjectType, subjectId, reactions, canReact }: Props) {
const [open, setOpen] = useState(false);
const toggle = useAction(toggleReaction);
const ref = useDismiss<HTMLDivElement>(open, () => setOpen(false));
const react = (content: (typeof REACTION_CONTENTS)[number]) => {
setOpen(false);
void toggle.run({ data: { owner, repo, subjectType, subjectId, content } });
};
if (!canReact && reactions.length === 0) return null;
return (
<div ref={ref} className="relative flex flex-wrap items-center gap-1.5">
{reactions.map((reaction) => (
<button
key={reaction.content}
type="button"
disabled={!canReact || toggle.pending}
onClick={() => react(reaction.content)}
aria-pressed={reaction.viewerReacted}
className={cn(
"inline-flex h-6 items-center gap-1 rounded-full border px-2 text-xs",
reaction.viewerReacted
? "border-accent-600/70 bg-accent-950 text-accent-300"