Skip to content

Commit

Permalink
fix(menu): fix for sub menu positioning (#10278)
Browse files Browse the repository at this point in the history
* fix(menu): fix for sub menu positioning

* fix(menu): missing jsdoc

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
jakubfaliszewski and kodiakhq[bot] authored Jan 4, 2022
1 parent 253af11 commit 846df76
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
5 changes: 3 additions & 2 deletions packages/react/src/components/Menu/Menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,16 @@ const Menu = function Menu({
const elementDimensions = [elementRect.width, elementRect.height];
const targetBoundaries = getTargetBoundaries();
const containerBoundaries = getContainerBoundaries();

const {
position: correctedPosition,
direction: correctedDirection,
} = getPosition(
elementDimensions,
targetBoundaries,
containerBoundaries,
preferredDirection
preferredDirection,
isRootMenu,
rootRef.current
);

setDirection(correctedDirection);
Expand Down
23 changes: 22 additions & 1 deletion packages/react/src/components/Menu/_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ export function getParentNode(node) {
return null;
}

export function getSubMenuOffset(node) {
if (node) {
const nodeStyles = getComputedStyle(node);
const spacings =
parseInt(nodeStyles.paddingTop) + parseInt(nodeStyles.paddingBottom); // styles always in px, convert to number
const elementHeight = node.firstElementChild.offsetHeight;
return elementHeight + spacings || 0;
}

return 0;
}

export function getParentMenu(el) {
if (el) {
const parentMenu = el.parentNode.closest(`ul.${prefix}--menu`);
Expand Down Expand Up @@ -129,13 +141,17 @@ function elementFits(elementDimensions, position, boundaries, axis = 'x') {
* @param {number[]} [targetBoundaries] The boundaries of the target the element should attach to: [minX, minY, maxX, maxY]
* @param {number[]} [containerBoundaries] The boundaries of the container the element should be contained in: [minX, minY, maxX, maxY]
* @param {number} [preferredDirection=1] Which direction is preferred. Either 1 (right right) or -1 (to left)
* @param {boolean} [isRootLevel] Flag that indicates if the element is on level 1 (the root level)
* @param {object} [element] The list element - used to calculate the offset of submenus
* @returns {object} The determined position and direction of the element: { position: [x, y], direction: 1 | -1 }
*/
export function getPosition(
elementDimensions,
targetBoundaries,
containerBoundaries,
preferredDirection = 1
preferredDirection = 1,
isRootLevel,
element
) {
const position = [0, 0];
let direction = preferredDirection;
Expand Down Expand Up @@ -171,6 +187,11 @@ export function getPosition(
);
if (!yFits) {
position[1] = targetBoundaries[1] - elementDimensions[1];
if (!isRootLevel && element) {
// if sub-menu and not root level, consider offset
const diff = getSubMenuOffset(element);
position[1] += diff;
}
}

return {
Expand Down

0 comments on commit 846df76

Please sign in to comment.