diff --git a/src/components/decorators/has-tutorial-tip.es6 b/src/components/decorators/has-tutorial-tip.es6 index 8fa963493..28a31d4db 100644 --- a/src/components/decorators/has-tutorial-tip.es6 +++ b/src/components/decorators/has-tutorial-tip.es6 @@ -2,7 +2,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import _ from 'underscore'; -import {Actions} from 'nylas-exports'; +import {Actions, WorkspaceStore} from 'nylas-exports'; import NylasStore from 'nylas-store'; const TipsBackgroundEl = document.createElement('tutorial-tip-background'); @@ -104,13 +104,19 @@ export default function HasTutorialTip(ComposedComponent, TipConfig) { constructor(props) { super(props); + this._unlisteners = []; this.state = {visible: false}; } componentDidMount() { TipsStore.mountedTip(TipKey); - this._unlisten = TipsStore.listen(this._onTooltipStateChanged); + this._unlisteners = [ + TipsStore.listen(this._onTooltipStateChanged), + WorkspaceStore.listen(() => { + this._workspaceTimer = setTimeout(this._onTooltipStateChanged, 0); + }), + ] window.addEventListener('resize', this._onRecomputeTooltipPosition); // unfortunately, we can't render() a container around ComposedComponent @@ -134,16 +140,28 @@ export default function HasTutorialTip(ComposedComponent, TipConfig) { } componentWillUnmount() { - this._unlisten(); + for (const unlisten of this._unlisteners) { + unlisten(); + } window.removeEventListener('resize', this._onRecomputeTooltipPosition); document.body.removeChild(this.tipNode); + clearTimeout(this._workspaceTimer); TipsStore.unmountedTip(TipKey); } + _containingSheetIsVisible = () => { + const el = ReactDOM.findDOMNode(this); + const sheetEl = el.closest('.sheet') || el.closest('.sheet-toolbar-container'); + if (!sheetEl) { + return true; + } + return (sheetEl.dataset.id === WorkspaceStore.topSheet().id); + } + _onTooltipStateChanged = () => { - const visible = TipsStore.isTipVisible(TipKey); + const visible = TipsStore.isTipVisible(TipKey) && this._containingSheetIsVisible(); if (this.state.visible !== visible) { this.setState({visible}); @@ -165,15 +183,12 @@ export default function HasTutorialTip(ComposedComponent, TipConfig) { el.removeEventListener('mouseover', this._onMouseOver); const tipRect = this.tipNode.getBoundingClientRect(); + const tipFocusCircleRadius = 64; const rect = ReactDOM.findDOMNode(this).getBoundingClientRect(); - const rectCX = rect.left + rect.width / 2; - const rectCY = rect.top + rect.height / 2; - TipsBackgroundEl.style.background = ` - -webkit-radial-gradient( - ${Math.round(rectCX / window.innerWidth * 100)}% - ${Math.round(rectCY / window.innerHeight * 100)}%, - circle, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) 3%, rgba(0, 0, 0, 0.2) 5%) - `; + const rectCX = Math.round(rect.left + rect.width / 2 - tipFocusCircleRadius); + const rectCY = Math.round(rect.top + rect.height / 2 - tipFocusCircleRadius); + TipsBackgroundEl.style.webkitMaskPosition = `0 0, ${rectCX}px ${rectCY}px`; + Actions.openPopover(( -
+
{toolbars}
diff --git a/static/components/tutorial-overlay.less b/static/components/tutorial-overlay.less index a3c68b6e3..653e7b998 100644 --- a/static/components/tutorial-overlay.less +++ b/static/components/tutorial-overlay.less @@ -4,11 +4,15 @@ tutorial-tip-background { left: 0; right: 0; bottom: 0; - background: -webkit-radial-gradient(50% 50%, circle, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 4%, rgba(0,0,0,0.2) 7%); z-index: 20; pointer-events: none; opacity: 0; transition: opacity ease-in-out 250ms; + background-color: rgba(0,0,0,0.25); + -webkit-mask-image: linear-gradient(to top, #fff 0%, #aaa 100%), url("data:image/png;base64,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"); + -webkit-mask-composite: xor; + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: 100% 100%, 128px 128px; } tutorial-tip-background.visible { @@ -30,6 +34,7 @@ tutorial-tip-background.visible { background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(241, 170, 211)), to(rgb(185, 59, 255))); opacity: 0; transition: opacity ease-out 100ms; + box-shadow: 0 1px 2px rgba(0,0,0,0.2); } .tutorial-tip.visible { @@ -47,32 +52,32 @@ body { height: 100%; border-radius: 50%; content: ''; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - box-shadow: 0 0 0 2px rgb(241, 170, 211); + border: 1px solid rgb(185, 59, 255); + transform-origin: 0.4 0.4; - animation: sonarEffect 2s ease-out 75ms; + animation: sonarEffect 3s ease-out 75ms; animation-iteration-count: infinite; + animation-delay: 1s; } @-webkit-keyframes sonarEffect { 0% { - opacity: 0.3; - } - 40% { - opacity: 0.7; - box-shadow: 0 0 0 2px rgba(255,255,255,0.1), 0 0 10px 10px #fff, 0 0 0 10px rgba(255,255,255,0.5); - } - 80% { - box-shadow: 0 0 0 2px rgba(255,255,255,0.1), 0 0 10px 10px #fff, 0 0 0 10px rgba(255,255,255,0.5); - -webkit-transform: scale(1.4); - opacity: 0.5; - } - 100% { - box-shadow: 0 0 0 2px rgba(255,255,255,0.1), 0 0 10px 10px #fff, 0 0 0 10px rgba(255,255,255,0.5); - -webkit-transform: scale(1.5); opacity: 0; } + 60% { + opacity: 0; + } + 65% { + opacity: 0.5; + transform: scale3d(1, 1, 1); + } + 80% { + opacity: 0.4; + transform: scale3d(2.6, 2.6, 2.6); + } + 100% { + opacity: 0; + transform: scale3d(3, 3, 3); + } }