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

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 Img, { ImageQuality } from "components/Img";
import InsetBox from "components/InsetBox";
import ToolTip from "components/ToolTip";
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";
export type PopupProps = {
setState: Dispatch<SetStateAction<boolean | undefined>>;
setState:
| Dispatch<SetStateAction<boolean>>
| Dispatch<SetStateAction<boolean | undefined>>;
state?: boolean;
children: React.ReactNode;
fillViewport?: boolean;
hideBackground?: boolean;
};
export default function Popup(props: PopupProps): JSX.Element {
return (
<div
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)]"
: "pointer-events-none touch-none"
}`}
onKeyUp={(e) => {
if (e.key.match("Escape")) props.setState(false);
}}
tabIndex={0}
>
<div
className={`fixed bg-shade inset-0 transition-all duration-500 ${
@ -25,8 +34,12 @@ export default function Popup(props: PopupProps): JSX.Element {
}}
/>
<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.fillViewport ? "absolute inset-10 top-20" : "relative"} ${
props.hideBackground
? ""
: "bg-light rounded-lg shadow-2xl shadow-shade"
}`}
>
<Button

View File

@ -7,6 +7,7 @@ import {
Enum_Componentmetadatabooks_Binding_Type,
Enum_Componentmetadatabooks_Page_Order,
GetLibraryItemQuery,
StrapiImage,
} from "graphql/operations-types";
import {
convertMmToInch,
@ -34,6 +35,9 @@ import { useAppLayout } from "contexts/AppLayoutContext";
import { useRouter } from "next/router";
import ContentTOCLine from "components/Library/ContentTOCLine";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { useState } from "react";
import Popup from "components/Popup";
import LightBox from "components/LightBox";
interface LibrarySlugProps extends AppStaticProps {
item: GetLibraryItemQuery["libraryItems"]["data"][number]["attributes"];
@ -52,6 +56,9 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
sortContent(item.contents);
const [lightboxOpened, setLightboxOpened] = useState(false);
const [lightboxImage, setLightboxImage] = useState<StrapiImage>();
const subPanel = (
<SubPanel>
<ReturnButton
@ -104,6 +111,12 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
const contentPanel = (
<ContentPanel width={ContentPanelWidthSizes.large}>
<LightBox
image={lightboxImage}
setState={setLightboxOpened}
state={lightboxOpened}
/>
<ReturnButton
href="/library/"
title={langui.library}
@ -112,7 +125,15 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
className="mb-10"
/>
<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 ? (
<Img
image={item.thumbnail.data.attributes}
@ -160,6 +181,10 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
<div
key={galleryItem.id}
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>
<Img