Something went wrong. Try again.
The Cavu Reader
Something went wrong. Try again.
2.4 kB · 65 lines
TSX
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566/** * "Download…" on a book overview: a small menu offering the book as * EPUB or PDF, served by the /{did}/{rkey}/download/{format} route. * Rendered only when the author has opted the book in * (page.cavu.book allowDownloads) — the caller decides; this component * just draws the menu. Plain anchors do the download so it works * without JS once the page is up, and closes on outside click/Escape. */import { useEffect, useId, useRef, useState } from 'react'
export function DownloadMenu({ did, rkey, title }: { did: string; rkey: string; title: string }) { const [open, setOpen] = useState(false) const rootRef = useRef<HTMLDivElement>(null) const menuId = useId()
useEffect(() => { if (!open) return const onPointerDown = (e: PointerEvent) => { if (!rootRef.current?.contains(e.target as Node)) setOpen(false) } const onKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false) } document.addEventListener('pointerdown', onPointerDown) document.addEventListener('keydown', onKeyDown) return () => { document.removeEventListener('pointerdown', onPointerDown) document.removeEventListener('keydown', onKeyDown) } }, [open])
const href = (format: 'epub' | 'pdf') => `/${encodeURIComponent(did)}/${encodeURIComponent(rkey)}/download/${format}`
return ( <div className="download-menu" ref={rootRef}> <button aria-controls={menuId} aria-expanded={open} aria-haspopup="menu" className="btn btn-quiet" onClick={() => setOpen((o) => !o)} type="button" > Download… </button> {open && ( <ul aria-label={`Download ${title}`} className="download-menu-list" id={menuId} role="menu"> <li role="none"> <a href={href('epub')} onClick={() => setOpen(false)} role="menuitem"> <span className="download-menu-format">EPUB</span> <span className="download-menu-hint">For e-readers and reading apps</span> </a> </li> <li role="none"> <a href={href('pdf')} onClick={() => setOpen(false)} role="menuitem"> <span className="download-menu-format">PDF</span> <span className="download-menu-hint">Printable, fixed pages</span> </a> </li> </ul> )} </div> )}