From 22219e0e802cc58eb3a6d507a2221ec9fc4ad64f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 14 Apr 2021 21:13:09 -0600 Subject: [PATCH] Adapt to use an Alignment enum instead --- src/components/views/elements/Field.tsx | 2 +- src/components/views/elements/InfoTooltip.tsx | 6 +-- src/components/views/elements/Tooltip.tsx | 48 ++++++++++++++++--- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/components/views/elements/Field.tsx b/src/components/views/elements/Field.tsx index f5754da9ae..59d9a11596 100644 --- a/src/components/views/elements/Field.tsx +++ b/src/components/views/elements/Field.tsx @@ -262,7 +262,7 @@ export default class Field extends React.PureComponent { tooltipClassName={classNames("mx_Field_tooltip", tooltipClassName)} visible={(this.state.focused && this.props.forceTooltipVisible) || this.state.feedbackVisible} label={tooltipContent || this.state.feedback} - forceOnRight + alignment={Tooltip.Alignment.Right} />; } diff --git a/src/components/views/elements/InfoTooltip.tsx b/src/components/views/elements/InfoTooltip.tsx index 8f7f1ea53f..d49090dbae 100644 --- a/src/components/views/elements/InfoTooltip.tsx +++ b/src/components/views/elements/InfoTooltip.tsx @@ -18,8 +18,8 @@ limitations under the License. import React from 'react'; import classNames from 'classnames'; -import Tooltip from './Tooltip'; -import { _t } from "../../../languageHandler"; +import Tooltip, {Alignment} from './Tooltip'; +import {_t} from "../../../languageHandler"; import {replaceableComponent} from "../../../utils/replaceableComponent"; interface ITooltipProps { @@ -61,7 +61,7 @@ export default class InfoTooltip extends React.PureComponent :
; return (
diff --git a/src/components/views/elements/Tooltip.tsx b/src/components/views/elements/Tooltip.tsx index b2dd00de18..116b226b8f 100644 --- a/src/components/views/elements/Tooltip.tsx +++ b/src/components/views/elements/Tooltip.tsx @@ -25,6 +25,14 @@ import {replaceableComponent} from "../../../utils/replaceableComponent"; const MIN_TOOLTIP_HEIGHT = 25; +export enum Alignment { + Natural, // Pick left or right + Left, + Right, + Top, // Centered + Bottom, // Centered +} + interface IProps { // Class applied to the element used to position the tooltip className?: string; @@ -36,7 +44,7 @@ interface IProps { visible?: boolean; // the react element to put into the tooltip label: React.ReactNode; - forceOnRight?: boolean; + alignment?: Alignment; // defaults to Natural yOffset?: number; } @@ -46,10 +54,14 @@ export default class Tooltip extends React.Component { private tooltip: void | Element | Component; private parent: Element; + // XXX: This is because some components (Field) are unable to `import` the Tooltip class, + // so we expose the Alignment options off of us statically. + public static readonly Alignment = Alignment; public static readonly defaultProps = { visible: true, yOffset: 0, + alignment: Alignment.Natural, }; // Create a wrapper for the tooltip outside the parent and attach it to the body element @@ -86,11 +98,35 @@ export default class Tooltip extends React.Component { offset = Math.floor(parentBox.height - MIN_TOOLTIP_HEIGHT); } - style.top = (parentBox.top - 2 + this.props.yOffset) + window.pageYOffset + offset; - if (!this.props.forceOnRight && parentBox.right > window.innerWidth / 2) { - style.right = window.innerWidth - parentBox.right - window.pageXOffset - 16; - } else { - style.left = parentBox.right + window.pageXOffset + 6; + const baseTop = (parentBox.top - 2 + this.props.yOffset) + window.pageYOffset; + const top = baseTop + offset; + const right = window.innerWidth - parentBox.right - window.pageXOffset - 16; + const left = parentBox.right + window.pageXOffset + 6; + const horizontalCenter = parentBox.right - window.pageXOffset - (parentBox.width / 2); + switch(this.props.alignment) { + case Alignment.Natural: + if (parentBox.right > window.innerWidth / 2) { + style.right = right; + style.top = top; + break; + } + // fall through to Right + case Alignment.Right: + style.left = left; + style.top = top; + break; + case Alignment.Left: + style.right = right; + style.top = top; + break; + case Alignment.Top: + style.top = baseTop - 16; + style.left = horizontalCenter; + break; + case Alignment.Bottom: + style.top = baseTop + parentBox.height; + style.left = horizontalCenter; + break; } return style;