summaryrefslogtreecommitdiff
path: root/addons/web_tour
diff options
context:
space:
mode:
authorqsm-odoo <qsm@odoo.com>2020-11-13 10:28:50 +0000
committerqsm-odoo <qsm@odoo.com>2020-11-13 15:05:43 +0000
commitdbf966f6f012ccf5aa9b501586e2aa0fde05be5d (patch)
treeec5b9bb2fabce8e8d1d63ec9a21c1c322ac555f7 /addons/web_tour
parentff648a0ace9cf72274211662707e7ee33fc73252 (diff)
[FIX] web_tour: review tour tips design
We noticed users may have difficulties noticing where the tip is in the page, even when searching explicitly for it. This commit reviews the design and improves the scss: the tip shape is now made of an unique transformed element with a white border all around. The box shadow was also made more visible. The visibility over white elements stays the same as before but it is now way more visible over dark content (like the website editor panel). task-2357170 closes odoo/odoo#61708 Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Diffstat (limited to 'addons/web_tour')
-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*/"};
+ }
}
}
}