Add 3-photo split layout to og images

This commit is contained in:
Sam Becker 2025-09-27 22:02:19 -05:00
parent 1d0973bfd1
commit 64c4b21f75
2 changed files with 64 additions and 36 deletions

View File

@ -66,7 +66,7 @@ export default function EntityHover({
}
}, [photosCount]);
const splitLayout = photosCount === 3;
const hasSplitLayout = photosCount === 3;
const content = useMemo(() =>
<div className="relative w-full h-full">
@ -77,7 +77,7 @@ export default function EntityHover({
<PhotoMedium
key={photos[index].id}
photo={photos[index]}
className={clsx(splitLayout && index === 0 && 'row-span-2')}
className={clsx(hasSplitLayout && index === 0 && 'row-span-2')}
/>)}
</div>
{/* Placeholder grid */}
@ -93,7 +93,7 @@ export default function EntityHover({
key={index}
className={clsx(
'border-[0.5px] border-main',
splitLayout && index === 0 && 'row-span-2',
hasSplitLayout && index === 0 && 'row-span-2',
)}
/>)}
</div>
@ -137,7 +137,7 @@ export default function EntityHover({
</div>
, [
gridClass,
splitLayout,
hasSplitLayout,
photosToShow,
photos,
header,

View File

@ -26,11 +26,12 @@ export default async function ImagePhotoGrid({
{ width: NextImageSize, widthArbitrary?: undefined } |
{ width?: undefined, widthArbitrary: number }
))) {
let count = 1;
let count = photos.length;
if (photos.length >= 12) { count = 12; }
else if (photos.length >= 6) { count = 6; }
else if (photos.length >= 4) { count = 4; }
else if (photos.length >= 2) { count = 2; }
const hasSplitLayout = count === 3;
const nextImageWidth: NextImageSize = count <= 2
? width ?? 1080
@ -39,17 +40,48 @@ export default async function ImagePhotoGrid({
let rows = 1;
if (count > 12) { rows = 4; }
else if (count > 6) { rows = 3; }
else if (count > 3) { rows = 2; }
else if (count >= 3) { rows = 2; }
const imagesPerRow = count / rows;
const imagesPerRow = Math.round(count / rows);
const cellWidth = (width ?? widthArbitrary) / imagesPerRow -
(imagesPerRow - 1) * gap / (imagesPerRow);
const cellWidth = (
(width ?? widthArbitrary) / imagesPerRow -
(imagesPerRow - 1) * gap / (imagesPerRow)
);
const cellHeight= height / rows -
(rows - 1) * gap / rows;
const doOptimizedFilesExist = await doAllPhotosHaveOptimizedFiles(photos);
const renderPhoto = ({ id, url }: Photo, width: number, height: number) =>
<div
key={id}
style={{
display: 'flex',
width,
height,
overflow: 'hidden',
filter: 'saturate(1.1)',
}}
>
<img {...{
src: getOptimizedPhotoUrl({
imageUrl: url,
size: nextImageWidth,
addBypassSecret: IS_PREVIEW,
compatibilityMode: !doOptimizedFilesExist,
}),
style: {
...imageStyle,
width: '100%',
...imagePosition === 'center' && {
height: '100%',
},
objectFit: 'cover',
},
}} />
</div>;
return (
<div
style={{
@ -60,35 +92,31 @@ export default async function ImagePhotoGrid({
gap,
}}
>
{photos.slice(0, count).map(({ id, url }) =>
<div
key={id}
style={{
{hasSplitLayout
? <>
{/* Large image (L) */}
<div style={{
display: 'flex',
width: cellWidth,
height: cellHeight * 2,
}}>
{renderPhoto(photos[0], cellWidth, cellHeight * 2)}
</div>
{/* Small images (R) */}
<div style={{
display: 'flex',
flexDirection: 'column',
width: cellWidth,
height: cellHeight,
overflow: 'hidden',
filter: 'saturate(1.1)',
}}
>
<img {...{
src: getOptimizedPhotoUrl({
imageUrl: url,
size: nextImageWidth,
addBypassSecret: IS_PREVIEW,
compatibilityMode: !doOptimizedFilesExist,
}),
style: {
...imageStyle,
width: '100%',
...imagePosition === 'center' && {
height: '100%',
},
objectFit: 'cover',
},
}} />
</div>,
)}
}}>
{photos.slice(1).map(photo =>
renderPhoto(photo, cellWidth, cellHeight),
)}
</div>
</>
: photos.slice(0, count).map(photo =>
renderPhoto(photo, cellWidth, cellHeight),
)}
</div>
);
}