diff --git a/src/content/components/FlameChartCanvas.css b/src/content/components/FlameChartCanvas.css index 32ee31766bb..901c228567c 100644 --- a/src/content/components/FlameChartCanvas.css +++ b/src/content/components/FlameChartCanvas.css @@ -8,6 +8,10 @@ left: 0; } +/** + * This tooltip is multi-line and more intense, so add additional whitespace to make it + * more readable. + */ .flameChartCanvasTooltip { padding: 5px; } diff --git a/src/content/components/IntervalMarkerOverview.js b/src/content/components/IntervalMarkerOverview.js index 33d7db2f11e..545afa4cdc6 100644 --- a/src/content/components/IntervalMarkerOverview.js +++ b/src/content/components/IntervalMarkerOverview.js @@ -157,7 +157,7 @@ class IntervalMarkerOverview extends PureComponent { this._scheduleDraw(); const { className, isSelected } = this.props; const { mouseDownItem, hoveredItem, mouseX, mouseY } = this.state; - const tooltipText = !mouseDownItem && hoveredItem ? hoveredItem.title : null; + const tooltipContents = !mouseDownItem && hoveredItem ? hoveredItem.title : null; const canvasClassName = className.split(' ').map(name => `${name}Canvas`).join(' '); return ( @@ -169,12 +169,12 @@ class IntervalMarkerOverview extends PureComponent { onMouseUp={this._onMouseUp} onMouseOut={this._onMouseOut}/> { - tooltipText + tooltipContents ? - {tooltipText} + {tooltipContents} : null } diff --git a/src/content/components/TimelineCanvas.js b/src/content/components/TimelineCanvas.js index 9141f2e6ff8..63183125d67 100644 --- a/src/content/components/TimelineCanvas.js +++ b/src/content/components/TimelineCanvas.js @@ -151,7 +151,7 @@ export default class TimelineCanvas extends Component { hover: hoveredItem !== null, }); - const tooltipText = this._getHoveredItemInfo(); + const tooltipContents = this._getHoveredItemInfo(); return (
@@ -161,11 +161,10 @@ export default class TimelineCanvas extends Component { onMouseOut={this._onMouseOut} onDoubleClick={this._onDoubleClick} /> { - !isDragging && tooltipText + !isDragging && tooltipContents ? - {tooltipText} + mouseY={mouseY}> + {tooltipContents} : null } diff --git a/src/content/components/Tooltip.css b/src/content/components/Tooltip.css index 4ef214b9f5f..5dd1ecc8d14 100644 --- a/src/content/components/Tooltip.css +++ b/src/content/components/Tooltip.css @@ -13,8 +13,9 @@ .tooltip { position: relative; max-width: 100%; - padding: 2px 5px; + box-sizing: border-box; display: inline-block; + padding: 2px 5px; border: 1px solid #ccc; background-color: #f9f9f9; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); @@ -67,3 +68,46 @@ width: 60px; color: var(--theme-highlight-gray); } + +.tooltipTiming { + padding-right: 0.5em; + color: var(--theme-highlight-green); + font-weight: bold; +} + +.tooltipOneLine { + display: flex; + max-width: 100%; + white-space: nowrap; + text-overflow: ellipsis; +} + +.tooltipName { + flex: 1; + text-overflow: ellipsis; + overflow: hidden; +} + +.tooltipSwatch { + width: 10px; + height: 10px; + display: inline-block; + border: 1px solid #888; + margin-right: 3px; +} + +.tooltipHeader { + padding-bottom: 10px; + margin-bottom: 10px; + border-bottom: 1px solid var(--theme-highlight-gray); +} + +.tooltipDetails { + margin: 5px 0; +} + +.tooltipLabel { + display: block; + width: 60px; + color: #666; +} diff --git a/src/content/components/Tooltip.js b/src/content/components/Tooltip.js index 20091eaa0be..708946441d3 100644 --- a/src/content/components/Tooltip.js +++ b/src/content/components/Tooltip.js @@ -22,7 +22,7 @@ export default class Tooltip extends PureComponent { state: { interiorElement: HTMLElement | null, - interiorElementRAF: HTMLElement | null, + isNewContentLaidOut: boolean, }; _isMounted: boolean; @@ -30,14 +30,14 @@ export default class Tooltip extends PureComponent { constructor(props: Props) { super(props); - (this: any)._getMountElement = this._getMountElement.bind(this); + (this: any)._setMountElement = this._setMountElement.bind(this); this.state = { interiorElement: null, - interiorElementRAF: null, + isNewContentLaidOut: false, }; } - _getMountElement(el: HTMLElement) { + _setMountElement(el: HTMLElement) { this.setState({ interiorElement: el }); } @@ -67,26 +67,34 @@ export default class Tooltip extends PureComponent { componentWillReceiveProps(nextProps: Props) { if (nextProps.children !== this.props.children) { - this.setState({interiorElementRAF: null }); - this._allowInteriorElementLayout(); + // If the children are different, allow them to do an initial lay out on the DOM. + this.setState({isNewContentLaidOut: false }); + this._forceUpdateAfterRAF(); } } componentDidUpdate() { - this._allowInteriorElementLayout(); + // Force an additional update to this component if the children content is + // different as it needs to fully lay out one time on the DOM to proper calculate + // sizing and positioning. + const { interiorElement, isNewContentLaidOut } = this.state; + if (interiorElement && !isNewContentLaidOut) { + this._forceUpdateAfterRAF(); + } + this._renderTooltipContents(); } - _allowInteriorElementLayout() { - const { interiorElement, interiorElementRAF } = this.state; - if (interiorElement && !interiorElementRAF) { - // Allow the interior element to fully lay out, then update the sizing. - requestAnimationFrame(() => { - if (this._isMounted) { - this.setState({ interiorElementRAF: interiorElement }); - } - }); - } + /** + * Children content needs to be on the DOM (not just virtual DOM) in order to correctly + * calculate the sizing and positioning of the tooltip. + */ + _forceUpdateAfterRAF() { + requestAnimationFrame(() => { + if (this._isMounted) { + this.setState({ isNewContentLaidOut: true }); + } + }); } /** @@ -116,14 +124,14 @@ export default class Tooltip extends PureComponent { }; ReactDOM.render( -
- {children} -
, +
+ {children} +
, this._mountElement ); } render() { - return
; + return null; } }