Web: Artikelbild per Klick gross anzeigen (Lightbox)

Klick aufs Artikelbild oeffnet es bildschirmfuellend; Schliessen per Knopf, Klick auf den Hintergrund oder Escape. Neue Lightbox-Komponente (Portal an <body>), im bestehenden Farbschema.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-27 14:44:43 +02:00
parent 89d8ba4eff
commit 4887596b43
3 changed files with 65 additions and 1 deletions

View File

@@ -0,0 +1,32 @@
import { useEffect } from "react";
import { createPortal } from "react-dom";
import Icon from "./Icon";
/**
* Bildschirmfüllende Bildansicht. Schließt per Schließen-Knopf, Klick auf den
* Hintergrund oder Escape. Wird per Portal an den <body> gehängt, damit es über
* allem liegt und nicht von Containern (overflow) abgeschnitten wird.
*/
export default function Lightbox({ src, alt, onClose }) {
useEffect(() => {
function onKey(e) { if (e.key === "Escape") onClose(); }
document.addEventListener("keydown", onKey);
const vorher = document.body.style.overflow;
document.body.style.overflow = "hidden";
return () => {
document.removeEventListener("keydown", onKey);
document.body.style.overflow = vorher;
};
}, [onClose]);
return createPortal(
<div className="lightbox" onClick={onClose} role="dialog" aria-modal="true">
<button className="lightbox-close" onClick={onClose} title="Schließen" aria-label="Schließen">
<Icon name="close" size={20} />
</button>
{/* Klick aufs Bild soll nicht schließen nur der Hintergrund. */}
<img className="lightbox-img" src={src} alt={alt || ""} onClick={(e) => e.stopPropagation()} />
</div>,
document.body,
);
}

View File

@@ -1,6 +1,7 @@
import { useEffect, useRef, useState } from "react";
import { authorizedObjectUrl } from "../api";
import Icon from "./Icon";
import Lightbox from "./Lightbox";
/**
* Lädt das Artikelbild aus der eigenen Datenbank.
@@ -61,8 +62,15 @@ function useBildUrl(productId, version = 0, onLoaded) {
*/
export default function ProduktBild({ productId, alt, className = "", version = 0, onLoaded }) {
const url = useBildUrl(productId, version, onLoaded);
const [zoom, setZoom] = useState(false);
if (!url) return null;
return <img className={`produkt-bild ${className}`.trim()} src={url} alt={alt || ""} />;
return (
<>
<img className={`produkt-bild clickable ${className}`.trim()} src={url} alt={alt || ""}
title="Zum Vergrößern klicken" onClick={() => setZoom(true)} />
{zoom && <Lightbox src={url} alt={alt} onClose={() => setZoom(false)} />}
</>
);
}
/**