ai starter implementation

This commit is contained in:
Garret Patti
2026-04-12 15:39:48 -04:00
parent 0238dbda7a
commit 732e9134c3
5 changed files with 212 additions and 5 deletions

View File

@@ -11,13 +11,16 @@ interface Props {
onNext?: () => void
itemKey?: string
onTagsChanged?: () => void
onAiTag?: () => Promise<void>
}
export default function ImageLightbox({ url, name, onClose, onPrev, onNext, itemKey, onTagsChanged }: Props) {
export default function ImageLightbox({ url, name, onClose, onPrev, onNext, itemKey, onTagsChanged, onAiTag }: Props) {
const overlayRef = useRef<HTMLDivElement>(null)
const [showTags, setShowTags] = useState(
() => !!itemKey && typeof window !== 'undefined' && window.innerWidth >= 1280
)
const [aiTagging, setAiTagging] = useState(false)
const [aiTagError, setAiTagError] = useState<string | null>(null)
useEffect(() => {
const handleKey = (e: KeyboardEvent) => {
@@ -71,6 +74,43 @@ export default function ImageLightbox({ url, name, onClose, onPrev, onNext, item
🏷
</button>
)}
{onAiTag && (
<button
onClick={async (e) => {
e.stopPropagation()
setAiTagging(true)
setAiTagError(null)
try {
await onAiTag()
onTagsChanged?.()
} catch (err) {
setAiTagError(err instanceof Error ? err.message : 'AI tagging failed')
setTimeout(() => setAiTagError(null), 4000)
} finally {
setAiTagging(false)
}
}}
disabled={aiTagging}
className="w-12 h-12 rounded-full flex items-center justify-center text-sm transition-colors disabled:opacity-50"
style={{
backgroundColor: aiTagError ? '#7f1d1d' : 'var(--surface)',
color: aiTagError ? '#fca5a5' : 'var(--text-primary)',
fontSize: '1.5rem',
}}
onMouseEnter={(e) => {
if (!aiTagging && !aiTagError) (e.currentTarget as HTMLElement).style.backgroundColor = 'var(--surface-hover)'
}}
onMouseLeave={(e) => {
if (!aiTagError) (e.currentTarget as HTMLElement).style.backgroundColor = 'var(--surface)'
}}
aria-label="AI Tag this image"
title={aiTagError ?? (aiTagging ? 'Tagging…' : 'AI Tag')}
>
{aiTagging ? (
<span className="animate-spin" style={{ display: 'inline-block', fontSize: '1.2rem' }}></span>
) : '✨'}
</button>
)}
<button
onClick={onClose}
className="w-12 h-12 rounded-full flex items-center justify-center text-sm transition-colors"