Share gallery layout with loading skeletons and add download progress.
Keep the public gallery hero/masonry geometry stable across route and client loading, and show busy state while photos download. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
// Layout shell shared by the public gallery page (GalleryClient) and its
|
||||
// loading placeholder (GallerySkeleton). Column count, gaps, radii and
|
||||
// container padding are defined once here, so the skeleton's geometry can
|
||||
// never drift from the grid it stands in for.
|
||||
|
||||
export function GalleryHeroFrame({
|
||||
children,
|
||||
backdrop,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
/** Cover image + scrim, absolutely positioned behind the text. */
|
||||
backdrop?: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="relative bg-brand-navy overflow-hidden">
|
||||
{backdrop}
|
||||
<div className="relative container-page px-4 pt-20 pb-8 md:pt-32 md:pb-12">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function GalleryContainer({ children }: { children: React.ReactNode }) {
|
||||
return <div className="container-page px-2 sm:px-4 py-4 md:py-8">{children}</div>;
|
||||
}
|
||||
|
||||
export function MasonryGrid({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="columns-2 sm:columns-3 lg:columns-4 gap-2 md:gap-3 [column-fill:_balance]">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Per-tile geometry. Deliberately carries no background so callers can pick
|
||||
// one (photo tiles: bg-gray-100, skeleton tiles: the skeleton surface) without
|
||||
// two `bg-*` utilities fighting over CSS order.
|
||||
export const masonryTileClass = 'mb-2 md:mb-3 break-inside-avoid overflow-hidden rounded-xl';
|
||||
|
||||
/**
|
||||
* Reserves the tile's aspect ratio up front so the image can load into a box
|
||||
* that is already the right size — late arrivals never reflow the columns.
|
||||
* Returns undefined when the photo has no stored dimensions.
|
||||
*/
|
||||
export function aspectStyle(width?: number, height?: number): React.CSSProperties | undefined {
|
||||
return width && height ? { aspectRatio: `${width} / ${height}` } : undefined;
|
||||
}
|
||||
Reference in New Issue
Block a user