Refactor GalleryPanel to dynamically adjust height and improve layout behavior
Updated the GalleryPanel component to calculate its height based on the viewport and surrounding elements, ensuring it maintains a consistent layout without causing dual scrollbars. Introduced a ResizeObserver to handle window resizing and changes in the layout, enhancing the overall user experience in the image gallery interface.
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { GalleryBrowser } from './ImageGallery'
|
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() {
|
export function GalleryPanel() {
|
||||||
|
const panelRef = useRef<HTMLDivElement>(null)
|
||||||
|
const [height, setHeight] = useState<number>()
|
||||||
|
|
||||||
|
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 (
|
return (
|
||||||
<div className="crt-panel flex h-[calc(100vh-14rem)] min-h-96 flex-col overflow-hidden rounded-md p-4">
|
<div
|
||||||
|
ref={panelRef}
|
||||||
|
style={{ height }}
|
||||||
|
className="crt-panel flex min-h-80 flex-col overflow-hidden rounded-md p-4"
|
||||||
|
>
|
||||||
<GalleryBrowser fill />
|
<GalleryBrowser fill />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user