[IMP] web: Tooltip UX on touch-enable devices
Before this commit, in a touch device the behaviour was a
"tap-hold-to-show” which let the user see the Tooltip by pressing the
element, and letting it disappear when the pressure ends.
This commit allows choosing between the previous "tap-hold-to-show"
behaviour and a new "tap-to-show" which let the user see the Tooltip by
pressing the element, and keep it open until it press something else.
This behaviour is more adapted when the tooltip is on a specific icon,
as is the case for the labels, since : f981c5f8f0
closes odoo/odoo#97680
Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
This commit is contained in:
@@ -23,6 +23,10 @@ const { whenReady } = owl;
|
||||
* The opening delay can be modified with the "data-tooltip-delay" attribute (default: 400):
|
||||
* <button data-tooltip="This is a tooltip" data-tooltip-delay="0">Do something</button>
|
||||
*
|
||||
* The default behaviour on touch devices to open the tooltip can be modified from "hold-to-show"
|
||||
* to "tap-to-show" "with the data-tooltip-touch-tap-to-show" attribute:
|
||||
* <button data-tooltip="This is a tooltip" data-tooltip-touch-tap-to-show="true">Do something</button>
|
||||
*
|
||||
* For advanced tooltips containing dynamic and/or html content, the
|
||||
* "data-tooltip-template" and "data-tooltip-info" attributes can be used.
|
||||
* For example, let's suppose the following qweb template:
|
||||
@@ -188,12 +192,20 @@ export const tooltipService = {
|
||||
if (hasTouch()) {
|
||||
document.body.addEventListener("touchstart", onTouchStart);
|
||||
|
||||
document.body.addEventListener("touchend", () => {
|
||||
touchPressed = false;
|
||||
document.body.addEventListener("touchend", (ev) => {
|
||||
if (ev.target.matches("[data-tooltip], [data-tooltip-template]")) {
|
||||
if (!ev.target.dataset.tooltipTouchTapToShow) {
|
||||
touchPressed = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.body.addEventListener("touchcancel", () => {
|
||||
touchPressed = false;
|
||||
document.body.addEventListener("touchcancel", (ev) => {
|
||||
if (ev.target.matches("[data-tooltip], [data-tooltip-template]")) {
|
||||
if (!ev.target.dataset.tooltipTouchTapToShow) {
|
||||
touchPressed = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
|
||||
@@ -55,6 +55,6 @@ export class FormLabel extends Component {
|
||||
}
|
||||
FormLabel.template = xml`
|
||||
<label class="o_form_label" t-att-for="props.id" t-att-class="className" >
|
||||
<t t-esc="props.string"/><sup class="btn-link p-2" t-if="hasTooltip" t-att="{'data-tooltip-template': 'web.FieldTooltip', 'data-tooltip-info': tooltipInfo}">?</sup>
|
||||
<t t-esc="props.string"/><sup class="btn-link p-2" t-if="hasTooltip" t-att="{'data-tooltip-template': 'web.FieldTooltip', 'data-tooltip-info': tooltipInfo, 'data-tooltip-touch-tap-to-show': 'true'}">?</sup>
|
||||
</label>
|
||||
`;
|
||||
|
||||
@@ -381,7 +381,7 @@ QUnit.module("Tooltip service", (hooks) => {
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
QUnit.test("touch rendering", async (assert) => {
|
||||
QUnit.test("touch rendering - hold-to-show", async (assert) => {
|
||||
class MyComponent extends Component {}
|
||||
MyComponent.template = xml`<button data-tooltip="hello">Action</button>`;
|
||||
let simulateTimeout;
|
||||
@@ -414,4 +414,41 @@ QUnit.module("Tooltip service", (hooks) => {
|
||||
await nextTick();
|
||||
assert.containsNone(target, ".o_popover_container .o_popover");
|
||||
});
|
||||
|
||||
QUnit.test("touch rendering - tap-to-show", async (assert) => {
|
||||
class MyComponent extends Component {}
|
||||
MyComponent.template = xml`<button data-tooltip="hello" data-tooltip-touch-tap-to-show="true">Action</button>`;
|
||||
let simulateTimeout;
|
||||
const mockSetTimeout = (fn) => {
|
||||
simulateTimeout = fn;
|
||||
};
|
||||
let simulateInterval;
|
||||
const mockSetInterval = (fn) => {
|
||||
simulateInterval = fn;
|
||||
};
|
||||
const mockOnTouchStart = () => {};
|
||||
await makeParent(MyComponent, { mockSetTimeout, mockSetInterval, mockOnTouchStart });
|
||||
|
||||
assert.containsNone(target, ".o_popover_container .o_popover");
|
||||
await triggerEvent(target, "button[data-tooltip]", "touchstart");
|
||||
await nextTick();
|
||||
assert.containsNone(target, ".o_popover_container .o_popover");
|
||||
|
||||
simulateTimeout();
|
||||
await nextTick();
|
||||
assert.containsOnce(target, ".o_popover_container .o_popover");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o_popover_container .o_popover").innerText,
|
||||
"hello"
|
||||
);
|
||||
|
||||
await triggerEvent(target, "button[data-tooltip]", "touchend");
|
||||
assert.containsOnce(target, ".o_popover_container .o_popover");
|
||||
simulateInterval();
|
||||
await nextTick();
|
||||
assert.containsOnce(target, ".o_popover_container .o_popover");
|
||||
|
||||
await triggerEvent(target, "button[data-tooltip]", "touchstart");
|
||||
assert.containsNone(target, ".o_popover_container .o_popover");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user