Added lightbox

This commit is contained in:
DrMint 2022-03-18 01:54:10 +01:00
parent 151ae0b126
commit f4c2e2cba5
5 changed files with 150 additions and 39 deletions

View File

@ -50,7 +50,7 @@ export function getImgSizesByQuality(
type ImgProps = { type ImgProps = {
className?: string; className?: string;
image: StrapiImage; image?: StrapiImage;
quality?: ImageQuality; quality?: ImageQuality;
alt?: ImageProps["alt"]; alt?: ImageProps["alt"];
layout?: ImageProps["layout"]; layout?: ImageProps["layout"];
@ -60,42 +60,46 @@ type ImgProps = {
}; };
export default function Img(props: ImgProps): JSX.Element { export default function Img(props: ImgProps): JSX.Element {
const imgSize = getImgSizesByQuality( if (props.image) {
props.image.width, const imgSize = getImgSizesByQuality(
props.image.height, props.image.width,
props.quality ? props.quality : ImageQuality.Small props.image.height,
); props.quality ? props.quality : ImageQuality.Small
);
if (props.rawImg) { if (props.rawImg) {
return ( return (
// eslint-disable-next-line @next/next/no-img-element // eslint-disable-next-line @next/next/no-img-element
<img <img
className={props.className} className={props.className}
src={getAssetURL( src={getAssetURL(
props.image.url, props.image.url,
props.quality ? props.quality : ImageQuality.Small props.quality ? props.quality : ImageQuality.Small
)} )}
alt={props.alt ? props.alt : props.image.alternativeText} alt={props.alt ? props.alt : props.image.alternativeText}
width={imgSize.width} width={imgSize.width}
height={imgSize.height} height={imgSize.height}
/> />
); );
} else {
return (
<Image
className={props.className}
src={getAssetURL(
props.image.url,
props.quality ? props.quality : ImageQuality.Small
)}
alt={props.alt ? props.alt : props.image.alternativeText}
width={props.layout === "fill" ? undefined : imgSize.width}
height={props.layout === "fill" ? undefined : imgSize.height}
layout={props.layout}
objectFit={props.objectFit}
priority={props.priority}
unoptimized
/>
);
}
} else { } else {
return ( return <></>;
<Image
className={props.className}
src={getAssetURL(
props.image.url,
props.quality ? props.quality : ImageQuality.Small
)}
alt={props.alt ? props.alt : props.image.alternativeText}
width={props.layout === "fill" ? undefined : imgSize.width}
height={props.layout === "fill" ? undefined : imgSize.height}
layout={props.layout}
objectFit={props.objectFit}
priority={props.priority}
unoptimized
/>
);
} }
} }

View File

@ -0,0 +1,31 @@
import { StrapiImage } from "graphql/operations-types";
import { Dispatch, SetStateAction } from "react";
import Img, { ImageQuality } from "./Img";
import Popup from "./Popup";
export type LightBoxProps = {
setState:
| Dispatch<SetStateAction<boolean>>
| Dispatch<SetStateAction<boolean | undefined>>;
state: boolean;
image?: StrapiImage;
};
export default function LightBox(props: LightBoxProps): JSX.Element {
return (
<Popup
setState={props.setState}
state={props.state}
fillViewport
hideBackground
>
<Img
className="rounded-lg"
image={props.image}
layout="fill"
objectFit="contain"
quality={ImageQuality.Large}
/>
</Popup>
);
}

View File

@ -1,4 +1,5 @@
import HorizontalLine from "components/HorizontalLine"; import HorizontalLine from "components/HorizontalLine";
import Img, { ImageQuality } from "components/Img";
import InsetBox from "components/InsetBox"; import InsetBox from "components/InsetBox";
import ToolTip from "components/ToolTip"; import ToolTip from "components/ToolTip";
import { useAppLayout } from "contexts/AppLayoutContext"; import { useAppLayout } from "contexts/AppLayoutContext";
@ -200,6 +201,43 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
); );
}, },
}, },
img: {
component: (props: {
alt: string;
src: string;
width?: number;
height?: number;
caption?: string;
name?: string;
}) => {
return (
<>
{props.src.startsWith("/uploads/") ? (
<div className="relative w-full aspect-video my-8">
<Img
image={{
__typename: "UploadFile",
alternativeText: props.alt,
url: props.src,
width: props.width || 1500,
height: props.height || 1000,
caption: props.caption || "",
name: props.name || "",
}}
layout="fill"
objectFit="contain"
quality={ImageQuality.Medium}
></Img>
</div>
) : (
<div className="grid place-content-center my-8">
<img {...props} className="max-h-[50vh] " />
</div>
)}
</>
);
},
},
}, },
}} }}
> >

View File

