Image Space reservation
This commit is contained in:
parent
c1363afb55
commit
2e0b586569
1
TODO.md
1
TODO.md
|
@ -23,6 +23,7 @@
|
|||
|
||||
## Long term
|
||||
|
||||
- More data caching between the CMS and Astro
|
||||
- [Folders] Support for nameless section
|
||||
- [Scripts] Can't run the scripts using node (ts-node?)
|
||||
- [Scans] Adapt size of obi based on cover/dustjacket
|
||||
|
|
|
@ -35,6 +35,7 @@ const style = `
|
|||
sizes="100vw"
|
||||
width={width}
|
||||
height={height}
|
||||
loading="lazy"
|
||||
class="when-no-print when-js"
|
||||
/>
|
||||
<img
|
||||
|
@ -44,6 +45,7 @@ const style = `
|
|||
sizes="100vw"
|
||||
width={width}
|
||||
height={height}
|
||||
loading="lazy"
|
||||
class="when-no-print when-no-js"
|
||||
/>
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ const hasNavigation = previousImageHref || nextImageHref;
|
|||
)
|
||||
}
|
||||
|
||||
<a href={url} target="_blank">
|
||||
<a id="image-anchor" href={url} target="_blank" style=`aspect-ratio:${width}/${height};`>
|
||||
<img
|
||||
src={url}
|
||||
srcset={sizesToSrcset(sizes)}
|
||||
|
@ -132,11 +132,45 @@ const hasNavigation = previousImageHref || nextImageHref;
|
|||
visibility: hidden;
|
||||
}
|
||||
|
||||
img {
|
||||
& > a {
|
||||
&:focus-visible {
|
||||
outline: 3px solid var(--color-base-1000);
|
||||
outline-offset: unset;
|
||||
}
|
||||
|
||||
&.pressable {
|
||||
border-radius: 9999px;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
height: 2.5em;
|
||||
|
||||
display: flex;
|
||||
place-items: center;
|
||||
place-content: center;
|
||||
|
||||
& > svg {
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > #image-anchor {
|
||||
display: block;
|
||||
transition: 100ms scale;
|
||||
box-shadow: 0 5px 20px -10px var(--color-shadow);
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
scale: 102%;
|
||||
}
|
||||
|
||||
max-height: 70vh;
|
||||
|
||||
& > img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ const {
|
|||
sizes={sizesForGridLayout(250, 1.15)}
|
||||
width={thumbnail.width}
|
||||
height={thumbnail.height}
|
||||
loading="lazy"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ const { node, context } = Astro.props;
|
|||
|
||||
{
|
||||
node.children.length > 0 && (
|
||||
<p style={`text-align: ${node.format};`}>
|
||||
<p style={node.format ? `text-align: ${node.format};` : undefined}>
|
||||
{node.children.map((node) => (
|
||||
<RTNode node={node} context={context} />
|
||||
))}
|
||||
|
|
|
@ -37,7 +37,7 @@ const mediaPage = getLocalizedUrl(`/images/${id}`);
|
|||
</HeaderTitle>
|
||||
)
|
||||
}
|
||||
<a href={mediaPage}>
|
||||
<a href={mediaPage} style=`aspect-ratio: ${width}/${height};`>
|
||||
<img
|
||||
src={url}
|
||||
srcset={sizesToSrcset(sizes)}
|
||||
|
@ -53,13 +53,13 @@ const mediaPage = getLocalizedUrl(`/images/${id}`);
|
|||
{/* ------------------------------------------- CSS -------------------------------------------- */}
|
||||
|
||||
<style>
|
||||
div {
|
||||
margin-block: 4em;
|
||||
}
|
||||
|
||||
a {
|
||||
display: block;
|
||||
line-height: 0;
|
||||
box-shadow: 0 5px 20px -10px var(--color-shadow);
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
width: fit-content;
|
||||
margin-bottom: 0.5em;
|
||||
|
||||
transition-property: scale, margin-bottom;
|
||||
|
@ -75,12 +75,15 @@ const mediaPage = getLocalizedUrl(`/images/${id}`);
|
|||
outline: 3px solid var(--color-base-1000);
|
||||
outline-offset: unset;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
max-height: 70vh;
|
||||
|
||||
& > img {
|
||||
box-shadow: 0 5px 20px -10px var(--color-shadow);
|
||||
border-radius: 16px;
|
||||
|
||||
max-width: 100%;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -69,8 +69,6 @@ export type WordingKey =
|
|||
| "collectibles.bookFormat.binding.hardcover"
|
||||
| "collectibles.bookFormat.binding.readingDirection.leftToRight"
|
||||
| "collectibles.bookFormat.binding.readingDirection.rightToLeft"
|
||||
| "collectibles.gallery"
|
||||
| "collectibles.scans"
|
||||
| "collectibles.imageCount"
|
||||
| "header.topbar.settings.tooltip"
|
||||
| "collectibles.contents"
|
||||
|
@ -89,29 +87,29 @@ export type WordingKey =
|
|||
| "pages.tableOfContent.break"
|
||||
| "global.languageOverride.availableLanguages"
|
||||
| "timeline.title"
|
||||
| "timeline.eras.drakengard3"
|
||||
| "timeline.description"
|
||||
| "timeline.eras.cataclysm"
|
||||
| "timeline.eras.drakengard"
|
||||
| "timeline.eras.drakengard2"
|
||||
| "timeline.eras.drakengard3"
|
||||
| "timeline.eras.nier"
|
||||
| "timeline.eras.nierAutomata"
|
||||
| "timeline.eras.cataclysm"
|
||||
| "timeline.description"
|
||||
| "timeline.notes.title"
|
||||
| "timeline.jumpTo"
|
||||
| "timeline.notes.content"
|
||||
| "timeline.notes.title"
|
||||
| "timeline.priorCataclysmNote.title"
|
||||
| "timeline.priorCataclysmNote.content"
|
||||
| "timeline.jumpTo"
|
||||
| "timeline.year.during"
|
||||
| "timeline.eventFooter.languages"
|
||||
| "timeline.eventFooter.sources"
|
||||
| "timeline.eventFooter.languages"
|
||||
| "timeline.eventFooter.note"
|
||||
| "global.sources.typeLabel.url"
|
||||
| "global.sources.typeLabel.page"
|
||||
| "global.sources.typeLabel.collectible"
|
||||
| "global.sources.typeLabel.folder"
|
||||
| "global.sources.typeLabel.collectible.range.custom"
|
||||
| "global.sources.typeLabel.collectible.range.page"
|
||||
| "global.sources.typeLabel.collectible.range.timestamp"
|
||||
| "global.sources.typeLabel.collectible.range.custom"
|
||||
| "global.sources.typeLabel.folder"
|
||||
| "global.sources.typeLabel.page"
|
||||
| "global.sources.typeLabel.url"
|
||||
| "global.openMediaPage"
|
||||
| "global.downloadButton"
|
||||
| "global.previewTypes.video"
|
||||
|
@ -121,6 +119,8 @@ export type WordingKey =
|
|||
| "global.previewTypes.collectible"
|
||||
| "global.previewTypes.unknown"
|
||||
| "collectibles.scans.title"
|
||||
| "collectibles.gallery.title"
|
||||
| "collectibles.gallery.subtitle"
|
||||
| "collectibles.scans.subtitle"
|
||||
| "collectibles.scans.shortIndex.flapFront"
|
||||
| "collectibles.scans.shortIndex.front"
|
||||
|
@ -134,11 +134,9 @@ export type WordingKey =
|
|||
| "collectibles.scans.obi"
|
||||
| "collectibles.scans.obiInside"
|
||||
| "collectibles.scans.pages"
|
||||
| "collectibles.gallery.title"
|
||||
| "collectibles.gallery.subtitle"
|
||||
| "global.sources.typeLabel.scans"
|
||||
| "collectibles.scans.dustjacket.description"
|
||||
| "collectibles.scans.obi.description"
|
||||
| "global.sources.typeLabel.scans"
|
||||
| "global.sources.typeLabel.gallery"
|
||||
| "global.media.attributes.filename"
|
||||
| "global.media.attributes.duration"
|
||||
|
|
|
@ -26,6 +26,7 @@ const { img, name, href } = Astro.props;
|
|||
class="when-light-theme"
|
||||
alt={name}
|
||||
title={name}
|
||||
loading="lazy"
|
||||
/>
|
||||
<img
|
||||
src={img.dark.url}
|
||||
|
@ -36,6 +37,7 @@ const { img, name, href } = Astro.props;
|
|||
class="when-dark-theme"
|
||||
alt={name}
|
||||
title={name}
|
||||
loading="lazy"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
|
|
|
@ -68,7 +68,10 @@ if (updatedBy) {
|
|||
<Fragment slot="header-aside">
|
||||
{
|
||||
thumbnail && (
|
||||
<a id="thumbnail" href={getLocalizedUrl(`/images/${thumbnail.id}`)}>
|
||||
<a
|
||||
id="thumbnail"
|
||||
href={getLocalizedUrl(`/images/${thumbnail.id}`)}
|
||||
style={`aspect-ratio: ${thumbnail.width}/${thumbnail.height};`}>
|
||||
<img
|
||||
src={thumbnail.url}
|
||||
srcset={sizesToSrcset(thumbnail.sizes)}
|
||||
|
@ -166,17 +169,18 @@ if (updatedBy) {
|
|||
|
||||
#thumbnail {
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 5px 20px -10px var(--color-shadow);
|
||||
overflow: hidden;
|
||||
transition: 100ms scale;
|
||||
display: block;
|
||||
width: fit-content;
|
||||
|
||||
max-height: 80vh;
|
||||
max-width: min(35rem, 100%);
|
||||
|
||||
& > img {
|
||||
max-width: min(35rem, 100%);
|
||||
max-height: 80vh;
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 5px 20px -10px var(--color-shadow);
|
||||
}
|
||||
|
||||
@media (max-width: 1280.5px) {
|
||||
|
|
|
@ -40,7 +40,9 @@ const translation = getLocalizedMatch(translations);
|
|||
<div>
|
||||
{
|
||||
images.map(({ url, width, height, sizes }, index) => (
|
||||
<a href={getLocalizedUrl(`/collectibles/${slug}/gallery/${index}`)}>
|
||||
<a
|
||||
href={getLocalizedUrl(`/collectibles/${slug}/gallery/${index}`)}
|
||||
style={`aspect-ratio: ${width}/${height};`}>
|
||||
<img
|
||||
src={url}
|
||||
srcset={sizesToSrcset(sizes)}
|
||||
|
@ -49,6 +51,7 @@ const translation = getLocalizedMatch(translations);
|
|||
${(width / height) * 320}px`}
|
||||
width={width}
|
||||
height={height}
|
||||
loading="lazy"
|
||||
/>
|
||||
</a>
|
||||
))
|
||||
|
@ -71,18 +74,25 @@ const translation = getLocalizedMatch(translations);
|
|||
gap: 1em;
|
||||
text-align: center;
|
||||
place-items: center;
|
||||
border-radius: 16px;
|
||||
|
||||
transition: 100ms scale;
|
||||
|
||||
&:hover {
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
scale: 104%;
|
||||
}
|
||||
|
||||
& > img {
|
||||
&:focus-visible {
|
||||
outline: 3px solid var(--color-base-1000);
|
||||
outline-offset: unset;
|
||||
}
|
||||
|
||||
max-height: 320px;
|
||||
|
||||
& > img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
width: auto;
|
||||
box-shadow: 0 5px 20px -10px var(--color-shadow);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
|
|
@ -155,9 +155,11 @@ if (price) {
|
|||
<div id="images">
|
||||
{
|
||||
thumbnail && (
|
||||
<a href={getLocalizedUrl(`/images/${thumbnail.id}`)}>
|
||||
<img
|
||||
<a
|
||||
id="thumbnail"
|
||||
href={getLocalizedUrl(`/images/${thumbnail.id}`)}
|
||||
style={`aspect-ratio: ${thumbnail.width}/${thumbnail.height};`}>
|
||||
<img
|
||||
src={thumbnail.url}
|
||||
srcset={sizesToSrcset(thumbnail.sizes)}
|
||||
sizes={`(max-width: 550px) 90vw, 550px`}
|
||||
|
@ -254,8 +256,7 @@ if (price) {
|
|||
}
|
||||
}
|
||||
|
||||
& a {
|
||||
width: fit-content;
|
||||
& > #thumbnail {
|
||||
transition: 100ms scale;
|
||||
|
||||
&:hover,
|
||||
|
@ -268,12 +269,13 @@ if (price) {
|
|||
outline-offset: unset;
|
||||
}
|
||||
|
||||
& > #thumbnail {
|
||||
max-width: min(35rem, 100%);
|
||||
max-height: 80vh;
|
||||
width: auto;
|
||||
height: auto;
|
||||
max-width: min(35rem, 100%);
|
||||
|
||||
& > img {
|
||||
box-shadow: 0 5px 20px -10px var(--color-shadow);
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
---
|
||||
import { getI18n } from "src/i18n/i18n";
|
||||
import type { EndpointScanImage } from "src/shared/payload/payload-sdk";
|
||||
import { sizesToSrcset } from "src/utils/img";
|
||||
import { sizesForGridLayout, sizesToSrcset } from "src/utils/img";
|
||||
|
||||
interface Props {
|
||||
scan: EndpointScanImage;
|
||||
collectibleSlug: string;
|
||||
aspectRatio?: { width: number; height: number } | undefined;
|
||||
}
|
||||
|
||||
const {
|
||||
scan: { url, index, width, height, sizes },
|
||||
aspectRatio,
|
||||
collectibleSlug,
|
||||
} = Astro.props;
|
||||
|
||||
|
@ -18,41 +20,51 @@ const { getLocalizedUrl, formatScanIndexShort } = await getI18n(Astro.locals.cur
|
|||
|
||||
{/* ------------------------------------------- HTML ------------------------------------------- */}
|
||||
|
||||
<a href={getLocalizedUrl(`/collectibles/${collectibleSlug}/scans/${index}`)}>
|
||||
<div style={aspectRatio ? `aspect-ratio:${aspectRatio.width}/${aspectRatio.height};` : undefined}>
|
||||
<a
|
||||
href={getLocalizedUrl(`/collectibles/${collectibleSlug}/scans/${index}`)}
|
||||
style=`aspect-ratio:${width}/${height};`>
|
||||
<img
|
||||
src={url}
|
||||
srcset={sizesToSrcset(sizes)}
|
||||
sizes={`
|
||||
(max-width: ${(width / height) * 320}px) 90vw,
|
||||
${(width / height) * 320}px`}
|
||||
sizes={sizesForGridLayout(200, 1.15)}
|
||||
width={width}
|
||||
height={height}
|
||||
loading="lazy"
|
||||
/>
|
||||
</a>
|
||||
<p>{formatScanIndexShort(index)}</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* ------------------------------------------- CSS -------------------------------------------- */}
|
||||
|
||||
<style>
|
||||
a {
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1em;
|
||||
text-align: center;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
a {
|
||||
transition: 100ms scale;
|
||||
|
||||
&:hover {
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
scale: 104%;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 3px solid var(--color-base-1000);
|
||||
outline-offset: unset;
|
||||
}
|
||||
|
||||
max-height: 100%;
|
||||
|
||||
& > img {
|
||||
max-height: 320px;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
width: auto;
|
||||
aspect-ratio: auto 21/29.7;
|
||||
box-shadow: 0 5px 20px -10px var(--color-shadow);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,11 +63,29 @@ const hasOutsideObi = obi ? Object.keys(obi).some((value) => !value.includes("in
|
|||
<section>
|
||||
<h2>{t("collectibles.scans.cover")}</h2>
|
||||
<div>
|
||||
{cover.flapFront && <ScanPreview collectibleSlug={slug} scan={cover.flapFront} />}
|
||||
{cover.front && <ScanPreview collectibleSlug={slug} scan={cover.front} />}
|
||||
{cover.spine && <ScanPreview collectibleSlug={slug} scan={cover.spine} />}
|
||||
{cover.back && <ScanPreview collectibleSlug={slug} scan={cover.back} />}
|
||||
{cover.flapBack && <ScanPreview collectibleSlug={slug} scan={cover.flapBack} />}
|
||||
{cover.flapFront && (
|
||||
<ScanPreview
|
||||
aspectRatio={cover.front}
|
||||
collectibleSlug={slug}
|
||||
scan={cover.flapFront}
|
||||
/>
|
||||
)}
|
||||
{cover.front && (
|
||||
<ScanPreview aspectRatio={cover.front} collectibleSlug={slug} scan={cover.front} />
|
||||
)}
|
||||
{cover.spine && (
|
||||
<ScanPreview aspectRatio={cover.front} collectibleSlug={slug} scan={cover.spine} />
|
||||
)}
|
||||
{cover.back && (
|
||||
<ScanPreview aspectRatio={cover.front} collectibleSlug={slug} scan={cover.back} />
|
||||
)}
|
||||
{cover.flapBack && (
|
||||
<ScanPreview
|
||||
aspectRatio={cover.front}
|
||||
collectibleSlug={slug}
|
||||
scan={cover.flapBack}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
@ -76,12 +94,32 @@ const hasOutsideObi = obi ? Object.keys(obi).some((value) => !value.includes("in
|
|||
<h2>{t("collectibles.scans.coverInside")}</h2>
|
||||
<div>
|
||||
{cover.insideFlapFront && (
|
||||
<ScanPreview collectibleSlug={slug} scan={cover.insideFlapFront} />
|
||||
<ScanPreview
|
||||
aspectRatio={cover.front}
|
||||
collectibleSlug={slug}
|
||||
scan={cover.insideFlapFront}
|
||||
/>
|
||||
)}
|
||||
{cover.insideFront && (
|
||||
<ScanPreview
|
||||
aspectRatio={cover.front}
|
||||
collectibleSlug={slug}
|
||||
scan={cover.insideFront}
|
||||
/>
|
||||
)}
|
||||
{cover.insideBack && (
|
||||
<ScanPreview
|
||||
aspectRatio={cover.front}
|
||||
collectibleSlug={slug}
|
||||
scan={cover.insideBack}
|
||||
/>
|
||||
)}
|
||||
{cover.insideFront && <ScanPreview collectibleSlug={slug} scan={cover.insideFront} />}
|
||||
{cover.insideBack && <ScanPreview collectibleSlug={slug} scan={cover.insideBack} />}
|
||||
{cover.insideFlapBack && (
|
||||
<ScanPreview collectibleSlug={slug} scan={cover.insideFlapBack} />
|
||||
<ScanPreview
|
||||
aspectRatio={cover.front}
|
||||
collectibleSlug={slug}
|
||||
scan={cover.insideFlapBack}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
@ -99,13 +137,39 @@ const hasOutsideObi = obi ? Object.keys(obi).some((value) => !value.includes("in
|
|||
<p class="prose">{t("collectibles.scans.dustjacket.description")}</p>
|
||||
<div>
|
||||
{dustjacket.flapFront && (
|
||||
<ScanPreview collectibleSlug={slug} scan={dustjacket.flapFront} />
|
||||
<ScanPreview
|
||||
aspectRatio={dustjacket.front}
|
||||
collectibleSlug={slug}
|
||||
scan={dustjacket.flapFront}
|
||||
/>
|
||||
)}
|
||||
{dustjacket.front && (
|
||||
<ScanPreview
|
||||
aspectRatio={dustjacket.front}
|
||||
collectibleSlug={slug}
|
||||
scan={dustjacket.front}
|
||||
/>
|
||||
)}
|
||||
{dustjacket.spine && (
|
||||
<ScanPreview
|
||||
aspectRatio={dustjacket.front}
|
||||
collectibleSlug={slug}
|
||||
scan={dustjacket.spine}
|
||||
/>
|
||||
)}
|
||||
{dustjacket.back && (
|
||||
<ScanPreview
|
||||
aspectRatio={dustjacket.front}
|
||||
collectibleSlug={slug}
|
||||
scan={dustjacket.back}
|
||||
/>
|
||||
)}
|
||||
{dustjacket.front && <ScanPreview collectibleSlug={slug} scan={dustjacket.front} />}
|
||||
{dustjacket.spine && <ScanPreview collectibleSlug={slug} scan={dustjacket.spine} />}
|
||||
{dustjacket.back && <ScanPreview collectibleSlug={slug} scan={dustjacket.back} />}
|
||||
{dustjacket.flapBack && (
|
||||
<ScanPreview collectibleSlug={slug} scan={dustjacket.flapBack} />
|
||||
<ScanPreview
|
||||
aspectRatio={dustjacket.front}
|
||||
collectibleSlug={slug}
|
||||
scan={dustjacket.flapBack}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
@ -115,19 +179,39 @@ const hasOutsideObi = obi ? Object.keys(obi).some((value) => !value.includes("in
|
|||
<h2>{t("collectibles.scans.dustjacketInside")}</h2>
|
||||
<div>
|
||||
{dustjacket.insideFlapFront && (
|
||||
<ScanPreview collectibleSlug={slug} scan={dustjacket.insideFlapFront} />
|
||||
<ScanPreview
|
||||
aspectRatio={dustjacket.front}
|
||||
collectibleSlug={slug}
|
||||
scan={dustjacket.insideFlapFront}
|
||||
/>
|
||||
)}
|
||||
{dustjacket.insideFront && (
|
||||
<ScanPreview collectibleSlug={slug} scan={dustjacket.insideFront} />
|
||||
<ScanPreview
|
||||
aspectRatio={dustjacket.front}
|
||||
collectibleSlug={slug}
|
||||
scan={dustjacket.insideFront}
|
||||
/>
|
||||
)}
|
||||
{dustjacket.insideSpine && (
|
||||
<ScanPreview collectibleSlug={slug} scan={dustjacket.insideSpine} />
|
||||
<ScanPreview
|
||||
aspectRatio={dustjacket.front}
|
||||
collectibleSlug={slug}
|
||||
scan={dustjacket.insideSpine}
|
||||
/>
|
||||
)}
|
||||
{dustjacket.insideBack && (
|
||||
<ScanPreview collectibleSlug={slug} scan={dustjacket.insideBack} />
|
||||
<ScanPreview
|
||||
aspectRatio={dustjacket.front}
|
||||
collectibleSlug={slug}
|
||||
scan={dustjacket.insideBack}
|
||||
/>
|
||||
)}
|
||||
{dustjacket.insideFlapBack && (
|
||||
<ScanPreview collectibleSlug={slug} scan={dustjacket.insideFlapBack} />
|
||||
<ScanPreview
|
||||
aspectRatio={dustjacket.front}
|
||||
collectibleSlug={slug}
|
||||
scan={dustjacket.insideFlapBack}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
@ -144,11 +228,21 @@ const hasOutsideObi = obi ? Object.keys(obi).some((value) => !value.includes("in
|
|||
<h2>{t("collectibles.scans.obi")}</h2>
|
||||
<p class="prose">{t("collectibles.scans.obi.description")}</p>
|
||||
<div>
|
||||
{obi.flapFront && <ScanPreview collectibleSlug={slug} scan={obi.flapFront} />}
|
||||
{obi.front && <ScanPreview collectibleSlug={slug} scan={obi.front} />}
|
||||
{obi.spine && <ScanPreview collectibleSlug={slug} scan={obi.spine} />}
|
||||
{obi.back && <ScanPreview collectibleSlug={slug} scan={obi.back} />}
|
||||
{obi.flapBack && <ScanPreview collectibleSlug={slug} scan={obi.flapBack} />}
|
||||
{obi.flapFront && (
|
||||
<ScanPreview aspectRatio={obi.front} collectibleSlug={slug} scan={obi.flapFront} />
|
||||
)}
|
||||
{obi.front && (
|
||||
<ScanPreview aspectRatio={obi.front} collectibleSlug={slug} scan={obi.front} />
|
||||
)}
|
||||
{obi.spine && (
|
||||
<ScanPreview aspectRatio={obi.front} collectibleSlug={slug} scan={obi.spine} />
|
||||
)}
|
||||
{obi.back && (
|
||||
<ScanPreview aspectRatio={obi.front} collectibleSlug={slug} scan={obi.back} />
|
||||
)}
|
||||
{obi.flapBack && (
|
||||
<ScanPreview aspectRatio={obi.front} collectibleSlug={slug} scan={obi.flapBack} />
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
@ -157,13 +251,35 @@ const hasOutsideObi = obi ? Object.keys(obi).some((value) => !value.includes("in
|
|||
<h2>{t("collectibles.scans.obiInside")}</h2>
|
||||
<div>
|
||||
{obi.insideFlapFront && (
|
||||
<ScanPreview collectibleSlug={slug} scan={obi.insideFlapFront} />
|
||||
<ScanPreview
|
||||
aspectRatio={obi.front}
|
||||
collectibleSlug={slug}
|
||||
scan={obi.insideFlapFront}
|
||||
/>
|
||||
)}
|
||||
{obi.insideFront && (
|
||||
<ScanPreview
|
||||
aspectRatio={obi.front}
|
||||
collectibleSlug={slug}
|
||||
scan={obi.insideFront}
|
||||
/>
|
||||
)}
|
||||
{obi.insideSpine && (
|
||||
<ScanPreview
|
||||
aspectRatio={obi.front}
|
||||
collectibleSlug={slug}
|
||||
scan={obi.insideSpine}
|
||||
/>
|
||||
)}
|
||||
{obi.insideBack && (
|
||||
<ScanPreview aspectRatio={obi.front} collectibleSlug={slug} scan={obi.insideBack} />
|
||||
)}
|
||||
{obi.insideFront && <ScanPreview collectibleSlug={slug} scan={obi.insideFront} />}
|
||||
{obi.insideSpine && <ScanPreview collectibleSlug={slug} scan={obi.insideSpine} />}
|
||||
{obi.insideBack && <ScanPreview collectibleSlug={slug} scan={obi.insideBack} />}
|
||||
{obi.insideFlapBack && (
|
||||
<ScanPreview collectibleSlug={slug} scan={obi.insideFlapBack} />
|
||||
<ScanPreview
|
||||
aspectRatio={obi.front}
|
||||
collectibleSlug={slug}
|
||||
scan={obi.insideFlapBack}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
@ -178,7 +294,7 @@ const hasOutsideObi = obi ? Object.keys(obi).some((value) => !value.includes("in
|
|||
<h2>{t("collectibles.scans.pages")}</h2>
|
||||
<div>
|
||||
{pages.map((image) => (
|
||||
<ScanPreview collectibleSlug={slug} scan={image} />
|
||||
<ScanPreview aspectRatio={pages[0]} collectibleSlug={slug} scan={image} />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
@ -204,9 +320,10 @@ const hasOutsideObi = obi ? Object.keys(obi).some((value) => !value.includes("in
|
|||
|
||||
& > div {
|
||||
margin-top: 1em;
|
||||
display: flex;
|
||||
gap: 2em;
|
||||
flex-wrap: wrap;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
gap: 32px 16px;
|
||||
align-items: end;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -17,7 +17,7 @@ if (recorder instanceof Response) {
|
|||
return recorder;
|
||||
}
|
||||
|
||||
const { t, getLocalizedMatch } = await getI18n(Astro.locals.currentLocale);
|
||||
const { t, getLocalizedMatch, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale);
|
||||
|
||||
const { username, languages, avatar, translations } = recorder;
|
||||
|
||||
|
@ -47,6 +47,9 @@ if (languages.length > 0) {
|
|||
{
|
||||
avatar && (
|
||||
<Fragment slot="header-aside">
|
||||
<a
|
||||
href={getLocalizedUrl(`/images/${avatar.id}`)}
|
||||
style={`aspect-ratio: ${avatar.width}/${avatar.height};`}>
|
||||
<img
|
||||
src={avatar.url}
|
||||
srcset={sizesToSrcset(avatar.sizes)}
|
||||
|
@ -54,6 +57,7 @@ if (languages.length > 0) {
|
|||
width={avatar.width}
|
||||
height={avatar.height}
|
||||
/>
|
||||
</a>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
@ -80,16 +84,34 @@ if (languages.length > 0) {
|
|||
{/* ------------------------------------------- CSS -------------------------------------------- */}
|
||||
|
||||
<style>
|
||||
img {
|
||||
max-width: min(35rem, 100%);
|
||||
max-height: 50vh;
|
||||
width: auto;
|
||||
height: auto;
|
||||
a {
|
||||
display: block;
|
||||
margin-bottom: 2em;
|
||||
border-radius: 16px;
|
||||
|
||||
transition: 100ms scale;
|
||||
|
||||
@media (max-width: 1280.5px) {
|
||||
margin-top: 2em;
|
||||
}
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
scale: 102%;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 3px solid var(--color-base-1000);
|
||||
outline-offset: unset;
|
||||
}
|
||||
|
||||
max-width: min(35rem, 100%);
|
||||
max-height: 50vh;
|
||||
|
||||
& > img {
|
||||
border-radius: 16px;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
#info {
|
||||
|
|
Loading…
Reference in New Issue