🎨 Palette: [UX improvement] Auto-focus Close button in Lightbox (#104)
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
This commit is contained in:
@@ -41,9 +41,12 @@ export async function POST(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isProtected(slug, type)) {
|
if (!isProtected(slug, type)) {
|
||||||
return NextResponse.json({
|
return NextResponse.json(
|
||||||
|
{
|
||||||
error: `${type === 'subpage' ? 'Subpage' : 'Album'} is not password-protected`,
|
error: `${type === 'subpage' ? 'Subpage' : 'Album'} is not password-protected`,
|
||||||
}, { status: 400 });
|
},
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const setCookie = authenticate(slug, password, type);
|
const setCookie = authenticate(slug, password, type);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export function Lightbox({ assets, currentIndex, onClose, onNext, onPrev }: Ligh
|
|||||||
const { exifData, exifLoading, fetchExif, clearExif } = useExif();
|
const { exifData, exifLoading, fetchExif, clearExif } = useExif();
|
||||||
const [imageLoaded, setImageLoaded] = useState(false);
|
const [imageLoaded, setImageLoaded] = useState(false);
|
||||||
const overlayRef = useRef<HTMLDivElement>(null);
|
const overlayRef = useRef<HTMLDivElement>(null);
|
||||||
|
const closeBtnRef = useRef<HTMLButtonElement>(null);
|
||||||
|
|
||||||
const current = assets[currentIndex];
|
const current = assets[currentIndex];
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
@@ -40,6 +41,13 @@ export function Lightbox({ assets, currentIndex, onClose, onNext, onPrev }: Ligh
|
|||||||
setMounted(true);
|
setMounted(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Auto-focus the close button when the modal mounts
|
||||||
|
useEffect(() => {
|
||||||
|
if (mounted) {
|
||||||
|
closeBtnRef.current?.focus();
|
||||||
|
}
|
||||||
|
}, [mounted]);
|
||||||
|
|
||||||
// Reset EXIF data when switching images; refetch if panel is open
|
// Reset EXIF data when switching images; refetch if panel is open
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
clearExif();
|
clearExif();
|
||||||
@@ -109,7 +117,13 @@ export function Lightbox({ assets, currentIndex, onClose, onNext, onPrev }: Ligh
|
|||||||
aria-label="Image viewer"
|
aria-label="Image viewer"
|
||||||
>
|
>
|
||||||
{/* Close button */}
|
{/* Close button */}
|
||||||
<button className={styles.close} onClick={onClose} aria-label="Close" title="Close (Esc)">
|
<button
|
||||||
|
ref={closeBtnRef}
|
||||||
|
className={styles.close}
|
||||||
|
onClick={onClose}
|
||||||
|
aria-label="Close"
|
||||||
|
title="Close (Esc)"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ subpages:
|
|||||||
albums:
|
albums:
|
||||||
- 55555555-5555-5555-5555-555555555555
|
- 55555555-5555-5555-5555-555555555555
|
||||||
- 66666666-6666-6666-6666-666666666666:
|
- 66666666-6666-6666-6666-666666666666:
|
||||||
title: "Private Highlights"
|
title: 'Private Highlights'
|
||||||
password: "album-secret-123" # Optional: album-level protection
|
password: 'album-secret-123' # Optional: album-level protection
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, you can use the object notation (recommended):
|
Alternatively, you can use the object notation (recommended):
|
||||||
@@ -99,7 +99,7 @@ albums:
|
|||||||
- 'album-uuid': My Title # → displays "My Title" instead
|
- 'album-uuid': My Title # → displays "My Title" instead
|
||||||
- 'album-uuid':
|
- 'album-uuid':
|
||||||
title: My Private Title
|
title: My Private Title
|
||||||
password: "secure-password" # → adds a password gate to this specific album
|
password: 'secure-password' # → adds a password gate to this specific album
|
||||||
```
|
```
|
||||||
|
|
||||||
**Full example:**
|
**Full example:**
|
||||||
|
|||||||
Reference in New Issue
Block a user