65 lines
1.8 KiB
TypeScript
65 lines
1.8 KiB
TypeScript
import { useRef, useState } from "react";
|
||
|
||
export function ArchitectureFigure({ source, alt }: { source: string; alt: string }) {
|
||
const dialog = useRef<HTMLDialogElement>(null);
|
||
const trigger = useRef<HTMLButtonElement>(null);
|
||
const stage = useRef<HTMLDivElement>(null);
|
||
const [originalSize, setOriginalSize] = useState(false);
|
||
|
||
function open() {
|
||
setOriginalSize(false);
|
||
dialog.current?.showModal();
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<button
|
||
ref={trigger}
|
||
className="architecture-preview"
|
||
onClick={open}
|
||
aria-label={`放大:${alt}`}
|
||
>
|
||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||
<img src={source} alt={alt} />
|
||
</button>
|
||
<dialog
|
||
ref={dialog}
|
||
className="image-lightbox"
|
||
aria-label={alt}
|
||
onClick={(event) => {
|
||
if (
|
||
event.target === dialog.current ||
|
||
event.target === stage.current
|
||
) {
|
||
dialog.current?.close();
|
||
}
|
||
}}
|
||
onClose={() => trigger.current?.focus()}
|
||
>
|
||
<button
|
||
className="image-lightbox-close"
|
||
aria-label="关闭图片"
|
||
onClick={() => dialog.current?.close()}
|
||
>
|
||
×
|
||
</button>
|
||
<div
|
||
ref={stage}
|
||
className="image-lightbox-stage"
|
||
tabIndex={0}
|
||
aria-label="图片滚动区域"
|
||
>
|
||
<button
|
||
className={`image-lightbox-picture${originalSize ? " original-size" : ""}`}
|
||
onClick={() => setOriginalSize((value) => !value)}
|
||
aria-label={originalSize ? "图片适应屏幕" : "查看图片原尺寸"}
|
||
>
|
||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||
<img src={source} alt={alt} />
|
||
</button>
|
||
</div>
|
||
</dialog>
|
||
</>
|
||
);
|
||
}
|