Skip to content

Commit

Permalink
Switch tgui tooltips to popper.js (tgstation#57992)
Browse files Browse the repository at this point in the history
* Preliminary popper support

* Switch tooltips to popper.js

* Documentation, change DEFAULT_PLACEMENT
  • Loading branch information
Mothblocks authored Mar 27, 2021
1 parent a7cbc00 commit 206c821
Show file tree
Hide file tree
Showing 25 changed files with 258 additions and 281 deletions.
2 changes: 1 addition & 1 deletion tgui/docs/component-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1102,7 +1102,7 @@ Usage:

**Props:**

- `position: string` - Tooltip position.
- `position: string` - Tooltip position. Valid positions are "bottom", "top", "left", and "right". You can affix "-start" and "-end" to achieve something like top left or top right respectively. Default to "top".
- `content: string` - Content of the tooltip. Must be a plain string.
Fragments or other elements are **not** supported.

Expand Down
4 changes: 2 additions & 2 deletions tgui/packages/tgui-panel/Panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const Panel = (props, context) => {
selected={audio.visible}
icon="music"
tooltip="Music player"
tooltipPosition="bottom-left"
tooltipPosition="bottom-start"
onClick={() => audio.toggle()} />
</Stack.Item>
<Stack.Item>
Expand All @@ -60,7 +60,7 @@ export const Panel = (props, context) => {
tooltip={settings.visible
? 'Close settings'
: 'Open settings'}
tooltipPosition="bottom-left"
tooltipPosition="bottom-start"
onClick={() => settings.toggle()} />
</Stack.Item>
</Stack>
Expand Down
33 changes: 22 additions & 11 deletions tgui/packages/tgui/components/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export const Button = props => {
selected,
tooltip,
tooltipPosition,
tooltipOverrideLong,
ellipsis,
compact,
circular,
Expand All @@ -49,7 +48,7 @@ export const Button = props => {
}
// IE8: Use a lowercase "onclick" because synthetic events are fucked.
// IE8: Use an "unselectable" prop because "user-select" doesn't work.
return (
let buttonContent = (
<Box
className={classes([
'Button',
Expand Down Expand Up @@ -106,14 +105,18 @@ export const Button = props => {
rotation={iconRotation}
spin={iconSpin} />
)}
{tooltip && (
<Tooltip
content={tooltip}
overrideLong={tooltipOverrideLong}
position={tooltipPosition} />
)}
</Box>
);

if (tooltip) {
buttonContent = (
<Tooltip content={tooltip} position={tooltipPosition}>
{buttonContent}
</Tooltip>
);
}

return buttonContent;
};

Button.defaultHooks = pureComponentHooks;
Expand Down Expand Up @@ -234,14 +237,13 @@ export class ButtonInput extends Component {
iconSpin,
tooltip,
tooltipPosition,
tooltipOverrideLong,
color = 'default',
placeholder,
maxLength,
...rest
} = this.props;

return (
let buttonContent = (
<Box
className={classes([
'Button',
Expand Down Expand Up @@ -284,12 +286,21 @@ export class ButtonInput extends Component {
{tooltip && (
<Tooltip
content={tooltip}
overrideLong={tooltipOverrideLong}
position={tooltipPosition}
/>
)}
</Box>
);

if (tooltip) {
buttonContent = (
<Tooltip content={tooltip} position={tooltipPosition}>
{buttonContent}
</Tooltip>
);
}

return buttonContent;
}
}

Expand Down
28 changes: 0 additions & 28 deletions tgui/packages/tgui/components/Tooltip.js

This file was deleted.

84 changes: 84 additions & 0 deletions tgui/packages/tgui/components/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { createPopper, Placement } from '@popperjs/core';
import { Component, createPortal, createRef, InfernoNode } from 'inferno';

const DEFAULT_PLACEMENT = "top";

type TooltipProps = {
children?: InfernoNode;
content: string;
position?: Placement;
};

type TooltipState = {
hovered: boolean;
};

export class Tooltip extends Component<TooltipProps, TooltipState> {
containerRef = createRef<HTMLSpanElement>();
tooltipRef = createRef<HTMLDivElement>();
portalNode = document.createElement("div");

constructor() {
super();

this.onMouseEnter = this.onMouseEnter.bind(this);
this.onMouseLeave = this.onMouseLeave.bind(this);

this.state = {
hovered: false,
};
}

componentDidMount() {
document.body.appendChild(this.portalNode);

createPopper(this.containerRef.current, this.tooltipRef.current, {
placement: this.props.position || DEFAULT_PLACEMENT,
});
}

componentWillUnmount() {
document.body.removeChild(this.portalNode);
this.portalNode = null;
}

onMouseEnter() {
this.setState({
hovered: true,
});
}

onMouseLeave() {
this.setState({
hovered: false,
});
}

render() {
const {
children,
content,
}: TooltipProps = this.props;

return (
<>
<span
ref={this.containerRef}
onmouseenter={this.onMouseEnter}
onmouseleave={this.onMouseLeave}
>
{ children }
</span>

{createPortal(
<div class="Tooltip" ref={this.tooltipRef} style={{
opacity: this.state.hovered ? 1 : 0,
}}>
{content}
</div>,
this.portalNode,
)}
</>
);
}
}
6 changes: 3 additions & 3 deletions tgui/packages/tgui/interfaces/BluespaceSender.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const BluespaceSender = (props, context) => {
mr={0.5}
color="transparent"
icon="info"
tooltipPosition="bottom-left"
tooltipPosition="bottom-start"
tooltip={multiline`
Any gas you pipe into here will be added to the Bluespace
Network! That means any connected Bluespace Vendor (multitool)
Expand All @@ -59,13 +59,13 @@ export const BluespaceSender = (props, context) => {
icon={data.on ? 'power-off' : 'times'}
content={data.on ? 'On' : 'Off'}
selected={data.on}
tooltipPosition="bottom-left"
tooltipPosition="bottom-start"
tooltip="Will only take in gases while on."
onClick={() => act('power')} />
<Button
ml={0.5}
content="Retrieve gases"
tooltipPosition="bottom-left"
tooltipPosition="bottom-start"
tooltip="Will transfer any gases inside to the pipe."
onClick={() => act('retrieve')} />
</>
Expand Down
2 changes: 1 addition & 1 deletion tgui/packages/tgui/interfaces/BluespaceVendor.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const BluespaceVendor = (props, context) => {
<Button
color="transparent"
icon="info"
tooltipPosition="bottom-left"
tooltipPosition="bottom-start"
tooltip={multiline`
Quick guide for machine use: prepare a tank to create a
new one in the machine, pick how much you want it filled,
Expand Down
24 changes: 13 additions & 11 deletions tgui/packages/tgui/interfaces/Canister.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,19 @@ export const Canister = (props, context) => {
<LabeledControls.Item
mr={1}
label="Port">
<Box position="relative">
<Icon
size={1.25}
name={portConnected ? 'plug' : 'times'}
color={portConnected ? 'good' : 'bad'} />
<Tooltip
content={portConnected
? 'Connected'
: 'Disconnected'}
position="top" />
</Box>
<Tooltip
content={portConnected
? 'Connected'
: 'Disconnected'}
position="top"
>
<Box position="relative">
<Icon
size={1.25}
name={portConnected ? 'plug' : 'times'}
color={portConnected ? 'good' : 'bad'} />
</Box>
</Tooltip>
</LabeledControls.Item>
</LabeledControls>
</Section>
Expand Down
Loading

0 comments on commit 206c821

Please sign in to comment.