|
1 | 1 | 'use client'; |
2 | 2 | import { assetPath } from '../lib/site-path'; |
3 | | -import { useState } from 'react'; |
4 | | -export default function PublicationImage({ src, alt, className = '' }) { |
| 3 | +import { useRef, useState } from 'react'; |
| 4 | +import { X } from 'lucide-react'; |
| 5 | + |
| 6 | +export default function PublicationImage({ src, alt, className = '', zoomable = false }) { |
5 | 7 | const [failed, setFailed] = useState(false); |
6 | | - return src && !failed ? ( |
| 8 | + const dialog = useRef(null); |
| 9 | + if (!src || failed) { |
| 10 | + return ( |
| 11 | + <div className={`publication-cover-placeholder ${className}`}> |
| 12 | + <img src={assetPath('/uffescience-logo.png')} alt="UFF eScience" /> |
| 13 | + <span>Research and knowledge</span> |
| 14 | + </div> |
| 15 | + ); |
| 16 | + } |
| 17 | + const image = ( |
7 | 18 | <img |
8 | 19 | src={assetPath(src)} |
9 | 20 | alt={alt} |
10 | 21 | className={className} |
11 | 22 | loading="lazy" |
12 | 23 | onError={() => setFailed(true)} |
13 | 24 | /> |
14 | | - ) : ( |
15 | | - <div className={`publication-cover-placeholder ${className}`}> |
16 | | - <img src={assetPath('/uffescience-logo.png')} alt="UFF eScience" /> |
17 | | - <span>Research and knowledge</span> |
18 | | - </div> |
| 25 | + ); |
| 26 | + if (!zoomable) return image; |
| 27 | + return ( |
| 28 | + <> |
| 29 | + <button |
| 30 | + className="publication-image-open" |
| 31 | + onClick={() => dialog.current?.showModal()} |
| 32 | + aria-label={`Enlarge image: ${alt}`} |
| 33 | + > |
| 34 | + {image} |
| 35 | + </button> |
| 36 | + <dialog |
| 37 | + ref={dialog} |
| 38 | + className="publication-image-dialog" |
| 39 | + aria-label={alt} |
| 40 | + onClick={(event) => { |
| 41 | + if (event.target === event.currentTarget) dialog.current.close(); |
| 42 | + }} |
| 43 | + > |
| 44 | + <button |
| 45 | + type="button" |
| 46 | + autoFocus |
| 47 | + className="publication-image-close" |
| 48 | + onClick={() => dialog.current.close()} |
| 49 | + aria-label="Close enlarged image" |
| 50 | + > |
| 51 | + <X size={24} /> |
| 52 | + </button> |
| 53 | + <img src={assetPath(src)} alt={alt} /> |
| 54 | + <a href={assetPath(src)} target="_blank" rel="noreferrer"> |
| 55 | + Open original image |
| 56 | + </a> |
| 57 | + </dialog> |
| 58 | + </> |
19 | 59 | ); |
20 | 60 | } |
0 commit comments