From 2c8d29818f92264583f863f7189ff455d659d00b Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Fri, 8 Oct 2021 23:23:26 +0530 Subject: [PATCH 1/4] added tooltip sense --- src/CONST.js | 1 + src/components/Tooltip/TooltipSense.js | 26 +++++++++++++++++ src/components/Tooltip/index.js | 40 +++++++++++++++++++------- 3 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 src/components/Tooltip/TooltipSense.js diff --git a/src/CONST.js b/src/CONST.js index 5b12ef437efd..bdc26ba86f62 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -213,6 +213,7 @@ const CONST = { SIDEBAR_LOADED: 'sidebar_loaded', COLD: 'cold', REPORT_ACTION_ITEM_LAYOUT_DEBOUNCE_TIME: 1500, + TOOLTIP_SENSE: 1000, }, PRIORITY_MODE: { GSD: 'gsd', diff --git a/src/components/Tooltip/TooltipSense.js b/src/components/Tooltip/TooltipSense.js new file mode 100644 index 000000000000..b2fd88c79b03 --- /dev/null +++ b/src/components/Tooltip/TooltipSense.js @@ -0,0 +1,26 @@ +import _ from 'underscore'; +import CONST from '../../CONST'; + +let active = false; +const debouncedDeactivate = _.debounce(() => { + active = false; +}, CONST.TIMING.TOOLTIP_SENSE); + +function activate() { + active = true; + debouncedDeactivate.cancel(); +} + +function isActive() { + return active === true; +} + +function deactivate() { + return debouncedDeactivate(); +} + +export default { + activate, + deactivate, + isActive, +}; diff --git a/src/components/Tooltip/index.js b/src/components/Tooltip/index.js index 093f0a8b9ae1..d10d53498233 100644 --- a/src/components/Tooltip/index.js +++ b/src/components/Tooltip/index.js @@ -5,6 +5,7 @@ import TooltipRenderedOnPageBody from './TooltipRenderedOnPageBody'; import Hoverable from '../Hoverable'; import withWindowDimensions from '../withWindowDimensions'; import {propTypes, defaultProps} from './TooltipPropTypes'; +import TooltipSense from './TooltipSense'; class Tooltip extends PureComponent { constructor(props) { @@ -36,6 +37,9 @@ class Tooltip extends PureComponent { this.tooltip = null; this.isComponentMounted = false; + + // Whether the tooltip is first tooltip to activate the TooltipSense + this.isTooltipSenseInitiator = false; this.shouldStartShowAnimation = false; this.animation = new Animated.Value(0); @@ -131,12 +135,19 @@ class Tooltip extends PureComponent { // We may need this check due to the reason that the animation start will fire async // and hideTooltip could fire before it thus keeping the Tooltip visible if (this.shouldStartShowAnimation) { - Animated.timing(this.animation, { - toValue: 1, - duration: 140, - delay: 500, - useNativeDriver: false, - }).start(); + // When TooltipSense is active, immediately show the tooltip + if (TooltipSense.isActive()) { + this.animation.setValue(1); + } else { + this.isTooltipSenseInitiator = true; + Animated.timing(this.animation, { + toValue: 1, + duration: 140, + delay: 500, + useNativeDriver: false, + }).start(); + } + TooltipSense.activate(); } }); } @@ -147,11 +158,18 @@ class Tooltip extends PureComponent { hideTooltip() { this.animation.stopAnimation(); this.shouldStartShowAnimation = false; - Animated.timing(this.animation, { - toValue: 0, - duration: 140, - useNativeDriver: false, - }).start(); + if (TooltipSense.isActive() && !this.isTooltipSenseInitiator) { + this.animation.setValue(0); + } else { + // Hide the first tooltip which initiated the TooltipSense with animation + this.isTooltipSenseInitiator = false; + Animated.timing(this.animation, { + toValue: 0, + duration: 140, + useNativeDriver: false, + }).start(); + } + TooltipSense.deactivate(); } render() { From fe815727b79b5d4417d062379ce9304c6fb90555 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Mon, 11 Oct 2021 11:51:24 +0530 Subject: [PATCH 2/4] cleanup --- src/components/Tooltip/TooltipSense.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/Tooltip/TooltipSense.js b/src/components/Tooltip/TooltipSense.js index b2fd88c79b03..9d914706bdfc 100644 --- a/src/components/Tooltip/TooltipSense.js +++ b/src/components/Tooltip/TooltipSense.js @@ -2,6 +2,10 @@ import _ from 'underscore'; import CONST from '../../CONST'; let active = false; + +/** + * Debounced function to deactive the TooltipSense after a specific time +*/ const debouncedDeactivate = _.debounce(() => { active = false; }, CONST.TIMING.TOOLTIP_SENSE); @@ -11,14 +15,14 @@ function activate() { debouncedDeactivate.cancel(); } -function isActive() { - return active === true; -} - function deactivate() { return debouncedDeactivate(); } +function isActive() { + return active === true; +} + export default { activate, deactivate, From 715da57d774fa6d9becf5c6d931421b263f07ffe Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Mon, 11 Oct 2021 13:57:33 +0530 Subject: [PATCH 3/4] Add tooltips --- src/components/AvatarWithImagePicker.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/components/AvatarWithImagePicker.js b/src/components/AvatarWithImagePicker.js index b677a9ab5f23..beedd26ef8da 100644 --- a/src/components/AvatarWithImagePicker.js +++ b/src/components/AvatarWithImagePicker.js @@ -17,6 +17,7 @@ import withLocalize, {withLocalizePropTypes} from './withLocalize'; import variables from '../styles/variables'; import CONST from '../CONST'; import SpinningIndicatorAnimation from '../styles/animation/SpinningIndicatorAnimation'; +import Tooltip from './Tooltip'; const propTypes = { /** Avatar URL to display */ @@ -174,14 +175,16 @@ class AvatarWithImagePicker extends React.Component { ) : ( <> - - - + + + + + this.setState({isMenuVisible: false})} From f7cb4c103d4e459026ceca42496d696038e58ae1 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Tue, 12 Oct 2021 22:36:48 +0530 Subject: [PATCH 4/4] add tooltips --- src/components/AttachmentView.js | 8 ++++---- src/components/FAB/FAB.js | 28 +++++++++++++++----------- src/languages/en.js | 2 +- src/languages/es.js | 2 +- src/pages/home/sidebar/SidebarLinks.js | 24 ++++++++++++---------- src/styles/styles.js | 1 + 6 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/components/AttachmentView.js b/src/components/AttachmentView.js index dd0c3109ba5a..83b7b37e6775 100755 --- a/src/components/AttachmentView.js +++ b/src/components/AttachmentView.js @@ -64,11 +64,11 @@ const AttachmentView = (props) => { {props.file && props.file.name} {props.shouldShowDownloadIcon && ( - - + + - - + + )} ); diff --git a/src/components/FAB/FAB.js b/src/components/FAB/FAB.js index 748c3245fad4..17cb9930dd51 100644 --- a/src/components/FAB/FAB.js +++ b/src/components/FAB/FAB.js @@ -7,6 +7,8 @@ import {Plus} from '../Icon/Expensicons'; import styles, {getAnimatedFABStyle} from '../../styles/styles'; import themeColors from '../../styles/themes/default'; import fabPropTypes from './fabPropTypes'; +import Tooltip from '../Tooltip'; +import withLocalize from '../withLocalize'; const AnimatedIcon = Animated.createAnimatedComponent(Icon); AnimatedIcon.displayName = 'AnimatedIcon'; @@ -58,20 +60,22 @@ class FAB extends PureComponent { }); return ( - - - + + + + + ); } } FAB.propTypes = fabPropTypes; -export default FAB; +export default withLocalize(FAB); diff --git a/src/languages/en.js b/src/languages/en.js index 7f7ecf8c5217..587324218ef4 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -8,7 +8,7 @@ export default { attachment: 'Attachment', to: 'To', optional: 'Optional', - new: 'NEW', + new: 'New', search: 'Search', next: 'Next', goBack: 'Go back', diff --git a/src/languages/es.js b/src/languages/es.js index fa9b594af0ee..08878a6897f3 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -8,7 +8,7 @@ export default { attachment: 'Archivo adjunto', to: 'A', optional: 'Opcional', - new: 'NUEVO', + new: 'Nuevo', search: 'Buscar', next: 'Siguiente', goBack: 'Regresar', diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 360cd87796bc..b3a4101371a1 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -152,17 +152,19 @@ class SidebarLinks extends React.Component { - - - + + + + +