Create navigation-based photo header
This commit is contained in:
parent
76c02ee015
commit
6be23effc7
@ -3,8 +3,7 @@ import { Photo, PhotoDateRange } from '.';
|
||||
import PhotoLarge from './PhotoLarge';
|
||||
import SiteGrid from '@/components/SiteGrid';
|
||||
import PhotoGrid from './PhotoGrid';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import PhotoLinks from './PhotoLinks';
|
||||
import PhotoNav from './PhotoNav';
|
||||
import TagHeader from '@/tag/TagHeader';
|
||||
import { Camera } from '@/camera';
|
||||
import CameraHeader from '@/camera/CameraHeader';
|
||||
@ -102,6 +101,24 @@ export default function PhotoDetailPage({
|
||||
dateRange={dateRange}
|
||||
/>}
|
||||
/>}
|
||||
<AnimateItems
|
||||
animateOnFirstLoadOnly
|
||||
items={[
|
||||
<SiteGrid
|
||||
key="photo-nav"
|
||||
className="mb-4"
|
||||
contentMain={<PhotoNav {...{
|
||||
photo,
|
||||
photos,
|
||||
className: 'border-t border-gray-100 pt-4',
|
||||
tag,
|
||||
camera,
|
||||
simulation,
|
||||
focal,
|
||||
}} />}
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
<AnimateItems
|
||||
className="md:mb-8"
|
||||
animateFromAppState
|
||||
@ -112,6 +129,7 @@ export default function PhotoDetailPage({
|
||||
primaryTag={tag}
|
||||
priority
|
||||
prefetchRelatedLinks
|
||||
showTitle={false}
|
||||
showCamera={!camera}
|
||||
showSimulation={!simulation}
|
||||
shouldShare={shouldShare}
|
||||
@ -134,30 +152,6 @@ export default function PhotoDetailPage({
|
||||
focal={focal}
|
||||
animateOnFirstLoadOnly
|
||||
/>}
|
||||
contentSide={<AnimateItems
|
||||
animateOnFirstLoadOnly
|
||||
type="bottom"
|
||||
items={[
|
||||
<div
|
||||
key="PhotoLinks"
|
||||
className={clsx(
|
||||
'grid grid-cols-2',
|
||||
'gap-0.5 sm:gap-1',
|
||||
'md:flex md:gap-4',
|
||||
'user-select-none',
|
||||
)}
|
||||
>
|
||||
<PhotoLinks {...{
|
||||
photo,
|
||||
photos,
|
||||
tag,
|
||||
camera,
|
||||
simulation,
|
||||
focal,
|
||||
}} />
|
||||
</div>,
|
||||
]}
|
||||
/>}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -38,11 +38,13 @@ import { useAppState } from '@/state/AppState';
|
||||
|
||||
export default function PhotoLarge({
|
||||
photo,
|
||||
className,
|
||||
primaryTag,
|
||||
priority,
|
||||
prefetch = SHOULD_PREFETCH_ALL_LINKS,
|
||||
prefetchRelatedLinks = SHOULD_PREFETCH_ALL_LINKS,
|
||||
revalidatePhoto,
|
||||
showTitle = true,
|
||||
showCamera = true,
|
||||
showSimulation = true,
|
||||
shouldShare = true,
|
||||
@ -55,11 +57,13 @@ export default function PhotoLarge({
|
||||
onVisible,
|
||||
}: {
|
||||
photo: Photo
|
||||
className?: string
|
||||
primaryTag?: string
|
||||
priority?: boolean
|
||||
prefetch?: boolean
|
||||
prefetchRelatedLinks?: boolean
|
||||
revalidatePhoto?: RevalidatePhoto
|
||||
showTitle?: boolean
|
||||
showCamera?: boolean
|
||||
showSimulation?: boolean
|
||||
shouldShare?: boolean
|
||||
@ -85,10 +89,14 @@ export default function PhotoLarge({
|
||||
|
||||
const { arePhotosMatted, isUserSignedIn } = useAppState();
|
||||
|
||||
const hasTitle = showTitle && (
|
||||
Boolean(photo.title) ||
|
||||
SHOW_PHOTO_TITLE_FALLBACK_TEXT
|
||||
);
|
||||
|
||||
const hasTitleContent =
|
||||
photo.title ||
|
||||
SHOW_PHOTO_TITLE_FALLBACK_TEXT ||
|
||||
photo.caption;
|
||||
hasTitle ||
|
||||
Boolean(photo.caption);
|
||||
|
||||
const hasMetaContent =
|
||||
showCameraContent ||
|
||||
@ -102,6 +110,7 @@ export default function PhotoLarge({
|
||||
return (
|
||||
<SiteGrid
|
||||
containerRef={ref}
|
||||
className={className}
|
||||
contentMain={
|
||||
<Link
|
||||
href={pathForPhoto({ photo })}
|
||||
@ -141,7 +150,7 @@ export default function PhotoLarge({
|
||||
{/* Meta */}
|
||||
<div className="pr-2 md:pr-0">
|
||||
<div className="md:relative flex gap-2 items-start">
|
||||
{(photo.title || SHOW_PHOTO_TITLE_FALLBACK_TEXT) &&
|
||||
{hasTitle &&
|
||||
<PhotoLink
|
||||
photo={photo}
|
||||
className="font-bold uppercase flex-grow"
|
||||
|
||||
@ -9,26 +9,33 @@ import { useAppState } from '@/state/AppState';
|
||||
import { AnimationConfig } from '@/components/AnimateItems';
|
||||
import { Camera } from '@/camera';
|
||||
import { FilmSimulation } from '@/simulation';
|
||||
import { SHOW_PHOTO_TITLE_FALLBACK_TEXT } from '@/site/config';
|
||||
import { BiChevronLeft, BiChevronRight } from 'react-icons/bi';
|
||||
import { clsx } from 'clsx/lite';
|
||||
|
||||
const LISTENER_KEYUP = 'keyup';
|
||||
|
||||
const ANIMATION_LEFT: AnimationConfig = { type: 'left', duration: 0.3 };
|
||||
const ANIMATION_RIGHT: AnimationConfig = { type: 'right', duration: 0.3 };
|
||||
|
||||
export default function PhotoLinks({
|
||||
export default function PhotoNav({
|
||||
photo,
|
||||
photos,
|
||||
className,
|
||||
tag,
|
||||
camera,
|
||||
simulation,
|
||||
focal,
|
||||
prefetch,
|
||||
}: {
|
||||
photo: Photo
|
||||
photos: Photo[]
|
||||
className?: string
|
||||
tag?: string
|
||||
camera?: Camera
|
||||
simulation?: FilmSimulation
|
||||
focal?: number
|
||||
prefetch?: boolean
|
||||
}) {
|
||||
const router = useRouter();
|
||||
|
||||
@ -94,7 +101,10 @@ export default function PhotoLinks({
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={clsx(
|
||||
'flex items-center',
|
||||
className,
|
||||
)}>
|
||||
<PhotoLink
|
||||
photo={previousPhoto}
|
||||
nextPhotoAnimation={ANIMATION_RIGHT}
|
||||
@ -105,8 +115,24 @@ export default function PhotoLinks({
|
||||
scroll={false}
|
||||
prefetch
|
||||
>
|
||||
PREV
|
||||
<span className="group inline-flex gap-1 items-center">
|
||||
<BiChevronLeft
|
||||
className={clsx(
|
||||
'text-[1.25rem] transition-transform',
|
||||
'group-hover:-translate-x-1',
|
||||
)}
|
||||
/>
|
||||
PREV
|
||||
</span>
|
||||
</PhotoLink>
|
||||
<div className="grow text-center">
|
||||
{(photo.title || SHOW_PHOTO_TITLE_FALLBACK_TEXT) &&
|
||||
<PhotoLink
|
||||
photo={photo}
|
||||
className="uppercase font-bold"
|
||||
prefetch={prefetch}
|
||||
/>}
|
||||
</div>
|
||||
<PhotoLink
|
||||
photo={nextPhoto}
|
||||
nextPhotoAnimation={ANIMATION_LEFT}
|
||||
@ -117,8 +143,16 @@ export default function PhotoLinks({
|
||||
scroll={false}
|
||||
prefetch
|
||||
>
|
||||
NEXT
|
||||
<span className="group inline-flex gap-1 items-center">
|
||||
NEXT
|
||||
<BiChevronRight
|
||||
className={clsx(
|
||||
'text-[1.25rem] transition-transform',
|
||||
'group-hover:translate-x-1',
|
||||
)}
|
||||
/>
|
||||
</span>
|
||||
</PhotoLink>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user