Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | /** * Hint — transient success/error toast notifications. * * Also exports ActionHint — singleton OverlayPanel for ActionButton * success/error feedback anchored near the triggering button. */ import {OverlayPanel, Toast} from '../../primereact/index.js'; import {useEffect, useRef} from 'react'; import {useAppStore} from '../../state/appStore.js'; export function Hint() { const toastRef = useRef<Toast>(null); const toasts = useAppStore(s => s.toasts); useEffect(() => { if (toastRef.current && toasts.length > 0) { const latest = toasts[toasts.length - 1]; toastRef.current.show({ severity: latest.severity, summary: latest.summary, detail: latest.detail, life: latest.life, }); } }, [toasts]); return ( <Toast ref={toastRef} position="top-right" /> ); } /** * ActionHint — singleton OverlayPanel for button-level feedback. * Mount once in App. ActionButton calls showHint() to display a * success/error message anchored to the button. Auto-dismisses after 2 s. */ export function ActionHint() { const hint = useAppStore(s => s.hint); const clearHint = useAppStore(s => s.clearHint); const overlayRef = useRef<OverlayPanel>(null); useEffect(() => { if (hint?.target) { overlayRef.current?.show(null, hint.target); const t = setTimeout(() => { overlayRef.current?.hide(); clearHint(); }, 2000); return () => clearTimeout(t); } else { overlayRef.current?.hide(); } }, [hint, clearHint]); return ( <OverlayPanel ref={overlayRef} style={{maxWidth: 240}} > <span className={hint?.error ? 'text-red-500' : 'text-green-500'}>{hint?.message}</span> </OverlayPanel> ); } |