delayed_button.tsx (983B)
1 import { useComputed, useSignal } from "@preact/signals"; 2 import { ComponentProps } from "preact"; 3 import { useEffect } from "preact/hooks"; 4 5 export default function DelayedButton( 6 { delay, children, ...props }: Omit<ComponentProps<"button">, "disabled"> & { 7 delay: number; 8 }, 9 ) { 10 const embargo = Date.now() + delay; 11 const countdown = useSignal(delay); 12 const disabled = useComputed(() => countdown.value > 0); 13 const content = useComputed(() => 14 disabled.value ? ` in ${countdown.value}s` : "" 15 ); 16 17 useEffect(() => { 18 const interval = setInterval(() => 19 countdown.value = Math.ceil((embargo - Date.now()) / 1000) 20 ); 21 return () => clearInterval(interval); 22 }); 23 24 return ( 25 <button 26 {...props} 27 onClick={props.href 28 ? ((event) => { 29 event.preventDefault(); 30 location.href = `${props.href}`; 31 }) 32 : undefined} 33 disabled={disabled} 34 > 35 {children} 36 {content} 37 </button> 38 ); 39 }