Skip to content

Commit

Permalink
fix: move tooltip showing logic into styles & improve visibility control
Browse files Browse the repository at this point in the history
  • Loading branch information
wallwhite committed Jan 11, 2022
1 parent a722779 commit f07d6ba
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 43 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

120 changes: 111 additions & 9 deletions pages/tooltip.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -98,24 +98,24 @@ import { Tooltip, Button, Grid, GridRow, GridCell } from '../src/ui';
</Tooltip>
```

## Tooltip controlled from outside
## Tooltip force showing

export const ControlledTooltip = () => {
const [isVisible, setIsVisible] = React.useState(false);
const tooltipBehaviorTitle = isVisible ? 'always visible' : 'normal'
return (
<Grid>
<GridRow>
<GridCell>
<Button onClick={() => setIsVisible(current=>!current)}>
Toggle tooltip
Toggle behavior: {tooltipBehaviorTitle}
</Button>
</GridCell>
<GridCell>
<Tooltip
position="top"
content="Hi there! I'm controlled by a parent."
forceIsVisible={isVisible}
onVisibleTooltipChange={setIsVisible}
content={`Hi there! I'm ${tooltipBehaviorTitle} tooltip.`}
forceShow={isVisible}
>
<Button>
Button with tooltip
Expand All @@ -131,15 +131,117 @@ export const ControlledTooltip = () => {

```
const [isVisible, setIsVisible] = React.useState(false);
const tooltipBehaviorTitle = isVisible ? 'always visible' : 'normal'
<Button onClick={() => setIsVisible(current=>!current)}>
Toggle tooltip
Toggle behavior: {tooltipBehaviorTitle}
</Button>
<Tooltip
position="top"
content="Hi there! I'm controlled by a parent."
forceIsVisible={isVisible}
onVisibleTooltipChange={setIsVisible}
content={`Hi there! I'm ${tooltipBehaviorTitle} tooltip.`}
forceShow={isVisible}
>
<Button>
Button with tooltip
</Button>
</Tooltip>
```

## Tooltip force hidding

export const HiddenTooltip = () => {
const [isHidden, setIsHidden] = React.useState(false);
const tooltipBehaviorTitle = isHidden ? 'always hidden' : 'normal';
return (
<Grid>
<GridRow>
<GridCell>
<Button onClick={() => setIsHidden(current=>!current)}>
Toggle behavior: {tooltipBehaviorTitle}
</Button>
</GridCell>
<GridCell>
<Tooltip
position="top"
content={`Hi there! I'm ${tooltipBehaviorTitle} tooltip.`}
forceHide={isHidden}
>
<Button>
Button with tooltip
</Button>
</Tooltip>
</GridCell>
</GridRow>
</Grid>
);
};

<HiddenTooltip />

```
const [isHidden, setIsHidden] = React.useState(false);
const tooltipBehaviorTitle = isHidden ? 'always hidden' : 'normal';
<Button onClick={() => setIsHidden(current=>!current)}>
Toggle behavior: {tooltipBehaviorTitle}
</Button>
<Tooltip
position="top"
content={`Hi there! I'm ${tooltipBehaviorTitle} tooltip.`}
forceHide={isHidden}
>
<Button>
Button with tooltip
</Button>
</Tooltip>
```

## Fully controlled

export const FullyControlledTooltip = () => {
const [isVisible, setIsVisible] = React.useState(false);
const tooltipBehaviorTitle = isVisible ? 'always visible' : 'always hidden';
return (
<Grid>
<GridRow>
<GridCell>
<Button onClick={() => setIsVisible(current=>!current)}>
Toggle behavior: {tooltipBehaviorTitle}
</Button>
</GridCell>
<GridCell>
<Tooltip
position="top"
content={`Hi there! I'm ${tooltipBehaviorTitle} tooltip.`}
forceShow={isVisible}
forceHide={!isVisible}
>
<Button>
Button with tooltip
</Button>
</Tooltip>
</GridCell>
</GridRow>
</Grid>
);
};

<FullyControlledTooltip />

```
const [isVisible, setIsVisible] = React.useState(false);
const tooltipBehaviorTitle = isVisible ? 'always visible' : 'always hidden';
<Button onClick={() => setIsVisible(current=>!current)}>
Toggle behavior: {tooltipBehaviorTitle}
</Button>
<Tooltip
position="top"
content={`Hi there! I'm ${tooltipBehaviorTitle} tooltip.`}
forceShow={isVisible}
forceHide={!isVisible}
>
<Button>
Button with tooltip
Expand Down
20 changes: 20 additions & 0 deletions src/Tooltip/Tooltip.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,37 @@
position: relative;
display: inline-block;

&:hover {
.tooltip {
&-message {
@include visibility(visible, 1);

&.-hide {
@include visibility(hidden, 0);
}
}

}
}

&-message {
@include visibility(hidden, 0);
position: absolute;
min-width: 350px;
max-width: 350px;
width: 100%;
z-index: 10;
transition: all .1s linear;

&::after {
content: '';
position: absolute;
}

&.-show {
@include visibility(visible, 1);
}

&.-custom-width {
min-width: fit-content;
max-width: fit-content;
Expand Down
46 changes: 14 additions & 32 deletions src/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,41 @@
import React, { useState, useEffect } from 'react';
import React from 'react';
import cx from 'clsx';

interface Tooltip {
content: React.ReactNode;
position: 'top' | 'bottom' | 'left' | 'right';
maxWidth?: number | string;
forceIsVisible?: boolean;
onVisibleTooltipChange?: (isVisible: boolean) => void;
forceShow?: boolean;
forceHide?: boolean;
}

const Tooltip: React.FC<Tooltip> = ({
children,
content,
position,
maxWidth,
forceIsVisible = false,
onVisibleTooltipChange,
forceShow = false,
forceHide = false,
}) => {
const [isVisible, setIsVisible] = useState(forceIsVisible);

const messageStyles = maxWidth && { width: maxWidth };

const messageStyles = maxWidth ? ({ width: maxWidth } as React.CSSProperties) : {};
const messageClassNames = cx(
'tooltip-message',
`-${position}`,
{
'-show': forceShow,
'-hide': forceHide,
'-custom-width': !!maxWidth,
}
);

const handleChangeVisibility = (nextIsVisible: boolean) => {
setIsVisible(nextIsVisible);
onVisibleTooltipChange?.(nextIsVisible);
};

const showTooltip = () => handleChangeVisibility(true);

const hideTooltip = () => handleChangeVisibility(false);

useEffect(() => setIsVisible(forceIsVisible), [forceIsVisible]);

return (
<div className="tooltip" onMouseLeave={hideTooltip}>
{isVisible && (
<div className={messageClassNames}>
<div className="tooltip-content" style={messageStyles}>{content}</div>
</div>
)}
<span
className="tooltip-trigger"
onMouseOver={showTooltip}
onFocus={showTooltip}
>
<div className="tooltip">
<div className={messageClassNames}>
<div className="tooltip-content" style={messageStyles}>{content}</div>
</div>
<div className="tooltip-trigger">
{children}
</span>
</div>
</div>
);
};
Expand Down
5 changes: 5 additions & 0 deletions src/helpers.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@
@content;
}
}

@mixin visibility($visibility, $opacity) {
visibility: $visibility;
opacity: $opacity;
}

0 comments on commit f07d6ba

Please sign in to comment.