[FIX] web: various dropdown style issues
Various styling fixes. Issues were brought by odoo/odoo@3b73095302 closes odoo/odoo#74752 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
<t t-name="web.DebugMenu" owl="1">
|
||||
<Dropdown class="o_debug_manager"
|
||||
beforeOpen="getElements"
|
||||
position="'bottom-end'"
|
||||
tag="'li'"
|
||||
togglerClass="'btn btn-link'">
|
||||
<t t-set-slot="toggler">
|
||||
<span class="fa fa-bug"/>
|
||||
@@ -15,7 +17,7 @@
|
||||
<span t-else="" t-esc="element.description"/>
|
||||
</DropdownItem>
|
||||
</t>
|
||||
<div t-if="element.type == 'separator'" role="separator" class="dropdown-divider"/>
|
||||
<li t-if="element.type == 'separator'" role="separator" class="dropdown-divider"/>
|
||||
<t t-if="element.type == 'component'" t-component="element.Component" t-props="element.props"/>
|
||||
</t>
|
||||
</Dropdown>
|
||||
|
||||
@@ -67,13 +67,17 @@ export class Dropdown extends Component {
|
||||
this.hasParentDropdown = this.env.inDropdown;
|
||||
useSubEnv({ inDropdown: true });
|
||||
this.rootTag = this.props.tag || (this.hasParentDropdown ? "li" : "div");
|
||||
const position =
|
||||
this.props.position || (this.hasParentDropdown ? "right-start" : "bottom-start");
|
||||
|
||||
// Set up key navigation -----------------------------------------------
|
||||
useDropdownNavigation();
|
||||
|
||||
// Set up toggler and positioning --------------------------------------
|
||||
const positioningOptions = {
|
||||
popper: "menuRef",
|
||||
position:
|
||||
this.props.position || (this.hasParentDropdown ? "right-start" : "bottom-start"),
|
||||
directionFlipOrder: { right: "rl", bottom: "bt", top: "tb", left: "lr" },
|
||||
};
|
||||
if (this.props.toggler === "parent") {
|
||||
// Add parent click listener to handle toggling
|
||||
useEffect(
|
||||
@@ -94,11 +98,11 @@ export class Dropdown extends Component {
|
||||
);
|
||||
|
||||
// Position menu relatively to parent element
|
||||
usePosition(() => this.el.parentElement, { popper: "menuRef", position });
|
||||
usePosition(() => this.el.parentElement, positioningOptions);
|
||||
} else {
|
||||
// Position menu relatively to inner toggler
|
||||
const togglerRef = useRef("togglerRef");
|
||||
usePosition(() => togglerRef.el, { popper: "menuRef", position });
|
||||
usePosition(() => togglerRef.el, positioningOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
|
||||
&_menu {
|
||||
@extend .dropdown-menu;
|
||||
position: relative;
|
||||
|
||||
&.o_dropdown_menu_right {
|
||||
// FIXME: does commenting this break anything?
|
||||
@@ -74,9 +75,8 @@
|
||||
}
|
||||
|
||||
& > li.o_dropdown {
|
||||
&.navigated > .o_dropdown_toggler {
|
||||
// FIXME: without this there is no selection feedback
|
||||
// @extend :hover;
|
||||
&.focus > .o_dropdown_toggler {
|
||||
background-color: $dropdown-link-hover-bg;
|
||||
}
|
||||
& > .o_dropdown_toggler {
|
||||
// FIXME: without this there is no selection feedback
|
||||
@@ -117,11 +117,8 @@
|
||||
// FIXME: does commenting this break anything?
|
||||
//@extend .disabled;
|
||||
}
|
||||
&.active > :first-child {
|
||||
// FIXME: without this there is no selection feedback
|
||||
// @extend :hover;
|
||||
background-color: rgba(0, 0, 0, 0.08);
|
||||
color: #091124;
|
||||
&.focus {
|
||||
background-color: $dropdown-link-hover-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<t
|
||||
t-tag="rootTag"
|
||||
class="o_dropdown"
|
||||
t-att-class="{ 'o-dropdown--open': state.open, 'o_dropdown_item': hasParentDropdown and rootTag === 'li' }"
|
||||
t-att-class="{ show: state.open, o_dropdown_item: hasParentDropdown and rootTag === 'li' }"
|
||||
t-on-dropdown-item-selected="onItemSelected"
|
||||
>
|
||||
<button
|
||||
|
||||
@@ -19,7 +19,7 @@ import { scrollTo } from "../utils/scrolling";
|
||||
const { hooks } = owl;
|
||||
const { useComponent, useRef } = hooks;
|
||||
|
||||
const ACTIVE_MENU_ELEMENT_CLASS = "active";
|
||||
const ACTIVE_MENU_ELEMENT_CLASS = "focus";
|
||||
const MENU_ELEMENTS_SELECTORS = [":scope > li.o_dropdown_item", ":scope > li.o_dropdown"];
|
||||
const NEXT_ACTIVE_INDEX_FNS = {
|
||||
FIRST: () => 0,
|
||||
@@ -46,108 +46,105 @@ export function useDropdownNavigation() {
|
||||
const menuRef = useRef("menuRef");
|
||||
/** @type {MenuElement[]} */
|
||||
let menuElements = [];
|
||||
useEffect(
|
||||
(open) => {
|
||||
if (!open) {
|
||||
return;
|
||||
}
|
||||
// Prepare MenuElements
|
||||
const addedListeners = [];
|
||||
/** @type {NodeListOf<HTMLElement>} */
|
||||
const queryResult = menuRef.el.querySelectorAll(MENU_ELEMENTS_SELECTORS.join());
|
||||
for (const el of queryResult) {
|
||||
const isSubDropdown = el.classList.contains("o_dropdown");
|
||||
const isSubDropdownOpen = () => el.classList.contains("o-dropdown--open");
|
||||
const togglerClick = () => {
|
||||
const toggler = el.querySelector(":scope > .o_dropdown_toggler");
|
||||
if (toggler) {
|
||||
toggler.dispatchEvent(new MouseEvent("click", { bubbles: false }));
|
||||
}
|
||||
};
|
||||
let subDropdownTimeout;
|
||||
const closeSubDropdown = () => {
|
||||
browser.clearTimeout(subDropdownTimeout);
|
||||
subDropdownTimeout = browser.setTimeout(() => {
|
||||
if (isSubDropdownOpen()) {
|
||||
togglerClick();
|
||||
}
|
||||
}, 200);
|
||||
};
|
||||
const openSubDropdown = (immediate = false) => {
|
||||
browser.clearTimeout(subDropdownTimeout);
|
||||
subDropdownTimeout = browser.setTimeout(
|
||||
() => {
|
||||
if (!isSubDropdownOpen()) {
|
||||
togglerClick();
|
||||
}
|
||||
},
|
||||
immediate ? 0 : 200
|
||||
);
|
||||
};
|
||||
const makeOnlyActive = () => {
|
||||
// Make all others inactive
|
||||
for (const menuElement of menuElements) {
|
||||
if (menuElement.el === el) {
|
||||
continue;
|
||||
}
|
||||
menuElement.el.classList.remove(ACTIVE_MENU_ELEMENT_CLASS);
|
||||
if (menuElement.isSubDropdown) {
|
||||
menuElement.closeSubDropdown();
|
||||
}
|
||||
}
|
||||
// Make myself active
|
||||
el.classList.add(ACTIVE_MENU_ELEMENT_CLASS);
|
||||
};
|
||||
|
||||
/** @type {MenuElement} */
|
||||
const menuElement = {
|
||||
el,
|
||||
get isActive() {
|
||||
return el.classList.contains(ACTIVE_MENU_ELEMENT_CLASS);
|
||||
},
|
||||
makeOnlyActive,
|
||||
get isSubDropdownOpen() {
|
||||
return isSubDropdownOpen();
|
||||
},
|
||||
isSubDropdown,
|
||||
closeSubDropdown,
|
||||
openSubDropdown,
|
||||
};
|
||||
menuElements.push(menuElement);
|
||||
|
||||
// Set up selection listeners
|
||||
const elementListeners = {
|
||||
click: makeOnlyActive,
|
||||
mouseenter: () => {
|
||||
if (!mouseSelectionActive) {
|
||||
mouseSelectionActive = true;
|
||||
} else {
|
||||
menuElement.makeOnlyActive();
|
||||
if (isSubDropdown) {
|
||||
openSubDropdown();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
for (const [eventType, listener] of Object.entries(elementListeners)) {
|
||||
menuElement.el.addEventListener(eventType, listener);
|
||||
}
|
||||
addedListeners.push([menuElement, elementListeners]);
|
||||
}
|
||||
return () => {
|
||||
menuElements = [];
|
||||
mouseSelectionActive = true;
|
||||
|
||||
// Clear mouse selection listeners
|
||||
for (const [menuElement, listeners] of addedListeners) {
|
||||
for (const [eventType, listener] of Object.entries(listeners)) {
|
||||
menuElement.el.removeEventListener(eventType, listener);
|
||||
}
|
||||
useEffect(() => {
|
||||
if (!comp.state.open) {
|
||||
return;
|
||||
}
|
||||
// Prepare MenuElements
|
||||
const addedListeners = [];
|
||||
/** @type {NodeListOf<HTMLElement>} */
|
||||
const queryResult = menuRef.el.querySelectorAll(MENU_ELEMENTS_SELECTORS.join());
|
||||
for (const el of queryResult) {
|
||||
const isSubDropdown = el.classList.contains("o_dropdown");
|
||||
const isSubDropdownOpen = () => el.classList.contains("show");
|
||||
const togglerClick = () => {
|
||||
const toggler = el.querySelector(":scope > .o_dropdown_toggler");
|
||||
if (toggler) {
|
||||
toggler.dispatchEvent(new MouseEvent("click", { bubbles: false }));
|
||||
}
|
||||
};
|
||||
},
|
||||
() => [comp.state.open]
|
||||
);
|
||||
let subDropdownTimeout;
|
||||
const closeSubDropdown = () => {
|
||||
browser.clearTimeout(subDropdownTimeout);
|
||||
subDropdownTimeout = browser.setTimeout(() => {
|
||||
if (isSubDropdownOpen()) {
|
||||
togglerClick();
|
||||
}
|
||||
}, 200);
|
||||
};
|
||||
const openSubDropdown = (immediate = false) => {
|
||||
browser.clearTimeout(subDropdownTimeout);
|
||||
subDropdownTimeout = browser.setTimeout(
|
||||
() => {
|
||||
if (!isSubDropdownOpen()) {
|
||||
togglerClick();
|
||||
}
|
||||
},
|
||||
immediate ? 0 : 200
|
||||
);
|
||||
};
|
||||
const makeOnlyActive = () => {
|
||||
// Make all others inactive
|
||||
for (const menuElement of menuElements) {
|
||||
if (menuElement.el === el) {
|
||||
continue;
|
||||
}
|
||||
menuElement.el.classList.remove(ACTIVE_MENU_ELEMENT_CLASS);
|
||||
if (menuElement.isSubDropdown) {
|
||||
menuElement.closeSubDropdown();
|
||||
}
|
||||
}
|
||||
// Make myself active
|
||||
el.classList.add(ACTIVE_MENU_ELEMENT_CLASS);
|
||||
};
|
||||
|
||||
/** @type {MenuElement} */
|
||||
const menuElement = {
|
||||
el,
|
||||
get isActive() {
|
||||
return el.classList.contains(ACTIVE_MENU_ELEMENT_CLASS);
|
||||
},
|
||||
makeOnlyActive,
|
||||
get isSubDropdownOpen() {
|
||||
return isSubDropdownOpen();
|
||||
},
|
||||
isSubDropdown,
|
||||
closeSubDropdown,
|
||||
openSubDropdown,
|
||||
};
|
||||
menuElements.push(menuElement);
|
||||
|
||||
// Set up selection listeners
|
||||
const elementListeners = {
|
||||
click: makeOnlyActive,
|
||||
mouseenter: () => {
|
||||
if (!mouseSelectionActive) {
|
||||
mouseSelectionActive = true;
|
||||
} else {
|
||||
menuElement.makeOnlyActive();
|
||||
if (isSubDropdown) {
|
||||
openSubDropdown();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
for (const [eventType, listener] of Object.entries(elementListeners)) {
|
||||
menuElement.el.addEventListener(eventType, listener);
|
||||
}
|
||||
addedListeners.push([menuElement, elementListeners]);
|
||||
}
|
||||
return () => {
|
||||
menuElements = [];
|
||||
mouseSelectionActive = true;
|
||||
|
||||
// Clear mouse selection listeners
|
||||
for (const [menuElement, listeners] of addedListeners) {
|
||||
for (const [eventType, listener] of Object.entries(listeners)) {
|
||||
menuElement.el.removeEventListener(eventType, listener);
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// Set up active menu element helpers --------------------------------------
|
||||
/**
|
||||
@@ -208,7 +205,11 @@ export function useDropdownNavigation() {
|
||||
enter: () => {
|
||||
const menuElement = getActiveMenuElement();
|
||||
if (menuElement) {
|
||||
menuElement.el.click();
|
||||
if (menuElement.isSubDropdown) {
|
||||
menuElement.openSubDropdown(true);
|
||||
} else {
|
||||
menuElement.el.click();
|
||||
}
|
||||
}
|
||||
},
|
||||
escape: comp.close,
|
||||
|
||||
@@ -9,6 +9,8 @@ import { debounce, throttle } from "../utils/timing";
|
||||
* container?: HTMLElement;
|
||||
* margin?: number;
|
||||
* position?: Position;
|
||||
* directionFlipOrder?: DirectionFlipOrder;
|
||||
* variantFlipOrder?: VariantFlipOrder;
|
||||
* }} Options
|
||||
*
|
||||
* @typedef {{
|
||||
@@ -36,6 +38,14 @@ import { debounce, throttle } from "../utils/timing";
|
||||
* }} VariantsData
|
||||
*
|
||||
* @typedef {"top" | "left" | "bottom" | "right"} Direction
|
||||
* @typedef {"start" | "middle" | "end"} Variant
|
||||
*
|
||||
* @typedef {{[direction in Direction]: string}} DirectionFlipOrder
|
||||
* values are successive DirectionsDataKey represented as a single string
|
||||
*
|
||||
* @typedef {{[variant in Variant]: string}} VariantFlipOrder
|
||||
* values are successive VariantsDataKey represented as a single string
|
||||
*
|
||||
* @typedef {Direction
|
||||
* | "top-start" | "top-middle" | "top-end"
|
||||
* | "left-start" | "left-middle" | "left-end"
|
||||
@@ -49,13 +59,13 @@ const { hooks } = owl;
|
||||
const { useComponent, useExternalListener, useRef } = hooks;
|
||||
|
||||
const POPPER_CLASS = "o-popper-position";
|
||||
const DIRECTION_FLIP_ORDER = { top: "tbrl", right: "rltb", bottom: "btrl", left: "lrbt" };
|
||||
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" },
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -72,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 } = options;
|
||||
const { container, margin, position, directionFlipOrder, variantFlipOrder } = options;
|
||||
|
||||
// Retrieve directions and variants
|
||||
const [directionKey, variantKey = "middle"] = position.split("-");
|
||||
const directions = DIRECTION_FLIP_ORDER[directionKey];
|
||||
const variants = VARIANT_FLIP_ORDER[variantKey];
|
||||
const directions = directionFlipOrder[directionKey];
|
||||
const variants = variantFlipOrder[variantKey];
|
||||
|
||||
// Boxes
|
||||
const popBox = popper.getBoundingClientRect();
|
||||
|
||||
@@ -89,8 +89,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
.o-dropdown{
|
||||
&--open > .o_dropdown_toggler {
|
||||
.o-dropdown {
|
||||
&.show > .o_dropdown_toggler {
|
||||
@extend %-main-navbar-entry-active;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
.o_switch_company_menu {
|
||||
.o_dropdown_menu {
|
||||
min-width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="web.SwitchCompanyMenu" owl="1">
|
||||
<Dropdown class="o_switch_company_menu">
|
||||
<Dropdown class="o_switch_company_menu" position="'bottom-end'" tag="'li'">
|
||||
<t t-set-slot="toggler">
|
||||
<span t-attf-class="{{env.isSmall ? 'fa fa-building-o' : 'oe_topbar_name'}}">
|
||||
<t t-if="!env.isSmall"><t t-esc="currentCompany.name"/></t>
|
||||
@@ -18,45 +18,43 @@
|
||||
|
||||
|
||||
<t t-name="web.SwitchCompanyItem" owl="1">
|
||||
<div>
|
||||
<DropdownItem class="p-0 bg-white">
|
||||
<t t-set="isCompanySelected" t-value="selectedCompanies.includes(company.id)"/>
|
||||
<t t-set="isCurrent" t-value="company.id === companyService.currentCompany.id"/>
|
||||
<DropdownItem class="p-0 bg-white">
|
||||
<div class="d-flex" data-menu="company" t-att-data-company-id="company.id">
|
||||
<div
|
||||
role="menuitemcheckbox"
|
||||
t-att-aria-checked="isCompanySelected"
|
||||
t-att-aria-label="company.name"
|
||||
t-att-title="(isCompanySelected ? 'Hide ' : 'Show ') + company.name + ' content.'"
|
||||
tabindex="0"
|
||||
class="border-right toggle_company o_py"
|
||||
t-attf-class="{{isCurrent ? 'border-primary' : ''}}"
|
||||
t-on-click.stop="toggleCompany(company.id)">
|
||||
<div class="d-flex" data-menu="company" t-att-data-company-id="company.id">
|
||||
<div
|
||||
role="menuitemcheckbox"
|
||||
t-att-aria-checked="isCompanySelected"
|
||||
t-att-aria-label="company.name"
|
||||
t-att-title="(isCompanySelected ? 'Hide ' : 'Show ') + company.name + ' content.'"
|
||||
tabindex="0"
|
||||
class="border-right toggle_company o_py"
|
||||
t-attf-class="{{isCurrent ? 'border-primary' : ''}}"
|
||||
t-on-click.stop="toggleCompany(company.id)">
|
||||
|
||||
<span class="btn btn-light border-0 p-2">
|
||||
<i class="fa fa-fw py-2" t-att-class="isCompanySelected ? 'fa-check-square text-primary' : 'fa-square-o'"/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
role="button"
|
||||
t-att-aria-pressed="isCurrent"
|
||||
t-att-aria-label="'Switch to ' + company.name "
|
||||
t-att-title="'Switch to ' + company.name "
|
||||
tabindex="0"
|
||||
class="d-flex flex-grow-1 align-items-center py-0 log_into pl-2 o_py"
|
||||
t-att-class="isCurrent ? 'alert-primary ml-1 mr-2' : 'btn btn-light font-weight-normal border-0'"
|
||||
t-on-click="logIntoCompany(company.id)">
|
||||
|
||||
<span
|
||||
class='company_label pr-3'
|
||||
t-att-class="isCurrent ? 'text-900 font-weight-bold' : 'ml-1'">
|
||||
<t t-esc="company.name"/>
|
||||
</span>
|
||||
</div>
|
||||
<span class="btn btn-light border-0 p-2">
|
||||
<i class="fa fa-fw py-2" t-att-class="isCompanySelected ? 'fa-check-square text-primary' : 'fa-square-o'"/>
|
||||
</span>
|
||||
</div>
|
||||
</DropdownItem>
|
||||
</div>
|
||||
|
||||
<div
|
||||
role="button"
|
||||
t-att-aria-pressed="isCurrent"
|
||||
t-att-aria-label="'Switch to ' + company.name "
|
||||
t-att-title="'Switch to ' + company.name "
|
||||
tabindex="0"
|
||||
class="d-flex flex-grow-1 align-items-center py-0 log_into pl-2 o_py"
|
||||
t-att-class="isCurrent ? 'alert-primary ml-1 mr-2' : 'btn btn-light font-weight-normal border-0'"
|
||||
t-on-click="logIntoCompany(company.id)">
|
||||
|
||||
<span
|
||||
class='company_label pr-3'
|
||||
t-att-class="isCurrent ? 'text-900 font-weight-bold' : 'ml-1'">
|
||||
<t t-esc="company.name"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</DropdownItem>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -7,10 +7,4 @@
|
||||
object-fit: cover;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.o_dropdown_menu {
|
||||
// FIXME weird hack to keep menu from taking all viewport width
|
||||
min-width: 100%;
|
||||
position: sticky;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="web.UserMenu" owl="1">
|
||||
<Dropdown class="o_user_menu" t-on-dropdown-item-selected.stop="onDropdownItemSelected">
|
||||
<Dropdown class="o_user_menu" tag="'li'" t-on-dropdown-item-selected.stop="onDropdownItemSelected">
|
||||
<t t-set-slot="toggler">
|
||||
<img class="rounded-circle o_user_avatar" t-att-src="source" alt="User"/> <span class="oe_topbar_name"><t t-esc="user.name"/><t t-if="env.debug" t-esc="' (' + user.db.name + ')'"/></span>
|
||||
</t>
|
||||
|
||||
@@ -99,11 +99,11 @@ QUnit.module("DebugMenu", (hooks) => {
|
||||
await click(debugManager.el.querySelector("button.o_dropdown_toggler"));
|
||||
debugManagerEl = debugManager.el;
|
||||
assert.containsN(debugManagerEl, "ul.o_dropdown_menu li.o_dropdown_item", 3);
|
||||
assert.containsOnce(debugManagerEl, "div.dropdown-divider");
|
||||
assert.containsOnce(debugManagerEl, "li.dropdown-divider");
|
||||
const children = [...(debugManagerEl.querySelector("ul.o_dropdown_menu").children || [])];
|
||||
assert.deepEqual(
|
||||
children.map((el) => el.tagName),
|
||||
["LI", "LI", "DIV", "LI"]
|
||||
["LI", "LI", "LI", "LI"]
|
||||
);
|
||||
const items =
|
||||
[...debugManagerEl.querySelectorAll("ul.o_dropdown_menu li.o_dropdown_item span")] ||
|
||||
|
||||
@@ -629,7 +629,7 @@ QUnit.module("Components", ({ beforeEach }) => {
|
||||
// Navigate with arrows
|
||||
assert.containsNone(
|
||||
parent.el,
|
||||
".o_dropdown_menu > .active",
|
||||
".o_dropdown_menu > .focus",
|
||||
"menu should not have any active items"
|
||||
);
|
||||
|
||||
@@ -654,7 +654,7 @@ QUnit.module("Components", ({ beforeEach }) => {
|
||||
for (const step of scenarioSteps) {
|
||||
triggerHotkey(step.hotkey);
|
||||
await nextTick();
|
||||
assert.hasClass(parent.el.querySelector(".o_dropdown_menu > .active"), step.expected);
|
||||
assert.hasClass(parent.el.querySelector(".o_dropdown_menu > .focus"), step.expected);
|
||||
}
|
||||
|
||||
// Select last one activated in previous scenario (item1)
|
||||
@@ -717,7 +717,7 @@ QUnit.module("Components", ({ beforeEach }) => {
|
||||
});
|
||||
|
||||
QUnit.test("multi-level dropdown: keynav", async (assert) => {
|
||||
assert.expect(119);
|
||||
assert.expect(126);
|
||||
class Parent extends owl.Component {
|
||||
onItemSelected(ev) {
|
||||
const { payload } = ev.detail;
|
||||
@@ -808,7 +808,9 @@ QUnit.module("Components", ({ beforeEach }) => {
|
||||
{ hotkey: "home", highlighted: ["second", "third", "third-first"] },
|
||||
{ hotkey: "end", highlighted: ["second", "third", "third-last"] },
|
||||
{ hotkey: "end", highlighted: ["second", "third", "third-last"] },
|
||||
{ hotkey: "enter", selected: "third-last" },
|
||||
{ hotkey: "arrowleft", highlighted: ["second", "third"] },
|
||||
{ hotkey: "enter", highlighted: ["second", "third", "third-first"] },
|
||||
{ hotkey: "enter", selected: "third-first" },
|
||||
{ hotkey: "alt+1" },
|
||||
{ hotkey: "alt+e", selected: false },
|
||||
{ hotkey: "alt+f", selected: "first-last" },
|
||||
@@ -826,7 +828,7 @@ QUnit.module("Components", ({ beforeEach }) => {
|
||||
await nextTick();
|
||||
if (step.highlighted !== undefined) {
|
||||
let index = 0;
|
||||
const activeElements = parent.el.querySelectorAll(".active");
|
||||
const activeElements = parent.el.querySelectorAll(".focus");
|
||||
assert.ok(
|
||||
activeElements.length === step.highlighted.length,
|
||||
`step ${stepIndex}: all active elements to check are found`
|
||||
|
||||
@@ -56,7 +56,7 @@ QUnit.module("SwitchCompanyMenu", (hooks) => {
|
||||
|
||||
const scMenu = await createSwitchCompanyMenu();
|
||||
|
||||
assert.strictEqual(scMenu.el.tagName.toUpperCase(), "DIV");
|
||||
assert.strictEqual(scMenu.el.tagName.toUpperCase(), "LI");
|
||||
assert.hasClass(scMenu.el, "o_switch_company_menu");
|
||||
assert.strictEqual(scMenu.el.textContent, "Hermit");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user