diff --git a/addons/mail/static/src/core/common/composer.scss b/addons/mail/static/src/core/common/composer.scss index 1c04322c361..ab2987dd148 100644 --- a/addons/mail/static/src/core/common/composer.scss +++ b/addons/mail/static/src/core/common/composer.scss @@ -63,13 +63,6 @@ --Avatar-size: #{$o-mail-Avatar-size}; } -.o-fast-popover { - animation: 0.02s slide-right !important; - animation: 0.02s slide-left !important; - animation: 0.02s slide-top !important; - animation: 0.02s slide-bottom !important; -} - .o-mail-Composer-fake { height: 0; top: -10000px; diff --git a/addons/mail/static/src/core/common/picker.js b/addons/mail/static/src/core/common/picker.js index e49f5f81725..2c0c0636943 100644 --- a/addons/mail/static/src/core/common/picker.js +++ b/addons/mail/static/src/core/common/picker.js @@ -65,7 +65,8 @@ export class Picker extends Component { fixedPosition: true, onClose: () => this.close(), closeOnClickAway: false, - popoverClass: "o-fast-popover", + animation: false, + arrow: false, }); useExternalListener( browser, diff --git a/addons/web/static/src/core/emoji_picker/emoji_picker.js b/addons/web/static/src/core/emoji_picker/emoji_picker.js index 943bff29c09..b318a91c657 100644 --- a/addons/web/static/src/core/emoji_picker/emoji_picker.js +++ b/addons/web/static/src/core/emoji_picker/emoji_picker.js @@ -32,7 +32,7 @@ import { useAutofocus, useService } from "@web/core/utils/hooks"; */ export function useEmojiPicker(ref, props, options = {}) { const targets = []; - const popover = usePopover(EmojiPicker, { ...options, popoverClass: "o-fast-popover" }); + const popover = usePopover(EmojiPicker, { ...options, animation: false }); props.storeScroll = { scrollValue: 0, set: (value) => { diff --git a/addons/web/static/src/core/popover/popover.js b/addons/web/static/src/core/popover/popover.js index 81905ce5fa1..4cecc3615ef 100644 --- a/addons/web/static/src/core/popover/popover.js +++ b/addons/web/static/src/core/popover/popover.js @@ -5,9 +5,11 @@ import { useForwardRefToParent } from "../utils/hooks"; import { usePosition } from "@web/core/position_hook"; export class Popover extends Component { + static animationTime = 200; setup() { useForwardRefToParent("ref"); - const position = usePosition( + this.shouldAnimate = this.props.animation; + this.position = usePosition( "ref", () => this.props.target, { @@ -15,7 +17,7 @@ export class Popover extends Component { (this.props.onPositioned || this.onPositioned.bind(this))(el, solution); if (this.props.fixedPosition) { // Prevent further positioning updates if fixed position is wanted - position.lock(); + this.position.lock(); } }, position: this.props.position, @@ -43,40 +45,56 @@ export class Popover extends Component { } // reset all arrow classes - const arrowEl = el.querySelector(".popover-arrow"); - if (!arrowEl) { - return; + if (this.props.arrow) { + const arrowEl = el.querySelector(":scope > .popover-arrow"); + arrowEl.className = "popover-arrow"; + switch (position) { + case "tm": // top-middle + case "bm": // bottom-middle + case "tf": // top-fit + case "bf": // bottom-fit + arrowEl.classList.add("start-0", "end-0", "mx-auto"); + break; + case "lm": // left-middle + case "rm": // right-middle + case "lf": // left-fit + case "rf": // right-fit + arrowEl.classList.add("top-0", "bottom-0", "my-auto"); + break; + case "ts": // top-start + case "bs": // bottom-start + arrowEl.classList.add("end-auto"); + break; + case "te": // top-end + case "be": // bottom-end + arrowEl.classList.add("start-auto"); + break; + case "ls": // left-start + case "rs": // right-start + arrowEl.classList.add("bottom-auto"); + break; + case "le": // left-end + case "re": // right-end + arrowEl.classList.add("top-auto"); + break; + } } - arrowEl.className = "popover-arrow"; - switch (position) { - case "tm": // top-middle - case "bm": // bottom-middle - case "tf": // top-fit - case "bf": // bottom-fit - arrowEl.classList.add("start-0", "end-0", "mx-auto"); - break; - case "lm": // left-middle - case "rm": // right-middle - case "lf": // left-fit - case "rf": // right-fit - arrowEl.classList.add("top-0", "bottom-0", "my-auto"); - break; - case "ts": // top-start - case "bs": // bottom-start - arrowEl.classList.add("end-auto"); - break; - case "te": // top-end - case "be": // bottom-end - arrowEl.classList.add("start-auto"); - break; - case "ls": // left-start - case "rs": // right-start - arrowEl.classList.add("bottom-auto"); - break; - case "le": // left-end - case "re": // right-end - arrowEl.classList.add("top-auto"); - break; + + // opening animation + if (this.shouldAnimate) { + this.shouldAnimate = false; // animate only once + const transform = { + top: ["translateY(-5%)", "translateY(0)"], + right: ["translateX(5%)", "translateX(0)"], + bottom: ["translateY(5%)", "translateY(0)"], + left: ["translateX(-5%)", "translateX(0)"], + }[direction]; + this.position.lock(); + const animation = el.animate( + { opacity: [0, 1], transform }, + this.constructor.animationTime + ); + animation.finished.then(this.position.unlock); } } } @@ -85,6 +103,9 @@ Popover.template = "web.PopoverWowl"; Popover.defaultProps = { position: "bottom", class: "", + fixedPosition: false, + arrow: true, + animation: true, }; Popover.props = { ref: { @@ -114,6 +135,14 @@ Popover.props = { type: Boolean, optional: true, }, + arrow: { + type: Boolean, + optional: true, + }, + animation: { + type: Boolean, + optional: true, + }, target: { validate: (target) => { // target may be inside an iframe, so get the Element constructor diff --git a/addons/web/static/src/core/popover/popover.scss b/addons/web/static/src/core/popover/popover.scss index e9b38e8408b..ae011d9a199 100644 --- a/addons/web/static/src/core/popover/popover.scss +++ b/addons/web/static/src/core/popover/popover.scss @@ -1,40 +1,5 @@ /*!rtl:begin:ignore*/ - -@keyframes slide-top { - 0% { - opacity: 0; - transform: translateY(-5%); - } -} - -@keyframes slide-end { - 0% { - opacity: 0; - transform: translateX(5%); - } -} - -@keyframes slide-bottom { - 0% { - opacity: 0; - transform: translateY(5%); - } -} - -@keyframes slide-start { - 0% { - opacity: 0; - transform: translateX(-5%); - } -} - .o_popover { - @each $direction in (top, end, bottom, start) { - &.bs-popover-#{$direction} { - animation: 0.2s slide-#{$direction}; - } - } - &.o-popover-top, &.o-popover-auto[x-placement^="top"] { margin-bottom: 0.5rem; } diff --git a/addons/web/static/src/core/popover/popover.xml b/addons/web/static/src/core/popover/popover.xml index ed2341c8e7f..79ffef425fd 100644 --- a/addons/web/static/src/core/popover/popover.xml +++ b/addons/web/static/src/core/popover/popover.xml @@ -4,7 +4,7 @@