@ -2,12 +2,17 @@ import { Dispatch, SetStateAction } from "react";
import Button from "./Button"; import Button from "./Button";
export type PopupProps = { export type PopupProps = {
setState: Dispatch<SetStateAction<boolean | undefined>>; setState:
| Dispatch<SetStateAction<boolean>>
| Dispatch<SetStateAction<boolean | undefined>>;
state?: boolean; state?: boolean;
children: React.ReactNode; children: React.ReactNode;
fillViewport?: boolean;
hideBackground?: boolean;
}; };
export default function Popup(props: PopupProps): JSX.Element { export default function Popup(props: PopupProps): JSX.Element {
return ( return (
<div <div
className={`fixed inset-0 z-50 grid place-content-center transition-[backdrop-filter] duration-500 ${ className={`fixed inset-0 z-50 grid place-content-center transition-[backdrop-filter] duration-500 ${
@ -15,6 +20,10 @@ export default function Popup(props: PopupProps): JSX.Element {
? "[backdrop-filter:blur(2px)]" ? "[backdrop-filter:blur(2px)]"
: "pointer-events-none touch-none" : "pointer-events-none touch-none"
}`} }`}
onKeyUp={(e) => {
if (e.key.match("Escape")) props.setState(false);
}}
tabIndex={0}
> >
<div <div
className={`fixed bg-shade inset-0 transition-all duration-500 ${ className={`fixed bg-shade inset-0 transition-all duration-500 ${
@ -25,8 +34,12 @@ export default function Popup(props: PopupProps): JSX.Element {
}} }}
/> />
<div <div
className={`relative p-10 bg-light rounded-lg shadow-2xl shadow-shade grid gap-4 place-items-center transition-transform ${ className={`p-10 grid gap-4 place-items-center transition-transform ${
props.state ? "scale-100" : "scale-0" props.state ? "scale-100" : "scale-0"
} ${props.fillViewport ? "absolute inset-10 top-20" : "relative"} ${
props.hideBackground
? ""
: "bg-light rounded-lg shadow-2xl shadow-shade"
}`} }`}
> >
<Button <Button

View File

@ -7,6 +7,7 @@ import {
Enum_Componentmetadatabooks_Binding_Type, Enum_Componentmetadatabooks_Binding_Type,
Enum_Componentmetadatabooks_Page_Order, Enum_Componentmetadatabooks_Page_Order,
GetLibraryItemQuery, GetLibraryItemQuery,
StrapiImage,
} from "graphql/operations-types"; } from "graphql/operations-types";
import { import {
convertMmToInch, convertMmToInch,
@ -34,6 +35,9 @@ import { useAppLayout } from "contexts/AppLayoutContext";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import ContentTOCLine from "components/Library/ContentTOCLine"; import ContentTOCLine from "components/Library/ContentTOCLine";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { useState } from "react";
import Popup from "components/Popup";
import LightBox from "components/LightBox";
interface LibrarySlugProps extends AppStaticProps { interface LibrarySlugProps extends AppStaticProps {
item: GetLibraryItemQuery["libraryItems"]["data"][number]["attributes"]; item: GetLibraryItemQuery["libraryItems"]["data"][number]["attributes"];
@ -52,6 +56,9 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
sortContent(item.contents); sortContent(item.contents);
const [lightboxOpened, setLightboxOpened] = useState(false);
const [lightboxImage, setLightboxImage] = useState<StrapiImage>();
const subPanel = ( const subPanel = (
<SubPanel> <SubPanel>
<ReturnButton <ReturnButton
@ -104,6 +111,12 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
const contentPanel = ( const contentPanel = (
<ContentPanel width={ContentPanelWidthSizes.large}> <ContentPanel width={ContentPanelWidthSizes.large}>
<LightBox
image={lightboxImage}
setState={setLightboxOpened}
state={lightboxOpened}
/>
<ReturnButton <ReturnButton
href="/library/" href="/library/"
title={langui.library} title={langui.library}
@ -112,7 +125,15 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
className="mb-10" className="mb-10"
/> />
<div className="grid place-items-center gap-12"> <div className="grid place-items-center gap-12">
<div className="drop-shadow-shade-xl w-full h-[50vh] mobile:h-[60vh] desktop:mb-16 relative cursor-pointer"> <div
className="drop-shadow-shade-xl w-full h-[50vh] mobile:h-[60vh] desktop:mb-16 relative cursor-pointer"
onClick={() => {
if (item.thumbnail.data) {
setLightboxImage(item.thumbnail.data.attributes);
setLightboxOpened(true);
}
}}
>
{item.thumbnail.data ? ( {item.thumbnail.data ? (
<Img <Img
image={item.thumbnail.data.attributes} image={item.thumbnail.data.attributes}
@ -160,6 +181,10 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
<div <div
key={galleryItem.id} key={galleryItem.id}
className="relative aspect-square hover:scale-[1.02] transition-transform cursor-pointer" className="relative aspect-square hover:scale-[1.02] transition-transform cursor-pointer"
onClick={() => {
setLightboxImage(galleryItem.attributes);
setLightboxOpened(true);
}}
> >
<div className="bg-light absolute inset-0 rounded-lg drop-shadow-shade-md"></div> <div className="bg-light absolute inset-0 rounded-lg drop-shadow-shade-md"></div>
<Img <Img