1import { createSignal, onMount, onCleanup } from 'solid-js';23interface PasskeyToastProps {4 site: string;5 displayName: string;6 username: string;7 requestId: string;8 onSignIn: () => void;9 onDeny: () => void;10}1112const TIMEOUT_MS = 30_000;1314export function PasskeyToast(props: PasskeyToastProps) {15 const [visible, setVisible] = createSignal(false);16 const [exiting, setExiting] = createSignal(false);17 let timeoutId: number;1819 onMount(() => {20 requestAnimationFrame(() => setVisible(true));2122 timeoutId = window.setTimeout(() => {23 handleDeny();24 }, TIMEOUT_MS);25 });2627 onCleanup(() => {28 clearTimeout(timeoutId);29 });3031 function handleSignIn() {32 clearTimeout(timeoutId);33 exit(props.onSignIn);34 }3536 function handleDeny() {37 clearTimeout(timeoutId);38 exit(props.onDeny);39 }4041 function exit(callback: () => void) {42 setExiting(true);43 setTimeout(callback, 220);44 }4546 47 48 return (49 <div50 class={[51 'peach-passkey-toast',52 visible() ? 'is-visible' : '',53 exiting() ? 'is-exiting' : '',54 ].join(' ')}55 >56 <div class="peach-passkey-toast-body">57 <div class="peach-passkey-toast-icon">58 <KeyIcon />59 </div>6061 <div class="peach-passkey-toast-domain">{props.site}</div>6263 <h2 class="peach-passkey-toast-headline">64 sign in with passkey?65 </h2>6667 <div class="peach-passkey-toast-user">68 {props.displayName} · {props.username}69 </div>7071 <div class="peach-passkey-toast-countdown">72 <div73 class="peach-passkey-toast-countdown-bar"74 style={{ 'animation-duration': `${TIMEOUT_MS}ms` }}75 />76 </div>7778 <div class="peach-passkey-toast-actions">79 <button80 class="peach-passkey-toast-btn peach-passkey-toast-btn--deny"81 on:click={handleDeny}82 >83 deny84 </button>85 <button86 class="peach-passkey-toast-btn peach-passkey-toast-btn--signin"87 on:click={handleSignIn}88 >89 sign in90 </button>91 </div>92 </div>93 </div>94 );95}9697function KeyIcon() {98 return (99 <svg width="22" height="22" viewBox="0 0 22 22" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">100 <circle cx="7" cy="11" r="3.5" />101 <path d="M10.5 11h9M16.5 11v3M19.5 11v2" />102 </svg>103 );104}