Make photo header animations consistent

This commit is contained in:
Sam Becker 2023-11-06 17:38:25 -06:00
parent bb1cf04218
commit f1aa761221
5 changed files with 90 additions and 93 deletions

View File

@ -1,6 +1,6 @@
import { Photo, PhotoDateRange } from '@/photo';
import { pathForCameraShare } from '@/site/paths';
import PhotoHeader from '@/photo/PhotoHeader';
import PhotoSetHeader from '@/photo/PhotoSetHeader';
import { Camera, cameraFromPhoto } from '.';
import PhotoCamera from './PhotoCamera';
import { descriptionForCameraPhotos } from './meta';
@ -20,7 +20,7 @@ export default function CameraHeader({
}) {
const camera = cameraFromPhoto(photos[0], cameraProp);
return (
<PhotoHeader
<PhotoSetHeader
entity={<PhotoCamera {...{ camera }} />}
entityVerb="Photo"
entityDescription={

View File

@ -1,59 +0,0 @@
import { cc } from '@/utility/css';
import { Photo, PhotoDateRange, dateRangeForPhotos } from '.';
import ShareButton from '@/components/ShareButton';
export default function PhotoHeader({
entity,
entityVerb,
entityDescription,
photos,
selectedPhoto,
sharePath,
count,
dateRange,
}: {
entity: JSX.Element
entityVerb: string
entityDescription: string
photos: Photo[]
selectedPhoto?: Photo
sharePath: string
count?: number
dateRange?: PhotoDateRange
}) {
const { start, end } = dateRangeForPhotos(photos, dateRange);
const selectedPhotoIndex = selectedPhoto
? photos.findIndex(photo => photo.id === selectedPhoto.id)
: undefined;
return (
<div className={cc(
'flex flex-col gap-y-0.5',
'xs:grid grid-cols-2 sm:grid-cols-4 md:grid-cols-3 lg:grid-cols-4',
)}>
{entity}
<span className={cc(
'inline-flex gap-2 items-center self-start',
'uppercase text-dim',
'sm:col-span-2 md:col-span-1 lg:col-span-2',
)}>
{selectedPhotoIndex !== undefined
// eslint-disable-next-line max-len
? `${entityVerb} ${selectedPhotoIndex + 1} of ${count ?? photos.length}`
: entityDescription}
{selectedPhotoIndex === undefined &&
<ShareButton path={sharePath} dim />}
</span>
<span className={cc(
'hidden sm:inline-block',
'text-right uppercase',
'text-dim',
)}>
{start === end
? start
: <>{start}<br /> {end}</>}
</span>
</div>
);
}

View File

@ -0,0 +1,68 @@
import { cc } from '@/utility/css';
import { Photo, PhotoDateRange, dateRangeForPhotos } from '.';
import ShareButton from '@/components/ShareButton';
import AnimateItems from '@/components/AnimateItems';
import { ReactNode } from 'react';
export default function PhotoSetHeader({
entity,
entityVerb,
entityDescription,
photos,
selectedPhoto,
sharePath,
count,
dateRange,
}: {
entity: ReactNode
entityVerb: string
entityDescription: string
photos: Photo[]
selectedPhoto?: Photo
sharePath: string
count?: number
dateRange?: PhotoDateRange
}) {
const { start, end } = dateRangeForPhotos(photos, dateRange);
const selectedPhotoIndex = selectedPhoto
? photos.findIndex(photo => photo.id === selectedPhoto.id)
: undefined;
return (
<AnimateItems
type="bottom"
distanceOffset={10}
animateOnFirstLoadOnly
items={[<div
key="PhotosHeader"
className={cc(
'flex flex-col gap-y-0.5',
'xs:grid grid-cols-2 sm:grid-cols-4 md:grid-cols-3 lg:grid-cols-4',
)}>
{entity}
<span className={cc(
'inline-flex gap-2 items-center self-start',
'uppercase text-dim',
'sm:col-span-2 md:col-span-1 lg:col-span-2',
)}>
{selectedPhotoIndex !== undefined
// eslint-disable-next-line max-len
? `${entityVerb} ${selectedPhotoIndex + 1} of ${count ?? photos.length}`
: entityDescription}
{selectedPhotoIndex === undefined &&
<ShareButton path={sharePath} dim />}
</span>
<span className={cc(
'hidden sm:inline-block',
'text-right uppercase',
'text-dim',
)}>
{start === end
? start
: <>{start}<br /> {end}</>}
</span>
</div>]}
/>
);
}

View File

@ -1,8 +1,7 @@
import { Photo, PhotoDateRange } from '@/photo';
import { FilmSimulation, descriptionForFilmSimulationPhotos } from '.';
import { pathForFilmSimulationShare } from '@/site/paths';
import PhotoHeader from '@/photo/PhotoHeader';
import AnimateItems from '@/components/AnimateItems';
import PhotoSetHeader from '@/photo/PhotoSetHeader';
import PhotoFilmSimulation from
'@/simulation/PhotoFilmSimulation';
@ -20,21 +19,16 @@ export default function FilmSimulationHeader({
dateRange?: PhotoDateRange
}) {
return (
<AnimateItems
type="bottom"
distanceOffset={10}
items={[<PhotoHeader
key="PhotoHeader"
entity={<PhotoFilmSimulation {...{ simulation }} />}
entityVerb="Photo"
entityDescription={descriptionForFilmSimulationPhotos(
photos, undefined, count, dateRange)}
photos={photos}
selectedPhoto={selectedPhoto}
sharePath={pathForFilmSimulationShare(simulation)}
count={count}
dateRange={dateRange}
/>]}
<PhotoSetHeader
entity={<PhotoFilmSimulation {...{ simulation }} />}
entityVerb="Photo"
entityDescription={descriptionForFilmSimulationPhotos(
photos, undefined, count, dateRange)}
photos={photos}
selectedPhoto={selectedPhoto}
sharePath={pathForFilmSimulationShare(simulation)}
count={count}
dateRange={dateRange}
/>
);
}

View File

@ -2,8 +2,7 @@ import { Photo } from '@/photo';
import PhotoTag from './PhotoTag';
import { descriptionForTaggedPhotos } from '.';
import { pathForTagShare } from '@/site/paths';
import PhotoHeader from '@/photo/PhotoHeader';
import AnimateItems from '@/components/AnimateItems';
import PhotoSetHeader from '@/photo/PhotoSetHeader';
export default function TagHeader({
tag,
@ -17,19 +16,14 @@ export default function TagHeader({
count?: number
}) {
return (
<AnimateItems
type="bottom"
distanceOffset={10}
items={[<PhotoHeader
key="PhotoHeader"
entity={<PhotoTag tag={tag} />}
entityVerb="Tagged"
entityDescription={descriptionForTaggedPhotos(photos, undefined, count)}
photos={photos}
selectedPhoto={selectedPhoto}
sharePath={pathForTagShare(tag)}
count={count}
/>]}
<PhotoSetHeader
entity={<PhotoTag tag={tag} />}
entityVerb="Tagged"
entityDescription={descriptionForTaggedPhotos(photos, undefined, count)}
photos={photos}
selectedPhoto={selectedPhoto}
sharePath={pathForTagShare(tag)}
count={count}
/>
);
}