/** Pressable with pointer-down scale feedback. */ import { animate } from "motion"; import type { ComponentChildren, JSX } from "preact"; import { useRef } from "preact/hooks"; import { prefersReducedMotion, springs } from "../motion/springs"; type PressableProps = { children: ComponentChildren; className?: string; disabled?: boolean; onClick?: JSX.MouseEventHandler; type?: "button" | "submit"; ariaLabel?: string; ariaPressed?: boolean; }; export function Pressable({ children, className = "", disabled = false, onClick, type = "button", ariaLabel, ariaPressed, }: PressableProps) { const ref = useRef(null); const active = useRef(false); const setScale = (value: number) => { const el = ref.current; if (!el || disabled) return; if (prefersReducedMotion()) { el.style.transform = "none"; el.style.opacity = value < 1 ? "0.85" : "1"; return; } animate(el, { scale: value }, springs.press); }; const onPointerDown = (event: PointerEvent) => { if (disabled || event.button !== 0) return; active.current = true; ref.current?.setPointerCapture(event.pointerId); setScale(0.98); }; const endPress = () => { if (!active.current) return; active.current = false; setScale(1); }; return ( ); }