Intelligently use vertical space in sidebar

This commit is contained in:
Sam Becker 2025-03-23 18:32:58 -05:00
parent a834e07abf
commit c9fe0bdc99
3 changed files with 37 additions and 6 deletions

View File

@ -4,10 +4,11 @@ import { Photo } from '.';
import { PATH_GRID_INFERRED } from '@/app/paths';
import PhotoGridSidebar from './PhotoGridSidebar';
import PhotoGridContainer from './PhotoGridContainer';
import { useEffect } from 'react';
import { useEffect, useRef } from 'react';
import { useAppState } from '@/state/AppState';
import clsx from 'clsx/lite';
import { PhotoSetCategories } from '@/category';
import useElementHeight from '@/utility/useElementHeight';
export default function PhotoGridPage({
photos,
@ -17,6 +18,8 @@ export default function PhotoGridPage({
photos: Photo[]
photosCount: number
}) {
const ref = useRef<HTMLDivElement>(null);
const { setSelectedPhotoIds } = useAppState();
useEffect(
@ -24,6 +27,8 @@ export default function PhotoGridPage({
[setSelectedPhotoIds],
);
const containerHeight = useElementHeight(ref);
return (
<PhotoGridContainer
cacheKey={`page-${PATH_GRID_INFERRED}`}
@ -31,6 +36,7 @@ export default function PhotoGridPage({
count={photosCount}
sidebar={
<div
ref={ref}
className={clsx(
'sticky top-0 -mb-5 -mt-5',
'max-h-screen h-full',
@ -47,6 +53,7 @@ export default function PhotoGridPage({
<PhotoGridSidebar {...{
...categories,
photosCount,
containerHeight,
}}
/>
</div>

View File

@ -30,15 +30,17 @@ import {
} from '@/category';
import PhotoFocalLength from '@/focal/PhotoFocalLength';
const SIDEBAR_ITEM_MAX_COUNT = 28;
const APPROXIMATE_ITEM_HEIGHT = 34;
export default function PhotoGridSidebar({
photosCount,
photosDateRange,
containerHeight,
...categories
}: PhotoSetCategories & {
photosCount: number
photosDateRange?: PhotoDateRange
containerHeight?: number
}) {
const {
cameras,
@ -49,14 +51,18 @@ export default function PhotoGridSidebar({
focalLengths,
} = categories;
const itemsCount = getCategoriesWithItemsCount(
const categoriesCount = getCategoriesWithItemsCount(
CATEGORY_VISIBILITY,
categories,
);
const maxItemsPerCategory = Math.floor(
SIDEBAR_ITEM_MAX_COUNT / itemsCount,
);
const maxItemsPerCategory = containerHeight
? Math.max(
Math.floor(containerHeight / categoriesCount / APPROXIMATE_ITEM_HEIGHT),
// Always show at least 2 items
2,
)
: undefined;
const { start, end } = dateRangeForPhotos(undefined, photosDateRange);

View File

@ -0,0 +1,18 @@
import { useState } from 'react';
import { RefObject, useEffect } from 'react';
export default function useElementHeight(
element: RefObject<HTMLElement | null>,
) {
const [height, setHeight] = useState(element.current?.clientHeight);
useEffect(() => {
const handleResize = () => setHeight(element.current?.clientHeight);
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [element]);
return height;
}