Description
Build a production-grade cooldown indicator system for the invoice detail page. It must poll cooldown state for the connected wallet across multiple invoices simultaneously, display an animated countdown, re-enable the pay button exactly when cooldown expires, and meet WCAG 2.1 AA accessibility standards.
Acceptance Criteria
Context
- Invoice detail page is at
src/app/invoice/[id]/page.tsx
- Use
useInterval hook — create src/hooks/useInterval.ts if it doesn't exist
- Wallet connection state is available via existing wallet context in the app
Description
Build a production-grade cooldown indicator system for the invoice detail page. It must poll cooldown state for the connected wallet across multiple invoices simultaneously, display an animated countdown, re-enable the pay button exactly when cooldown expires, and meet WCAG 2.1 AA accessibility standards.
Acceptance Criteria
src/components/CooldownBadge.tsx— acceptsexpiresAt: number | nullprop; renders animated countdown (e.g."Next payment in 4h 30m 12s") updating every second viauseIntervalexpiresAtis null or expired, component renders nothing (no layout shift)src/app/invoice/[id]/page.tsx) fetches cooldown expiry for the connected wallet on mount and after each successful paymentdisabledand hasaria-disabled="true"when cooldown is active;aria-labelupdates to include remaining timeCooldownBadgehasrole="status"andaria-live="polite"so screen readers announce updates without interruptingDeadlineEngine.getCountdownfrom the SDK (split-sdk issue Add multi-language support #9)CooldownBadge: renders countdown, clears when expired, does not re-render unnecessarily (useReact.memo)Context
src/app/invoice/[id]/page.tsxuseIntervalhook — createsrc/hooks/useInterval.tsif it doesn't exist