Display a tooltip when you hover over a location (#7472)
This commit is contained in:
parent
707f8cd878
commit
309f7bb235
4 changed files with 39 additions and 6 deletions
|
@ -32,6 +32,7 @@ export enum Alignment {
|
||||||
Right,
|
Right,
|
||||||
Top, // Centered
|
Top, // Centered
|
||||||
Bottom, // Centered
|
Bottom, // Centered
|
||||||
|
InnerBottom, // Inside the target, at the bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITooltipProps {
|
export interface ITooltipProps {
|
||||||
|
@ -50,6 +51,8 @@ export interface ITooltipProps {
|
||||||
// id describing tooltip
|
// id describing tooltip
|
||||||
// used to associate tooltip with target for a11y
|
// used to associate tooltip with target for a11y
|
||||||
id?: string;
|
id?: string;
|
||||||
|
// If the parent is over this width, act as if it is only this wide
|
||||||
|
maxParentWidth?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@replaceableComponent("views.elements.Tooltip")
|
@replaceableComponent("views.elements.Tooltip")
|
||||||
|
@ -107,11 +110,18 @@ export default class Tooltip extends React.Component<ITooltipProps> {
|
||||||
offset = Math.floor(parentBox.height - MIN_TOOLTIP_HEIGHT);
|
offset = Math.floor(parentBox.height - MIN_TOOLTIP_HEIGHT);
|
||||||
}
|
}
|
||||||
const width = UIStore.instance.windowWidth;
|
const width = UIStore.instance.windowWidth;
|
||||||
|
const parentWidth = (
|
||||||
|
this.props.maxParentWidth
|
||||||
|
? Math.min(parentBox.width, this.props.maxParentWidth)
|
||||||
|
: parentBox.width
|
||||||
|
);
|
||||||
const baseTop = (parentBox.top - 2 + this.props.yOffset) + window.pageYOffset;
|
const baseTop = (parentBox.top - 2 + this.props.yOffset) + window.pageYOffset;
|
||||||
const top = baseTop + offset;
|
const top = baseTop + offset;
|
||||||
const right = width - parentBox.right - window.pageXOffset - 16;
|
const right = width - parentBox.right - window.pageXOffset - 16;
|
||||||
const left = parentBox.right + window.pageXOffset + 6;
|
const left = parentBox.right + window.pageXOffset + 6;
|
||||||
const horizontalCenter = parentBox.right - window.pageXOffset - (parentBox.width / 2);
|
const horizontalCenter = (
|
||||||
|
parentBox.left - window.pageXOffset + (parentWidth / 2)
|
||||||
|
);
|
||||||
switch (this.props.alignment) {
|
switch (this.props.alignment) {
|
||||||
case Alignment.Natural:
|
case Alignment.Natural:
|
||||||
if (parentBox.right > width / 2) {
|
if (parentBox.right > width / 2) {
|
||||||
|
@ -136,6 +146,10 @@ export default class Tooltip extends React.Component<ITooltipProps> {
|
||||||
style.top = baseTop + parentBox.height;
|
style.top = baseTop + parentBox.height;
|
||||||
style.left = horizontalCenter;
|
style.left = horizontalCenter;
|
||||||
break;
|
break;
|
||||||
|
case Alignment.InnerBottom:
|
||||||
|
style.top = baseTop + parentBox.height - 50;
|
||||||
|
style.left = horizontalCenter;
|
||||||
|
style.transform = "translate(-50%)";
|
||||||
}
|
}
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
|
|
|
@ -36,6 +36,7 @@ const TooltipTarget: React.FC<IProps> = ({
|
||||||
alignment,
|
alignment,
|
||||||
yOffset,
|
yOffset,
|
||||||
tooltipClassName,
|
tooltipClassName,
|
||||||
|
maxParentWidth,
|
||||||
...rest
|
...rest
|
||||||
}) => {
|
}) => {
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
@ -63,6 +64,7 @@ const TooltipTarget: React.FC<IProps> = ({
|
||||||
yOffset={yOffset}
|
yOffset={yOffset}
|
||||||
alignment={alignment}
|
alignment={alignment}
|
||||||
visible={isVisible}
|
visible={isVisible}
|
||||||
|
maxParentWidth={maxParentWidth}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,6 +27,8 @@ import { _t } from '../../../languageHandler';
|
||||||
import MemberAvatar from '../avatars/MemberAvatar';
|
import MemberAvatar from '../avatars/MemberAvatar';
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import LocationViewDialog from '../location/LocationViewDialog';
|
import LocationViewDialog from '../location/LocationViewDialog';
|
||||||
|
import TooltipTarget from '../elements/TooltipTarget';
|
||||||
|
import { Alignment } from '../elements/Tooltip';
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
error: Error;
|
error: Error;
|
||||||
|
@ -93,6 +95,7 @@ export default class MLocationBody extends React.Component<IBodyProps, IState> {
|
||||||
bodyId={this.getBodyId()}
|
bodyId={this.getBodyId()}
|
||||||
markerId={this.getMarkerId()}
|
markerId={this.getMarkerId()}
|
||||||
error={this.state.error}
|
error={this.state.error}
|
||||||
|
tooltip={_t("Expand map")}
|
||||||
onClick={this.onClick}
|
onClick={this.onClick}
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
@ -103,10 +106,17 @@ interface ILocationBodyContentProps {
|
||||||
bodyId: string;
|
bodyId: string;
|
||||||
markerId: string;
|
markerId: string;
|
||||||
error: Error;
|
error: Error;
|
||||||
|
tooltip?: string;
|
||||||
onClick?: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
onClick?: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function LocationBodyContent(props: ILocationBodyContentProps) {
|
export function LocationBodyContent(props: ILocationBodyContentProps) {
|
||||||
|
const mapDiv = <div
|
||||||
|
id={props.bodyId}
|
||||||
|
onClick={props.onClick}
|
||||||
|
className="mx_MLocationBody_map"
|
||||||
|
/>;
|
||||||
|
|
||||||
return <div className="mx_MLocationBody">
|
return <div className="mx_MLocationBody">
|
||||||
{
|
{
|
||||||
props.error
|
props.error
|
||||||
|
@ -115,11 +125,17 @@ export function LocationBodyContent(props: ILocationBodyContentProps) {
|
||||||
</div>
|
</div>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
<div
|
{
|
||||||
id={props.bodyId}
|
props.tooltip
|
||||||
onClick={props.onClick}
|
? <TooltipTarget
|
||||||
className="mx_MLocationBody_map"
|
label={props.tooltip}
|
||||||
/>
|
alignment={Alignment.InnerBottom}
|
||||||
|
maxParentWidth={450}
|
||||||
|
>
|
||||||
|
{ mapDiv }
|
||||||
|
</TooltipTarget>
|
||||||
|
: mapDiv
|
||||||
|
}
|
||||||
<div className="mx_MLocationBody_marker" id={props.markerId}>
|
<div className="mx_MLocationBody_marker" id={props.markerId}>
|
||||||
<div className="mx_MLocationBody_markerBorder">
|
<div className="mx_MLocationBody_markerBorder">
|
||||||
<MemberAvatar
|
<MemberAvatar
|
||||||
|
|
|
@ -2091,6 +2091,7 @@
|
||||||
"Declining …": "Declining …",
|
"Declining …": "Declining …",
|
||||||
"%(name)s wants to verify": "%(name)s wants to verify",
|
"%(name)s wants to verify": "%(name)s wants to verify",
|
||||||
"You sent a verification request": "You sent a verification request",
|
"You sent a verification request": "You sent a verification request",
|
||||||
|
"Expand map": "Expand map",
|
||||||
"Failed to load map": "Failed to load map",
|
"Failed to load map": "Failed to load map",
|
||||||
"Vote not registered": "Vote not registered",
|
"Vote not registered": "Vote not registered",
|
||||||
"Sorry, your vote was not registered. Please try again.": "Sorry, your vote was not registered. Please try again.",
|
"Sorry, your vote was not registered. Please try again.": "Sorry, your vote was not registered. Please try again.",
|
||||||
|
|
Loading…
Reference in a new issue