From 2a76461fb8794ea138bd1fd987047386ca25f4f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=BCchele?= Date: Tue, 20 Aug 2019 03:18:32 -0700 Subject: [PATCH] Tooltip components Summary: _typescript_ Reviewed By: passy, bnelo12 Differential Revision: D16830063 fbshipit-source-id: bd0cf3c109caba74ee5a8f9915d46630007702fe --- src/init.tsx | 2 +- src/ui/components/{Tooltip.js => Tooltip.tsx} | 23 ++- ...TooltipProvider.js => TooltipProvider.tsx} | 161 +++++++++++------- .../data-inspector/DataInspector.js | 2 +- src/ui/index.js | 4 +- 5 files changed, 116 insertions(+), 76 deletions(-) rename src/ui/components/{Tooltip.js => Tooltip.tsx} (77%) rename src/ui/components/{TooltipProvider.js => TooltipProvider.tsx} (62%) diff --git a/src/init.tsx b/src/init.tsx index 3f4253218..5058b58e1 100644 --- a/src/init.tsx +++ b/src/init.tsx @@ -18,7 +18,7 @@ import {createStore} from 'redux'; import {persistStore} from 'redux-persist'; import reducers, {Actions, State as StoreState} from './reducers/index'; import dispatcher from './dispatcher/index'; -import TooltipProvider from './ui/components/TooltipProvider.js'; +import TooltipProvider from './ui/components/TooltipProvider'; import config from './utils/processConfig'; import {stateSanitizer} from './utils/reduxDevToolsConfig'; import {initLauncherHooks} from './utils/launcher'; diff --git a/src/ui/components/Tooltip.js b/src/ui/components/Tooltip.tsx similarity index 77% rename from src/ui/components/Tooltip.js rename to src/ui/components/Tooltip.tsx index f241331c8..6864561d7 100644 --- a/src/ui/components/Tooltip.js +++ b/src/ui/components/Tooltip.tsx @@ -5,12 +5,9 @@ * @format */ -import type TooltipProvider from './TooltipProvider.js'; -import type {TooltipOptions} from './TooltipProvider.js'; - -import styled from '../styled/index.js'; -import {Component} from 'react'; - +import TooltipProvider, {TooltipOptions} from './TooltipProvider'; +import styled from 'react-emotion'; +import React, {Component} from 'react'; import PropTypes from 'prop-types'; const TooltipContainer = styled('div')({ @@ -19,14 +16,14 @@ const TooltipContainer = styled('div')({ type TooltipProps = { /** Content shown in the tooltip */ - title: React$Node, + title: React.ReactNode; /** Component that will show the tooltip */ - children: React$Node, - options?: TooltipOptions, + children: React.ReactNode; + options?: TooltipOptions; }; type TooltipState = { - open: boolean, + open: boolean; }; export default class Tooltip extends Component { @@ -35,10 +32,10 @@ export default class Tooltip extends Component { }; context: { - TOOLTIP_PROVIDER: TooltipProvider, + TOOLTIP_PROVIDER: TooltipProvider; }; - ref: ?HTMLDivElement; + ref: HTMLDivElement | null; state = { open: false, @@ -66,7 +63,7 @@ export default class Tooltip extends Component { this.setState({open: false}); }; - setRef = (ref: ?HTMLDivElement) => { + setRef = (ref: HTMLDivElement | null) => { this.ref = ref; }; diff --git a/src/ui/components/TooltipProvider.js b/src/ui/components/TooltipProvider.tsx similarity index 62% rename from src/ui/components/TooltipProvider.js rename to src/ui/components/TooltipProvider.tsx index 99cbfe4b3..efd41f7e6 100644 --- a/src/ui/components/TooltipProvider.js +++ b/src/ui/components/TooltipProvider.tsx @@ -5,11 +5,24 @@ * @format */ -import styled from '../styled/index.js'; -import {colors} from './colors.tsx'; +import styled from 'react-emotion'; +import {colors} from './colors'; import {Component} from 'react'; - import PropTypes from 'prop-types'; +import { + TopProperty, + LeftProperty, + BottomProperty, + RightProperty, + BackgroundColorProperty, + LineHeightProperty, + PaddingProperty, + BorderRadiusProperty, + MaxWidthProperty, + ColorProperty, + WidthProperty, +} from 'csstype'; +import React from 'react'; const defaultOptions = { backgroundColor: colors.blueGrey, @@ -25,33 +38,49 @@ const defaultOptions = { }; export type TooltipOptions = { - backgroundColor?: string, - position?: 'below' | 'above' | 'toRight' | 'toLeft', - color?: string, - showTail?: boolean, - maxWidth?: string, - width?: string, - borderRadius?: number, - padding?: string, - lineHeight?: string, - delay?: number, // in milliseconds + backgroundColor?: string; + position?: 'below' | 'above' | 'toRight' | 'toLeft'; + color?: string; + showTail?: boolean; + maxWidth?: string; + width?: string; + borderRadius?: number; + padding?: string; + lineHeight?: string; + delay?: number; // in milliseconds }; -const TooltipBubble = styled('div')(props => ({ - position: 'absolute', - zIndex: 99999999999, - backgroundColor: props.options.backgroundColor, - lineHeight: props.options.lineHeight, - padding: props.options.padding, - borderRadius: props.options.borderRadius, - width: props.options.width, - maxWidth: props.options.maxWidth, - top: props.top, - left: props.left, - bottom: props.bottom, - right: props.right, - color: props.options.color, -})); +const TooltipBubble = styled('div')( + (props: { + top: TopProperty; + left: LeftProperty; + bottom: BottomProperty; + right: RightProperty; + options: { + backgroundColor: BackgroundColorProperty; + lineHeight: LineHeightProperty; + padding: PaddingProperty; + borderRadius: BorderRadiusProperty; + width: WidthProperty; + maxWidth: MaxWidthProperty; + color: ColorProperty; + }; + }) => ({ + position: 'absolute', + zIndex: 99999999999, + backgroundColor: props.options.backgroundColor, + lineHeight: props.options.lineHeight, + padding: props.options.padding, + borderRadius: props.options.borderRadius, + width: props.options.width, + maxWidth: props.options.maxWidth, + top: props.top, + left: props.left, + bottom: props.bottom, + right: props.right, + color: props.options.color, + }), +); // vertical offset on bubble when position is 'below' const BUBBLE_BELOW_POSITION_VERTICAL_OFFSET = -10; @@ -64,40 +93,50 @@ const TAIL_AB_POSITION_HORIZONTAL_OFFSET = 15; // vertical offset on tail when position is 'toLeft' or 'toRight' const TAIL_LR_POSITION_HORIZONTAL_OFFSET = 5; -const TooltipTail = styled('div')(props => ({ - position: 'absolute', - display: 'block', - whiteSpace: 'pre', - height: '10px', - width: '10px', - lineHeight: '0', - zIndex: 99999999998, - transform: 'rotate(45deg)', - backgroundColor: props.options.backgroundColor, - top: props.top, - left: props.left, - bottom: props.bottom, - right: props.right, -})); +const TooltipTail = styled('div')( + (props: { + top: TopProperty; + left: LeftProperty; + bottom: BottomProperty; + right: RightProperty; + options: { + backgroundColor: BackgroundColorProperty; + }; + }) => ({ + position: 'absolute', + display: 'block', + whiteSpace: 'pre', + height: '10px', + width: '10px', + lineHeight: '0', + zIndex: 99999999998, + transform: 'rotate(45deg)', + backgroundColor: props.options.backgroundColor, + top: props.top, + left: props.left, + bottom: props.bottom, + right: props.right, + }), +); type TooltipProps = { - children: React$Node, + children: React.ReactNode; }; type TooltipObject = { - rect: ClientRect, - title: React$Node, - options: TooltipOptions, + rect: ClientRect; + title: React.ReactNode; + options: TooltipOptions; }; type TooltipState = { - tooltip: ?TooltipObject, - timeoutID: ?TimeoutID, + tooltip: TooltipObject | null | undefined; + timeoutID: ReturnType | null | undefined; }; export default class TooltipProvider extends Component< TooltipProps, - TooltipState, + TooltipState > { static childContextTypes = { TOOLTIP_PROVIDER: PropTypes.object, @@ -112,7 +151,11 @@ export default class TooltipProvider extends Component< return {TOOLTIP_PROVIDER: this}; } - open(container: HTMLDivElement, title: React$Node, options: TooltipOptions) { + open( + container: HTMLDivElement, + title: React.ReactNode, + options: TooltipOptions, + ) { const node = container.childNodes[0]; if (node == null || !(node instanceof HTMLElement)) { return; @@ -153,10 +196,10 @@ export default class TooltipProvider extends Component< return null; } - let left = 'auto'; - let top = 'auto'; - let bottom = 'auto'; - let right = 'auto'; + let left: LeftProperty = 'auto'; + let top: TopProperty = 'auto'; + let bottom: BottomProperty = 'auto'; + let right: RightProperty = 'auto'; if (opts.position === 'below') { left = tooltip.rect.left + TAIL_AB_POSITION_HORIZONTAL_OFFSET; @@ -189,10 +232,10 @@ export default class TooltipProvider extends Component< getTooltipBubble(tooltip: TooltipObject) { const opts = Object.assign(defaultOptions, tooltip.options); - let left = 'auto'; - let top = 'auto'; - let bottom = 'auto'; - let right = 'auto'; + let left: LeftProperty = 'auto'; + let top: TopProperty = 'auto'; + let bottom: BottomProperty = 'auto'; + let right: RightProperty = 'auto'; if (opts.position === 'below') { left = tooltip.rect.left; diff --git a/src/ui/components/data-inspector/DataInspector.js b/src/ui/components/data-inspector/DataInspector.js index 527d80756..e453b6609 100644 --- a/src/ui/components/data-inspector/DataInspector.js +++ b/src/ui/components/data-inspector/DataInspector.js @@ -8,7 +8,7 @@ import DataDescription from './DataDescription.js'; import {Component} from 'react'; import ContextMenu from '../ContextMenu.js'; -import Tooltip from '../Tooltip.js'; +import Tooltip from '../Tooltip.tsx'; import styled from '../../styled/index.js'; import DataPreview from './DataPreview.js'; import createPaste from '../../../fb-stubs/createPaste.tsx'; diff --git a/src/ui/index.js b/src/ui/index.js index 6e1affdc2..06040eb70 100644 --- a/src/ui/index.js +++ b/src/ui/index.js @@ -130,8 +130,8 @@ export {default as TextParagraph} from './components/TextParagraph.tsx'; export {default as Link} from './components/Link.js'; export {default as PathBreadcrumbs} from './components/PathBreadcrumbs.tsx'; export {default as ModalOverlay} from './components/ModalOverlay.tsx'; -export {default as Tooltip} from './components/Tooltip.js'; -export {default as TooltipProvider} from './components/TooltipProvider.js'; +export {default as Tooltip} from './components/Tooltip.tsx'; +export {default as TooltipProvider} from './components/TooltipProvider.tsx'; export {default as ResizeSensor} from './components/ResizeSensor.tsx'; export {default as StatusIndicator} from './components/StatusIndicator.tsx';