mirror of
https://github.com/immich-app/immich.git
synced 2026-03-22 11:19:37 +03:00
fix(web): combobox dropdown positioning in modals (#26707)
This commit is contained in:
@@ -180,6 +180,17 @@
|
|||||||
onSelect(selectedOption);
|
onSelect(selectedOption);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: move this combobox component into @immich/ui
|
||||||
|
// Bits UI dialogs use `contain: layout` so fixed descendants are positioned in dialog space
|
||||||
|
const getModalBounds = () => {
|
||||||
|
const modalRoot = input?.closest('[data-dialog-content]');
|
||||||
|
if (!modalRoot || !getComputedStyle(modalRoot).contain.includes('layout')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return modalRoot.getBoundingClientRect();
|
||||||
|
};
|
||||||
|
|
||||||
const calculatePosition = (boundary: DOMRect | undefined) => {
|
const calculatePosition = (boundary: DOMRect | undefined) => {
|
||||||
const visualViewport = window.visualViewport;
|
const visualViewport = window.visualViewport;
|
||||||
|
|
||||||
@@ -187,29 +198,35 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const left = boundary.left + (visualViewport?.offsetLeft || 0);
|
const modalBounds = getModalBounds();
|
||||||
const offsetTop = visualViewport?.offsetTop || 0;
|
const offsetTop = modalBounds?.top || 0;
|
||||||
|
const offsetLeft = modalBounds?.left || 0;
|
||||||
|
const rootHeight = modalBounds?.height || window.innerHeight;
|
||||||
|
|
||||||
|
const top = boundary.top - offsetTop;
|
||||||
|
const bottom = boundary.bottom - offsetTop;
|
||||||
|
const left = boundary.left - offsetLeft;
|
||||||
|
|
||||||
if (dropdownDirection === 'top') {
|
if (dropdownDirection === 'top') {
|
||||||
return {
|
return {
|
||||||
bottom: `${window.innerHeight - boundary.top - offsetTop}px`,
|
bottom: `${rootHeight - top}px`,
|
||||||
left: `${left}px`,
|
left: `${left}px`,
|
||||||
width: `${boundary.width}px`,
|
width: `${boundary.width}px`,
|
||||||
maxHeight: maxHeight(boundary.top - dropdownOffset),
|
maxHeight: maxHeight(top - dropdownOffset),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewportHeight = visualViewport?.height || 0;
|
const viewportHeight = visualViewport?.height || rootHeight;
|
||||||
const availableHeight = viewportHeight - boundary.bottom;
|
const availableHeight = modalBounds ? rootHeight - bottom : viewportHeight - boundary.bottom;
|
||||||
return {
|
return {
|
||||||
top: `${boundary.bottom + offsetTop}px`,
|
top: `${bottom}px`,
|
||||||
left: `${left}px`,
|
left: `${left}px`,
|
||||||
width: `${boundary.width}px`,
|
width: `${boundary.width}px`,
|
||||||
maxHeight: maxHeight(availableHeight - dropdownOffset),
|
maxHeight: maxHeight(availableHeight - dropdownOffset),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const maxHeight = (size: number) => `min(${size}px,18rem)`;
|
const maxHeight = (size: number) => `min(${Math.max(size, 0)}px,18rem)`;
|
||||||
|
|
||||||
const onPositionChange = () => {
|
const onPositionChange = () => {
|
||||||
if (!isOpen) {
|
if (!isOpen) {
|
||||||
|
|||||||
Reference in New Issue
Block a user