[REF] web,mail: add popover props: arrow,animation
Better API as the arrow was not displayed when the fixedPosition prop was true, which is as we were mixing apples and pears. And as for the animation prop, it permits to remove the hacky "o-fast-popover" class usages. closes odoo/odoo#135188 Signed-off-by: Michaël Mattiello (mcm) <mcm@odoo.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<t t-name="web.PopoverWowl">
|
||||
<div role="tooltip" class="o_popover popover mw-100" t-att-class="props.class" t-ref="ref">
|
||||
<t t-slot="default" />
|
||||
<div t-if="!props.fixedPosition" class="popover-arrow"/>
|
||||
<div t-if="props.arrow" class="popover-arrow"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ import { PopoverController } from "./popover_controller";
|
||||
* closeOnClickAway?: boolean | (target: HTMLElement) => boolean;
|
||||
* onClose?: () => void;
|
||||
* popoverClass?: string;
|
||||
* animation?: Boolean;
|
||||
* arrow?: Boolean;
|
||||
* position?: import("@web/core/position_hook").Options["position"];
|
||||
* fixedPosition?: boolean;
|
||||
* onPositioned?: import("@web/core/position_hook").PositionEventHandler;
|
||||
@@ -43,6 +45,8 @@ export const popoverService = {
|
||||
popoverProps: {
|
||||
target,
|
||||
class: options.popoverClass,
|
||||
animation: options.animation,
|
||||
arrow: options.arrow,
|
||||
position: options.position,
|
||||
onPositioned: options.onPositioned,
|
||||
fixedPosition: options.fixedPosition,
|
||||
|
||||
@@ -45,6 +45,7 @@ export class PropertiesField extends Component {
|
||||
position: "top",
|
||||
onClose: () => this.onCloseCurrentPopover?.(),
|
||||
fixedPosition: true,
|
||||
arrow: false,
|
||||
});
|
||||
this.propertiesRef = useRef("properties");
|
||||
|
||||
@@ -753,11 +754,6 @@ export class PropertiesField extends Component {
|
||||
);
|
||||
|
||||
reposition(popover, target, { position: "top", margin: 10 });
|
||||
|
||||
const arrow = popover.querySelector(".popover-arrow");
|
||||
if (arrow) {
|
||||
arrow.classList.add("d-none");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user