<script lang="ts">
import { reactorNames, type ReactionGroup } from "#lib/components/reaction/reactions.ts";
import { formatCount } from "#lib/format.ts";
import Button from "#lib/components/ui/Button.svelte";
import Tooltip from "#lib/components/ui/Tooltip.svelte";
interface Props {
reaction: ReactionGroup;
ontoggle?: () => void; // null for loggedout users
pending?: boolean;
failed?: boolean;
onhold?: () => void;
}
let { reaction, ontoggle, pending = false, failed = false, onhold }: Props = $props();
const HOLD = 500;
let timer: ReturnType<typeof setTimeout> | undefined;
let held = false;
const release = () => {
clearTimeout(timer);
timer = undefined;
};
const onpointerdown = (event: PointerEvent) => {
held = false;
if (!onhold || event.pointerType !== "touch") return;
release();
timer = setTimeout(() => {
timer = undefined;
held = true;
onhold();
}, HOLD);
};
const onclick = () => {
if (held) {
held = false;
return;
}
ontoggle?.();
};
const title = $derived(reactorNames(reaction));
</script>
<Tooltip content="Something went wrong. Try again." disabled={!failed}>
<Button
data-testid="reactionChip"
data-kind={reaction.kind}
data-count={reaction.count}
size="small"
variant={failed ? "danger" : "default"}
{title}
disabled={pending}
aria-pressed={reaction.isReacted}
{onclick}
{onpointerdown}
onpointerup={release}
onpointercancel={release}
onpointerleave={release}
class={reaction.isReacted && !failed
? "border-background-info-emphasis/10 bg-background-info-subtle shadow-none hover:bg-background-info-subtle-hover dark:border-background-info-emphasis/30"
: "shadow-none"}
>
<span class="typography-paragraph-large leading-none">{reaction.kind}</span>
<span class="typography-paragraph-small leading-none">{formatCount(reaction.count)}</span>
</Button>
</Tooltip>