index.tsx raw
1 import { faviconUrl } from '@/lib/faviconUrl'
2 import { cn } from '@/lib/utils'
3 import { useContentPolicy } from '@/providers/ContentPolicyProvider'
4 import { useState } from 'react'
5
6 export function Favicon({
7 domain,
8 className,
9 fallback = null
10 }: {
11 domain: string
12 className?: string
13 fallback?: React.ReactNode
14 }) {
15 const { faviconUrlTemplate } = useContentPolicy()
16 const [loading, setLoading] = useState(true)
17 const [error, setError] = useState(false)
18 if (error) return fallback
19
20 const url = faviconUrl(faviconUrlTemplate, `https://${domain}`)
21
22 return (
23 <div className={cn('relative', className)}>
24 {loading && <div className={cn('absolute inset-0', className)}>{fallback}</div>}
25 <img
26 src={url}
27 alt={domain}
28 className={cn('absolute inset-0', loading && 'opacity-0', className)}
29 onError={() => setError(true)}
30 onLoad={() => setLoading(false)}
31 />
32 </div>
33 )
34 }
35