[FIX] web: dropdown menus should not overflow viewport

Before this commit:
Dropdowns menus were overriding the positioning hook direction flip
order in order to always stay in the same axis.
But a dropdown menu has as its maximum height 70% of the viewport.
These two "rules" aren't enough to ensure the whole spectrum of
possibilities will always make the menus entirely visible on screen.
We could have chose a correctier formula (50vh - toggler height), but
this would have led to sadly short dropdown menus in many cases,
so we chose the following alternative...

After this commit:
Dropdown components are no longer overriding the positioning hook
direction flipping order option.
That way, the flipping axis is no longer enforced and therefore the
menus will have a greater spectrum of possibilities to reposition.
This has shown us that it fixes the visibility issue of the menus.
E.g. when the menu flips to a right-middle position it could take up to
100vh and still get displayed entirely.

The position hook directionFlipOrder option has also been made
unavailable as there is no use case anymore.

X-original-commit: b768d771018843d7bfa8aab2e1b2e624d088e3f6
Part-of: odoo/odoo#78261
This commit is contained in:
Bruno Boi
2021-10-13 06:03:58 +00:00
parent 9c0d5228d4
commit 44c6946c7c
2 changed files with 7 additions and 8 deletions
@@ -88,7 +88,6 @@ export class Dropdown extends Component {
const positioningOptions = {
popper: "menuRef",
position,
directionFlipOrder: { right: "rl", bottom: "bt", top: "tb", left: "lr" },
};
this.directionCaretClass = DIRECTION_CARET_CLASS[direction];
this.togglerRef = useRef("togglerRef");
@@ -9,8 +9,6 @@ import { debounce, throttle } from "../utils/timing";
* container?: HTMLElement;
* margin?: number;
* position?: Position;
* directionFlipOrder?: DirectionFlipOrder;
* variantFlipOrder?: VariantFlipOrder;
* }} Options
*
* @typedef {{
@@ -59,13 +57,15 @@ const { hooks } = owl;
const { useComponent, useExternalListener, useRef } = hooks;
const POPPER_CLASS = "o-popper-position";
/** @type DirectionFlipOrder */
const DIRECTION_FLIP_ORDER = { top: "tbrl", right: "rltb", bottom: "btrl", left: "lrbt" };
/** @type VariantFlipOrder */
const VARIANT_FLIP_ORDER = { start: "sme", middle: "mse", end: "ems" };
/** @type {Options} */
export const DEFAULTS = {
margin: 0,
position: "bottom",
directionFlipOrder: { top: "tbrl", right: "rltb", bottom: "btrl", left: "lrbt" },
variantFlipOrder: { start: "sme", middle: "mse", end: "ems" },
};
/**
@@ -82,12 +82,12 @@ export const DEFAULTS = {
* - a method returning style to apply to the popper for a given direction and variant
*/
export function computePositioning(reference, popper, options) {
const { container, margin, position, directionFlipOrder, variantFlipOrder } = options;
const { container, margin, position } = options;
// Retrieve directions and variants
const [directionKey, variantKey = "middle"] = position.split("-");
const directions = directionFlipOrder[directionKey];
const variants = variantFlipOrder[variantKey];
const directions = DIRECTION_FLIP_ORDER[directionKey];
const variants = VARIANT_FLIP_ORDER[variantKey];
// Boxes
const popBox = popper.getBoundingClientRect();