Files
Spanglish/frontend/src/components/gallery/GalleryLayout.tsx
T
MichilisandCursor fa8686276d 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>
2026-08-05 22:05:33 +00:00

47 lines
1.7 KiB
TypeScript

// 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;
}