diff --git a/frontend/src/features/admin/images/GalleryPanel.tsx b/frontend/src/features/admin/images/GalleryPanel.tsx index 2eba8ce..f305ba8 100644 --- a/frontend/src/features/admin/images/GalleryPanel.tsx +++ b/frontend/src/features/admin/images/GalleryPanel.tsx @@ -1,5 +1,9 @@ +import { useEffect, useRef, useState } from 'react' import { GalleryBrowser } from './ImageGallery' +/** Нижний отступ `main` в общем каркасе (py-8): под панелью должен остаться он же. */ +const BOTTOM_GAP = 32 + /** * Отдельная страница «Галерея»: просмотр/загрузка/удаление всех изображений приложения. * @@ -7,13 +11,39 @@ import { GalleryBrowser } from './ImageGallery' * админки. Страница занимает экран и сама не прокручивается — пагинации у списка нет, а две полосы * прокрутки (внешняя и внутри сетки) мешали бы друг другу. * - * 14rem — то, что занято над панелью и под ней: шапка сайта, отступы main, заголовок админки - * и строка вкладок. Промахнуться в меньшую сторону безопасно (снизу останется зазор), в большую — - * вернётся вторая полоса прокрутки. + * Высота меряется по факту, а не вычитается константой из `100vh`: над панелью шапка сайта, + * заголовок и строка вкладок, которая на узком экране переносится. Любое подобранное число + * промахивается — либо возвращается страничная прокрутка, либо снизу зияет пустота. */ export function GalleryPanel() { + const panelRef = useRef(null) + const [height, setHeight] = useState() + + useEffect(() => { + const update = () => { + const top = panelRef.current?.getBoundingClientRect().top ?? 0 + setHeight(Math.max(320, window.innerHeight - top - BOTTOM_GAP)) + } + + update() + // Пересчитываем и на смене размера окна, и когда каркас над панелью меняет высоту + // (перенос вкладок, другой язык): ResizeObserver ловит это без опроса. + window.addEventListener('resize', update) + const observer = new ResizeObserver(update) + if (document.body) observer.observe(document.body) + + return () => { + window.removeEventListener('resize', update) + observer.disconnect() + } + }, []) + return ( -
+
)