From 3d6c938e595aff57444695151eeedd3714f12ae9 Mon Sep 17 00:00:00 2001 From: Alex Khomenko Date: Fri, 6 Sep 2024 17:36:55 +0300 Subject: [PATCH] RolePicker: Improve overlay positioning (#92590) * RolePicker: Improve overlay positioning * Fix vertical position * More fixes --- .../core/components/RolePicker/RolePicker.tsx | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/public/app/core/components/RolePicker/RolePicker.tsx b/public/app/core/components/RolePicker/RolePicker.tsx index 3df906a381c..e94fb1009d9 100644 --- a/public/app/core/components/RolePicker/RolePicker.tsx +++ b/public/app/core/components/RolePicker/RolePicker.tsx @@ -5,7 +5,12 @@ import { Role, OrgRole } from 'app/types'; import { RolePickerInput } from './RolePickerInput'; import { RolePickerMenu } from './RolePickerMenu'; -import { MENU_MAX_HEIGHT, ROLE_PICKER_MAX_MENU_WIDTH, ROLE_PICKER_WIDTH } from './constants'; +import { + MENU_MAX_HEIGHT, + ROLE_PICKER_MAX_MENU_WIDTH, + ROLE_PICKER_MENU_MAX_WIDTH, + ROLE_PICKER_WIDTH, +} from './constants'; export interface Props { basicRole?: OrgRole; @@ -79,39 +84,38 @@ export const RolePicker = ({ return {}; } const { bottom, top, left, right } = dimensions; + + const spaceBelow = window.innerHeight - bottom; + const spaceAbove = top; + const spaceRight = window.innerWidth - right; + const spaceLeft = left; + let horizontal = left; + let vertical = bottom; let menuToLeft = false; + let menuToTop = false; - const distance = window.innerHeight - bottom; - let vertical = bottom + 5; - let ToTheSide = false; - if (distance < MENU_MAX_HEIGHT + 20) { - // move the menu above the input if there is not enough space below - vertical = top - MENU_MAX_HEIGHT - 50; - } - - // check if there is enough space above the input field - if (top < MENU_MAX_HEIGHT + 50) { - // if not, reset the vertical position - vertical = top; - // move the menu to the right edge of the input field - horizontal = right + 5; - // flag to align the menu to the right or left edge of the input field - ToTheSide = true; + // Check vertical space + if (spaceBelow < MENU_MAX_HEIGHT && spaceAbove > spaceBelow) { + vertical = top - MENU_MAX_HEIGHT; + menuToTop = true; } - /* - * This expression calculates whether there is enough place - * on the right of the RolePicker input to show/fit the role picker menu and its sub menu AND - * whether there is enough place under the RolePicker input to show/fit - * both (the role picker menu and its sub menu) aligned to the left edge of the input. - * Otherwise, it aligns the role picker menu to the right. - */ - if (horizontal + ROLE_PICKER_MAX_MENU_WIDTH > window.innerWidth) { - horizontal = window.innerWidth - (ToTheSide ? left : right); + // Check horizontal space + if (spaceRight < ROLE_PICKER_MENU_MAX_WIDTH && spaceLeft < ROLE_PICKER_MENU_MAX_WIDTH) { + horizontal = right - ROLE_PICKER_MENU_MAX_WIDTH; menuToLeft = true; + } else { + horizontal = Math.max(0, left + (dimensions.width - ROLE_PICKER_MENU_MAX_WIDTH) / 2); } + // Ensure the menu stays within the viewport + horizontal = Math.max(0, Math.min(horizontal, window.innerWidth - ROLE_PICKER_MAX_MENU_WIDTH)); + vertical = Math.max(0, Math.min(vertical, window.innerHeight - MENU_MAX_HEIGHT)); + if (menuToTop) { + // Adjust vertical position to align with the input + vertical -= 48; + } return { horizontal, vertical, menuToLeft }; };