ai-agent-app / design-system /src /components /InstallPrompt.jsx
MinhTai's picture
deploy: 66c22b0
1576c24
Raw
History Blame Contribute Delete
1.96 kB
import { useState, useEffect } from 'react'
const DISMISSED_KEY = 'pwa_install_dismissed'
/**
* PWA install prompt banner (fixed bottom).
* Appears when the browser fires `beforeinstallprompt`; hidden once dismissed or installed.
*
* @example
* <InstallPrompt />
*/
export default function InstallPrompt() {
const [prompt, setPrompt] = useState(null)
const [visible, setVisible] = useState(false)
useEffect(() => {
if (localStorage.getItem(DISMISSED_KEY)) return
const handler = e => {
e.preventDefault()
setPrompt(e)
setVisible(true)
}
window.addEventListener('beforeinstallprompt', handler)
return () => window.removeEventListener('beforeinstallprompt', handler)
}, [])
function dismiss() {
setVisible(false)
localStorage.setItem(DISMISSED_KEY, '1')
}
async function install() {
if (!prompt) return
prompt.prompt()
const { outcome } = await prompt.userChoice
if (outcome === 'accepted') setVisible(false)
else dismiss()
}
if (!visible) return null
return (
<div className="fixed bottom-16 left-4 right-4 z-50 max-w-sm mx-auto glass-base border border-primary/20 rounded-2xl p-5">
<div className="flex items-center justify-between gap-3">
<div className="flex flex-col gap-0.5">
<span className="font-sans text-[13px] font-semibold text-foreground">Thêm vào màn hình chính</span>
<span className="font-sans text-[11px] text-dim">Trải nghiệm nhanh hơn, offline được</span>
</div>
<div className="flex items-center gap-2 flex-shrink-0">
<button
onClick={install}
className="px-4 py-1.5 rounded-lg font-sans text-[12px] font-bold bg-primary text-background"
>
Thêm
</button>
<button onClick={dismiss} className="text-dim hover:text-muted text-lg leading-none">×</button>
</div>
</div>
</div>
)
}