Files
jellybloom/src/components/ui/LetterboxdAddModal.tsx
T

98 lines
3.6 KiB
TypeScript

import { useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { X } from '../../lib/icons'
import { normaliseLetterboxdListUrl } from '../../api/letterboxd'
import { useLetterboxdLists } from '../../stores/letterboxd-lists-store'
interface Props {
open: boolean
onClose: () => void
}
export default function LetterboxdAddModal({ open, onClose }: Props) {
const add = useLetterboxdLists(s => s.add)
const [url, setUrl] = useState('')
const [error, setError] = useState<string | null>(null)
function save() {
const norm = normaliseLetterboxdListUrl(url)
if (!norm) {
setError('That doesn\'t look like a Letterboxd list URL.')
return
}
add(norm)
setUrl('')
setError(null)
onClose()
}
return (
<AnimatePresence>
{open && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.18 }}
onClick={onClose}
className="fixed inset-0 z-[80] grid place-items-center bg-black/65 backdrop-blur-sm p-6"
>
<motion.div
initial={{ y: 20, scale: 0.96 }}
animate={{ y: 0, scale: 1 }}
exit={{ y: 20, scale: 0.96 }}
transition={{ duration: 0.32, ease: [0.16, 1, 0.3, 1] }}
onClick={e => e.stopPropagation()}
className="relative w-full max-w-md rounded-2xl bg-surface ring-1 ring-border-strong shadow-[0_30px_80px_-20px_rgba(0,0,0,0.85)] p-5"
>
<button
onClick={onClose}
aria-label="Close"
className="absolute top-3 right-3 w-8 h-8 grid place-items-center rounded-full text-text-3 hover:text-text-1 hover:bg-elevated transition focus-ring"
>
<X size={14} stroke={2} />
</button>
<h2 className="text-[16px] font-semibold tracking-tight text-text-1 mb-1">
Add a Letterboxd list
</h2>
<p className="text-[12px] text-text-3 mb-4 leading-relaxed">
Paste the URL of any public Letterboxd list. We'll cross-check it against
your library so missing entries are obvious.
</p>
<input
type="url"
value={url}
onChange={e => {
setUrl(e.target.value)
if (error) setError(null)
}}
onKeyDown={e => { if (e.key === 'Enter') save() }}
placeholder="https://letterboxd.com/USER/list/SLUG/"
autoFocus
className="w-full h-10 px-3 rounded-md bg-elevated/60 ring-1 ring-border focus:ring-accent/50 outline-none text-[13px] tracking-tight"
/>
{error && (
<p className="text-[11.5px] text-red-300 mt-2">{error}</p>
)}
<div className="flex items-center justify-end gap-2 mt-5">
<button
onClick={onClose}
className="h-10 px-4 rounded-full text-[12.5px] text-text-2 hover:text-text-1 hover:bg-elevated transition focus-ring"
>
Cancel
</button>
<button
onClick={save}
disabled={!url.trim()}
className="h-10 px-5 rounded-full bg-accent text-void text-[12.5px] font-semibold tracking-tight transition disabled:opacity-40 disabled:cursor-not-allowed hover:bg-accent-hover focus-ring"
>
Add list
</button>
</div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
)
}