summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/web_tour/static/src/js/tip.js22
-rw-r--r--addons/web_tour/static/src/scss/keyframes.scss50
-rw-r--r--addons/web_tour/static/src/scss/tip.scss238
3 files changed, 121 insertions, 189 deletions
diff --git a/addons/web_tour/static/src/js/tip.js b/addons/web_tour/static/src/js/tip.js
index c7900ac5dd2..fc6598a39e6 100644
--- a/addons/web_tour/static/src/js/tip.js
+++ b/addons/web_tour/static/src/js/tip.js
@@ -26,7 +26,8 @@ var Tip = Widget.extend({
* - handler [function] the handler
* - position [String] tip's position ('top', 'right', 'left' or 'bottom'), default 'right'
* - width [int] the width in px of the tip when opened, default 270
- * - space [int] space in px between anchor and tip, default 10
+ * - space [int] space in px between anchor and tip, default to 0, added to
+ * the natural space chosen in css
* - hidden [boolean] if true, the tip won't be visible (but the handlers will still be
* bound on the anchor, so that the tip is consumed if the user clicks on it)
* - overlay [Object] x and y values for the number of pixels the mouseout detection area
@@ -37,7 +38,7 @@ var Tip = Widget.extend({
this.info = _.defaults(info, {
position: "right",
width: 270,
- space: 10,
+ space: 0,
overlay: {
x: 50,
y: 50,
@@ -74,9 +75,9 @@ var Tip = Widget.extend({
start() {
this.$tooltip_overlay = this.$(".o_tooltip_overlay");
this.$tooltip_content = this.$(".o_tooltip_content");
- this.init_width = this.$el.innerWidth();
- this.init_height = this.$el.innerHeight();
- this.double_border_width = this.$el.outerWidth() - this.init_width;
+ this.init_width = this.$el.outerWidth();
+ this.init_height = this.$el.outerHeight();
+ this.double_border_width = 0; // TODO remove me in master
this.content_width = this.$tooltip_content.outerWidth(true);
this.content_height = this.$tooltip_content.outerHeight(true);
this.$tooltip_content.html(this.info.scrollContent);
@@ -98,7 +99,7 @@ var Tip = Widget.extend({
this._updatePosition(true);
this.$el.toggleClass('d-none', !!this.info.hidden);
- this.el.style.setProperty('opacity', '1', 'important');
+ this.el.classList.add('o_tooltip_visible');
core.bus.on("resize", this, _.debounce(function () {
if (this.tip_opened) {
this._to_bubble_mode(true);
@@ -326,8 +327,8 @@ var Tip = Widget.extend({
const offset = {top: this.$el[0].offsetTop, left: this.$el[0].offsetLeft};
this.$tooltip_overlay.css({
top: -Math.min((this.info.position === "bottom" ? this.info.space : this.info.overlay.y), offset.top),
- right: -Math.min((this.info.position === positionRight ? this.info.space : this.info.overlay.x), this.$window.width() - (offset.left + this.init_width + this.double_border_width)),
- bottom: -Math.min((this.info.position === "top" ? this.info.space : this.info.overlay.y), this.$window.height() - (offset.top + this.init_height + this.double_border_width)),
+ right: -Math.min((this.info.position === positionRight ? this.info.space : this.info.overlay.x), this.$window.width() - (offset.left + this.init_width)),
+ bottom: -Math.min((this.info.position === "top" ? this.info.space : this.info.overlay.y), this.$window.height() - (offset.top + this.init_height)),
left: -Math.min((this.info.position === positionLeft ? this.info.space : this.info.overlay.x), offset.left),
});
this.position = offset;
@@ -437,9 +438,9 @@ var Tip = Widget.extend({
var overflow = false;
var posVertical = (this.info.position === "top" || this.info.position === "bottom");
if (posVertical) {
- overflow = (offset.left + this.content_width + this.double_border_width + this.info.overlay.x > this.$window.width());
+ overflow = (offset.left + this.content_width + this.info.overlay.x > this.$window.width());
} else {
- overflow = (offset.top + this.content_height + this.double_border_width + this.info.overlay.y > this.$window.height());
+ overflow = (offset.top + this.content_height + this.info.overlay.y > this.$window.height());
}
if (posVertical && overflow || this.info.position === "left" || (_t.database.parameters.direction === 'rtl' && this.info.position == "right")) {
mbLeft -= (this.content_width - this.init_width);
@@ -482,7 +483,6 @@ var Tip = Widget.extend({
this.timerOut = undefined;
this.tip_opened = false;
-
this.$el.removeClass("active").addClass("o_animated");
this.el.style.setProperty('width', `${this.init_width}px`, 'important');
this.el.style.setProperty('height', `${this.init_height}px`, 'important');
diff --git a/addons/web_tour/static/src/scss/keyframes.scss b/addons/web_tour/static/src/scss/keyframes.scss
index 0e7bb598fb2..74f3bbf07b2 100644
--- a/addons/web_tour/static/src/scss/keyframes.scss
+++ b/addons/web_tour/static/src/scss/keyframes.scss
@@ -1,49 +1 @@
-@-webkit-keyframes move-left-right {
- 0% {
- transform: translate(-3px, 0);
- }
- 100% {
- transform: translate(3px, 0);
- }
-}
-@-moz-keyframes move-left-right {
- 0% {
- transform: translate(-3px, 0);
- }
- 100% {
- transform: translate(3px, 0);
- }
-}
-@keyframes move-left-right {
- 0% {
- transform: translate(-3px, 0);
- }
- 100% {
- transform: translate(3px, 0);
- }
-}
-
-@-webkit-keyframes move-bottom-top {
- 0% {
- transform: translate(0, -3px);
- }
- 100% {
- transform: translate(0, 3px);
- }
-}
-@-moz-keyframes move-bottom-top {
- 0% {
- transform: translate(0px, -3px);
- }
- 100% {
- transform: translate(0, 3px);
- }
-}
-@keyframes move-bottom-top {
- 0% {
- transform: translate(0px, -3px);
- }
- 100% {
- transform: translate(0, 3px);
- }
-}
+// TODO remove in master
diff --git a/addons/web_tour/static/src/scss/tip.scss b/addons/web_tour/static/src/scss/tip.scss
index 680b76229b6..14413423cd7 100644
--- a/addons/web_tour/static/src/scss/tip.scss
+++ b/addons/web_tour/static/src/scss/tip.scss
@@ -1,3 +1,32 @@
+$o-tip-width: 28px;
+$o-tip-height: 38px;
+$o-tip-anchor-space: 3px;
+$o-tip-color: $o-enterprise-color;
+$o-tip-border-width: 3px;
+$o-tip-border-color: white;
+$o-tip-animation-speed: 500ms;
+$o-tip-arrow-size: 12px;
+
+$o-tip-duration-in: 200ms;
+$o-tip-size-duration-in: floor($o-tip-duration-in * 3 / 4);
+$o-tip-size-delay-in: $o-tip-duration-in - $o-tip-size-duration-in;
+
+@keyframes move-left-right {
+ 0% {
+ transform: translate(-$o-tip-anchor-space, 0);
+ }
+ 100% {
+ transform: translate($o-tip-anchor-space, 0);
+ }
+}
+@keyframes move-bottom-top {
+ 0% {
+ transform: translate(0, -$o-tip-anchor-space);
+ }
+ 100% {
+ transform: translate(0, $o-tip-anchor-space);
+ }
+}
.o_tooltip_parent {
position: relative !important;
@@ -21,118 +50,82 @@
}
.o_tooltip {
- $o-tip-color: $o-brand-odoo;
- $o-tip-size: 24px;
- $o-tip-border-width: 2px;
- $o-tip-arrow-length: 10px;
- $o-tip-arrow-width: 20px;
- $o-tip-arrow-integration: 2px;
-
- $o-tip-duration-in: 200ms;
- $o-tip-size-duration-in: floor($o-tip-duration-in * 3 / 4);
- $o-tip-size-delay-in: floor($o-tip-duration-in / 4);
- $o-tip-border-radius-duration-in: floor($o-tip-duration-in / 2);
- $o-tip-border-radius-delay-in: floor($o-tip-duration-in * 0);
- $o-tip-bg-color-duration-in: floor($o-tip-duration-in * 1);
- $o-tip-bg-color-delay-in: floor($o-tip-duration-in * 0);
- $o-tip-arrow-duration-in: floor($o-tip-duration-in / 2);
- $o-tip-arrow-delay-in: floor($o-tip-duration-in * 0);
- $o-tip-white-arrow-duration-in: floor($o-tip-duration-in * 1);
- $o-tip-white-arrow-delay-in: floor($o-tip-duration-in * 0);
-
- $o-tip-duration-out: 150ms;
- $o-tip-size-duration-out: floor($o-tip-duration-out * 2 / 3);
- $o-tip-size-delay-out: floor($o-tip-duration-out * 0);
- $o-tip-border-radius-duration-out: floor($o-tip-duration-out * 2 / 3);
- $o-tip-border-radius-delay-out: floor($o-tip-duration-out / 3);
- $o-tip-arrow-duration-out: floor($o-tip-duration-out / 2);
- $o-tip-arrow-delay-out: floor($o-tip-duration-out / 2);
-
- box-sizing: content-box !important;
/*rtl:begin:ignore*/
position: absolute !important;
top: 50% !important;
left: 50% !important;
/*rtl:end:ignore*/
+ z-index: $zindex-tooltip !important; // See comment on 'o_tooltip_parent' class
opacity: 0 !important;
- width: $o-tip-size !important;
- height: $o-tip-size !important;
+ width: $o-tip-width !important;
+ height: $o-tip-width !important; // the shape must be done using transform
margin: 0 !important;
- border: $o-tip-border-width solid $o-tip-color !important;
- border-radius: 50% !important;
- padding: 0 !important; // ! Cannot be changed ! Javascript rely on this.
- z-index: $zindex-tooltip !important; // See comment on 'o_tooltip_parent' class
- background-color: $o-tip-color !important;
- box-shadow: 0 2px 2px 1px rgba(150, 150, 150, 0.3) !important;
+ padding: 0 !important;
- transition:
- width $o-tip-size-duration-out ease $o-tip-size-delay-out,
- height $o-tip-size-duration-out ease $o-tip-size-delay-out,
- margin $o-tip-size-duration-out ease $o-tip-size-delay-out,
- border-radius $o-tip-border-radius-duration-out ease $o-tip-border-radius-delay-out !important;
+ transition: opacity 400ms ease 0ms !important;
&.o_animated {
- animation: move-bottom-top 500ms ease-in 0ms infinite alternate !important;
+ animation: move-bottom-top $o-tip-animation-speed ease-in 0ms infinite alternate !important;
+
&.right, &.left {
animation-name: move-left-right !important;
}
}
+ &.o_tooltip_visible {
+ opacity: 1 !important;
+ }
&.o_tooltip_fixed {
position: fixed !important;
}
+ // Use the ::before element to make the tip shape: a simple filled and
+ // bordered square with one corner and 3 rounded corners, then transformed.
+ // Transform, from right to left: 1) make the arrow point up, 2) scale along
+ // Y axis so that the tip reach the desired height, 3) translate along the Y
+ // axis so that the arrow exactly points at the original square tip border
+ // = the border that will be against the pointed element, 4) rotate the
+ // the shape depending on the tip orientation.
&::before {
content: "";
- border: 0 solid rgba(0, 0, 0, 0);
- transition: all $o-tip-arrow-duration-out ease $o-tip-arrow-delay-out;
- }
- &.right::before {
- @include o-position-absolute($left: -$o-tip-arrow-length+$o-tip-arrow-integration, $top: ($o-tip-size - $o-tip-arrow-width) / 2);
- border-width: $o-tip-arrow-width/2 $o-tip-arrow-length $o-tip-arrow-width/2 0;
- border-right-color: $o-tip-color;
+ @include o-position-absolute(0, 0);
+ width: $o-tip-width; // Not 100% need to stay small and square for close transition
+ height: $o-tip-width;
+ border: $o-tip-border-width solid $o-tip-border-color;
+ border-radius: 0 50% 50% 50%;
+ background: radial-gradient(lighten($o-tip-color, 7%), $o-tip-color);
+ box-shadow: 0 0 40px 2px rgba(255, 255, 255, 0.5);
}
+ $-sqrt-2: 1.4142;
+ $-tip-scale: $o-tip-height / ((1 + $-sqrt-2) * $o-tip-width / 2);
+ $-tip-overflow: ($-sqrt-2 * $-tip-scale - 1) * $o-tip-width / 2;
+ $-tip-translate: $o-tip-anchor-space + $-tip-overflow;
&.top::before {
- /*rtl:begin:ignore*/
- @include o-position-absolute($bottom: -$o-tip-arrow-length+$o-tip-arrow-integration, $left: ($o-tip-size - $o-tip-arrow-width) / 2);
- /*rtl:end:ignore*/
- border-width: $o-tip-arrow-length $o-tip-arrow-width/2 0 $o-tip-arrow-width/2;
- border-top-color: $o-tip-color;
+ transform: rotate(180deg) translateY($-tip-translate) scaleY($-tip-scale) rotate(45deg);
}
- &.left::before {
- @include o-position-absolute($right: -$o-tip-arrow-length+$o-tip-arrow-integration, $top: ($o-tip-size - $o-tip-arrow-width) / 2);
- border-width: $o-tip-arrow-width/2 0 $o-tip-arrow-width/2 $o-tip-arrow-length;
- border-left-color: $o-tip-color;
+ &.right::before {
+ transform: rotate(270deg) translateY($-tip-translate) scaleY($-tip-scale) rotate(45deg);
}
&.bottom::before {
- /*rtl:begin:ignore*/
- @include o-position-absolute($top: -$o-tip-arrow-length+$o-tip-arrow-integration, $left: ($o-tip-size - $o-tip-arrow-width) / 2);
- /*rtl:end:ignore*/
- border-width: 0 $o-tip-arrow-width/2 $o-tip-arrow-length $o-tip-arrow-width/2;
- border-bottom-color: $o-tip-color;
+ transform: rotate(0deg) translateY($-tip-translate) scaleY($-tip-scale) rotate(45deg);
}
-
- &::after {
- content: "";
- @include o-position-absolute(-$o-tip-border-width, -$o-tip-border-width, -$o-tip-border-width, -$o-tip-border-width);
- border-color: $o-tip-color;
- border-radius: 50%;
- transition: margin $o-tip-size-duration-out ease $o-tip-size-delay-out, border-radius $o-tip-duration-out linear 0s;
- background: radial-gradient(lighten($o-tip-color, 7%), $o-tip-color);
+ &.left::before {
+ transform: rotate(90deg) translateY($-tip-translate) scaleY($-tip-scale) rotate(45deg);
}
> .o_tooltip_overlay {
display: none;
@include o-position-absolute(0, 0, 0, 0);
- margin: -$o-tip-border-width;
z-index: -1;
}
> .o_tooltip_content {
overflow: hidden;
- padding: floor($o-tip-size/4) floor($o-tip-size/2);
+ direction: ltr;
+ position: relative;
+ padding: 7px 14px;
+ background-color: inherit;
+ color: transparent;
visibility: hidden;
- transition: visibility 0s ease 0s;
- color: black;
// Force style so that it does not depend on where the tooltip is attached
line-height: $line-height-base;
@@ -155,98 +148,85 @@
}
&.active {
- border-radius: 0 !important;
+ border: $o-tip-border-width solid $o-tip-color !important;
background-color: white !important;
transition:
width $o-tip-size-duration-in ease $o-tip-size-delay-in,
height $o-tip-size-duration-in ease $o-tip-size-delay-in,
- margin $o-tip-size-duration-in ease $o-tip-size-delay-in,
- border-radius $o-tip-border-radius-duration-in ease $o-tip-border-radius-delay-in,
- background-color $o-tip-bg-color-duration-in ease $o-tip-bg-color-delay-in !important;
+ margin $o-tip-size-duration-in ease $o-tip-size-delay-in !important;
&::before {
- transition: all $o-tip-arrow-duration-in ease $o-tip-arrow-delay-in;
- }
- &::after {
- border: 0 solid rgba(0, 0, 0, 0);
+ width: $o-tip-arrow-size;
+ height: $o-tip-arrow-size;
+ border-color: $o-tip-color;
border-radius: 0;
+ background: white;
+ box-shadow: none;
}
> .o_tooltip_overlay {
display: block;
}
> .o_tooltip_content {
- direction: ltr;
+ // Content background must appear immediately to hide the bottom of
+ // the square present to shape the bubble arrow. But text must
+ // appear at the very end.
+ color: black;
visibility: visible;
- transition: visibility 0s ease $o-tip-duration-in;
+ transition: color 0ms ease $o-tip-duration-in;
}
+ $-arrow-offset: ($o-tip-width - $o-tip-arrow-size) / 2 - $o-tip-border-width;
+ $-tip-translate: $o-tip-anchor-space + $o-tip-arrow-size / 2;
&.right {
+ transform: translateX($-tip-translate) !important;
+
&::before {
- left: -$o-tip-arrow-length;
- border-right-color: $o-tip-color;
- }
- &::after {
- @include o-position-absolute($left: -$o-tip-arrow-length+$o-tip-border-width*2, $top: ($o-tip-size - $o-tip-arrow-width) / 2);
- border-width: $o-tip-arrow-width/2 $o-tip-arrow-length $o-tip-arrow-width/2 0;
- border-right-color: white;
- transition: border-right-color $o-tip-white-arrow-duration-in ease $o-tip-white-arrow-delay-in;
+ @include o-position-absolute($left: -$o-tip-arrow-size, $top: $-arrow-offset);
+ transform: translateX(50%) rotate(45deg);
}
}
&.top {
+ transform: translateY(-$-tip-translate) !important;
+
&::before {
- bottom: -$o-tip-arrow-length;
- border-top-color: $o-tip-color;
- }
- &::after {
/*rtl:begin:ignore*/
- @include o-position-absolute($bottom: -$o-tip-arrow-length+$o-tip-border-width*2, $left: ($o-tip-size - $o-tip-arrow-width) / 2);
+ @include o-position-absolute($bottom: -$o-tip-arrow-size, $left: $-arrow-offset);
/*rtl:end:ignore*/
- border-width: $o-tip-arrow-length $o-tip-arrow-width/2 0 $o-tip-arrow-width/2;
- border-top-color: white;
- transition: border-top-color $o-tip-white-arrow-duration-in ease $o-tip-white-arrow-delay-in;
+ transform: translateY(-50%) rotate(45deg);
}
}
&.left {
+ transform: translateX(-$-tip-translate) !important;
+
&::before {
- right: -$o-tip-arrow-length;
- border-left-color: $o-tip-color;
- }
- &::after {
- @include o-position-absolute($right: -$o-tip-arrow-length+$o-tip-border-width*2, $top: ($o-tip-size - $o-tip-arrow-width) / 2);
- border-width: $o-tip-arrow-width/2 0 $o-tip-arrow-width/2 $o-tip-arrow-length;
- border-left-color: white;
- transition: border-left-color $o-tip-white-arrow-duration-in ease $o-tip-white-arrow-delay-in;
+ @include o-position-absolute($right: -$o-tip-arrow-size, $top: $-arrow-offset);
+ transform: translateX(-50%) rotate(45deg);
}
}
&.bottom {
+ transform: translateY($-tip-translate) !important;
+
&::before {
- top: -$o-tip-arrow-length;
- border-bottom-color: $o-tip-color;
- }
- &::after {
/*rtl:begin:ignore*/
- @include o-position-absolute($top: -$o-tip-arrow-length+$o-tip-border-width*2, $left: ($o-tip-size - $o-tip-arrow-width) / 2);
+ @include o-position-absolute($top: -$o-tip-arrow-size, $left: $-arrow-offset);
/*rtl:end:ignore*/
- border-width: 0 $o-tip-arrow-width/2 $o-tip-arrow-length $o-tip-arrow-width/2;
- border-bottom-color: white;
- transition: border-bottom-color $o-tip-white-arrow-duration-in ease $o-tip-white-arrow-delay-in;
+ transform: translateY(50%) rotate(45deg);
}
}
- }
-
- &.inverse {
- &.left, &.right {
- &::before, &.active::after {
- top: auto;
- bottom: ($o-tip-size - $o-tip-arrow-width) / 2;
+ &.inverse {
+ &.left, &.right {
+ &::before {
+ top: auto;
+ bottom: $-arrow-offset;
+ }
}
- }
- &.top, &.bottom {
- &::before, &.active::after {
- left: auto#{"/*rtl:ignore*/"};
- right: ($o-tip-size - $o-tip-arrow-width) / 2#{"/*rtl:ignore*/"};
+ &.top, &.bottom {
+ &::before {
+ left: auto#{"/*rtl:ignore*/"};
+ right: $-arrow-offset#{"/*rtl:ignore*/"};
+ }
}
}
}