Improve tooltips component, add tooltips

This commit is contained in:
Nicholas Zuber 2020-01-27 18:45:36 -05:00
parent 4be1f2876c
commit 015758fc9e
3 changed files with 70 additions and 27 deletions

View File

@ -36,24 +36,34 @@ class Tooltip extends React.Component {
} }
const {tooltipOffsetX, tooltipOffsetY} = this.props; const {tooltipOffsetX, tooltipOffsetY} = this.props;
const {x, y} = event.target.getBoundingClientRect(); const {
x,
y,
width: targetWidth,
height: targetHeight
} = event.target.getBoundingClientRect();
const text = document.createTextNode(this.props.message); const text = document.createTextNode(this.props.message);
const tooltipElement = document.createElement('div'); const tooltipElement = document.createElement('div');
tooltipElement.setAttribute('id', this.id); tooltipElement.setAttribute('id', this.id);
tooltipElement.setAttribute('class', 'react-tooltip'); tooltipElement.setAttribute('class', 'react-tooltip');
tooltipElement.setAttribute(
'style',
`top: ${y + tooltipOffsetY + window.scrollY}px; left: ${x + tooltipOffsetX}px;`
);
tooltipElement.appendChild(text); tooltipElement.appendChild(text);
document.querySelector('body').appendChild(tooltipElement); document.querySelector('body').appendChild(tooltipElement);
const {width} = tooltipElement.getBoundingClientRect();
const positionStyle = `
top: ${y + targetHeight + window.scrollY + tooltipOffsetY}px;
left: ${x - (width / 2) + (targetWidth / 2) + tooltipOffsetX}px;
`;
tooltipElement.setAttribute('style', positionStyle);
this.timeout = setTimeout(() => { this.timeout = setTimeout(() => {
tooltipElement.setAttribute( tooltipElement.setAttribute(
'style', 'style', `
`top: ${y + tooltipOffsetY + window.scrollY}px; left: ${x + tooltipOffsetX}px; opacity: .83;` ${positionStyle}
opacity: .9;
`
); );
}, this.props.tooltipSpeed); }, this.props.tooltipSpeed);
} }

View File

@ -10,7 +10,7 @@ import Logo from '../../../components/Logo';
import LoadingIcon from '../../../components/LoadingIcon' import LoadingIcon from '../../../components/LoadingIcon'
import {getFact} from '../../../utils/facts'; import {getFact} from '../../../utils/facts';
import {Mode, Sort, View} from '../index'; import {Mode, Sort, View} from '../index';
import {isMobile} from 'react-device-detect'; import {withTooltip} from '../../../enhance';
import { import {
stringOfError, stringOfError,
getPRIssueIcon, getPRIssueIcon,
@ -60,10 +60,10 @@ import {
LoadingNotificationRow, LoadingNotificationRow,
NotificationBlock, NotificationBlock,
ErrorContainer, ErrorContainer,
NotificationCell, NotificationCell as BaseNotificationCell,
NotificationTitle, NotificationTitle,
NotificationByline, NotificationByline,
IconLink, IconLink as BaseIconLink,
Divider, Divider,
Connector, Connector,
RepoBarContainer, RepoBarContainer,
@ -78,10 +78,13 @@ import {
} from './ui'; } from './ui';
export const AnimatedNotificationRow = animated(NotificationRow); export const AnimatedNotificationRow = animated(NotificationRow);
const IconLink = withTooltip(BaseIconLink);
const NotificationCell = withTooltip(BaseNotificationCell);
const hash = process.localEnv.GIT_HASH ? `#${process.localEnv.GIT_HASH}` : ''; const hash = process.localEnv.GIT_HASH ? `#${process.localEnv.GIT_HASH}` : '';
const version = require('../../../../package.json').version + hash; const version = require('../../../../package.json').version + hash;
function PageItem ({children, onChange, ...props}) { function BasePageItem ({children, onChange, ...props}) {
return ( return (
<PageItemComponent <PageItemComponent
onClick={() => onChange(props.view)} onClick={() => onChange(props.view)}
@ -92,6 +95,8 @@ function PageItem ({children, onChange, ...props}) {
); );
} }
const PageItem = withTooltip(BasePageItem);
function MenuIconItem ({children, onChange, selected, alwaysActive, noBorder, ...props}) { function MenuIconItem ({children, onChange, selected, alwaysActive, noBorder, ...props}) {
return ( return (
<IconContainer <IconContainer
@ -587,7 +592,7 @@ export default function Scene ({
setDropdownOpen(false); setDropdownOpen(false);
}} }}
> >
<IconLink> <IconLink tooltip={`${hasNotificationsOn ? 'Disable' : 'Enable'} notifications`}>
{hasNotificationsOn ? ( {hasNotificationsOn ? (
<i className="fas fa-bell"></i> <i className="fas fa-bell"></i>
) : ( ) : (
@ -607,12 +612,12 @@ export default function Scene ({
setDarkMode(m => !m); setDarkMode(m => !m);
}} }}
> >
<IconLink> <IconLink tooltip={`${darkMode ? 'Disable' : 'Enable'} dark mode`}>
<i className="fas fa-moon"></i> <i className="fas fa-moon"></i>
</IconLink> </IconLink>
</optimized.li> </optimized.li>
<optimized.li> <optimized.li>
<IconLink onClick={() => setDropdownOpen(true)}> <IconLink tooltip="View more options" onClick={() => setDropdownOpen(true)}>
<i className="fas fa-ellipsis-v"></i> <i className="fas fa-ellipsis-v"></i>
</IconLink> </IconLink>
<InteractionMenu show={dropdownOpen}> <InteractionMenu show={dropdownOpen}>
@ -688,6 +693,8 @@ export default function Scene ({
primary={ThemeColor(darkMode)} primary={ThemeColor(darkMode)}
onChange={setView} onChange={setView}
mark={hasUnread} mark={hasUnread}
tooltip="View your active unread notifications"
tooltipOffsetY={-72}
> >
{'Unread'} {'Unread'}
{unreadCount > 0 && ( {unreadCount > 0 && (
@ -715,6 +722,8 @@ export default function Scene ({
selected={view === View.READ} selected={view === View.READ}
primary={ThemeColor(darkMode)} primary={ThemeColor(darkMode)}
onChange={setView} onChange={setView}
tooltip="View notifications you have already read"
tooltipOffsetY={-72}
> >
{'Read'} {'Read'}
{readCount > 0 && ( {readCount > 0 && (
@ -742,6 +751,8 @@ export default function Scene ({
selected={view === View.ARCHIVED} selected={view === View.ARCHIVED}
primary={ThemeColor(darkMode)} primary={ThemeColor(darkMode)}
onChange={setView} onChange={setView}
tooltip="View notifications that are considered completed"
tooltipOffsetY={-72}
> >
{'Archived'} {'Archived'}
{archivedCount > 0 && ( {archivedCount > 0 && (
@ -1084,12 +1095,17 @@ function NotificationCollection ({
{'@' + item.repository} {'@' + item.repository}
</NotificationCell> </NotificationCell>
{/* Score */} {/* Score */}
<NotificationCell width={60} css={css` <NotificationCell
font-weight: 600; tooltip="Score representing this notification's importance compared to the others"
color: ${colorOfScore(item.score)}; tooltipOffsetX={-100}
font-size: 12px; width={60}
text-align: center; css={css`
`}> font-weight: 600;
color: ${colorOfScore(item.score)};
font-size: 12px;
text-align: center;
`}
>
{'+' + item.score} {'+' + item.score}
</NotificationCell> </NotificationCell>
<NotificationCell width={80} css={css` <NotificationCell width={80} css={css`
@ -1133,10 +1149,16 @@ function ActionItems ({item, view, markAsRead, markAsArchived, markAsUnread}) {
case View.UNREAD: case View.UNREAD:
return ( return (
<> <>
<IconLink onClick={() => markAsRead(item.id, item.repository)}> <IconLink
tooltip="Mark as read"
onClick={() => markAsRead(item.id, item.repository)}
>
<i className="fas fa-check"></i> <i className="fas fa-check"></i>
</IconLink> </IconLink>
<IconLink onClick={() => markAsArchived(item.id, item.repository)}> <IconLink
tooltip="Mark as archived"
onClick={() => markAsArchived(item.id, item.repository)}
>
<i className="fas fa-times"></i> <i className="fas fa-times"></i>
</IconLink> </IconLink>
</> </>
@ -1144,10 +1166,16 @@ function ActionItems ({item, view, markAsRead, markAsArchived, markAsUnread}) {
case View.READ: case View.READ:
return ( return (
<> <>
<IconLink onClick={() => markAsUnread(item.id)}> <IconLink
tooltip="Mark as unread"
onClick={() => markAsUnread(item.id)}
>
<i className="fas fa-undo"></i> <i className="fas fa-undo"></i>
</IconLink> </IconLink>
<IconLink onClick={() => markAsArchived(item.id, item.repository)}> <IconLink
tooltip="Mark as archived"
onClick={() => markAsArchived(item.id, item.repository)}
>
<i className="fas fa-times"></i> <i className="fas fa-times"></i>
</IconLink> </IconLink>
</> </>
@ -1155,10 +1183,16 @@ function ActionItems ({item, view, markAsRead, markAsArchived, markAsUnread}) {
case View.ARCHIVED: case View.ARCHIVED:
return ( return (
<> <>
<IconLink onClick={() => markAsUnread(item.id)}> <IconLink
tooltip="Mark as read"
onClick={() => markAsUnread(item.id)}
>
<i className="fas fa-undo"></i> <i className="fas fa-undo"></i>
</IconLink> </IconLink>
<IconLink onClick={() => markAsRead(item.id, item.repository)}> <IconLink
tooltip="Mark as unread"
onClick={() => markAsRead(item.id, item.repository)}
>
<i className="fas fa-check"></i> <i className="fas fa-check"></i>
</IconLink> </IconLink>
</> </>

View File

@ -98,7 +98,6 @@ a {
font-size: 11px; font-size: 11px;
border-radius: 4px; border-radius: 4px;
white-space: nowrap; white-space: nowrap;
transform: translateX(-35%) translateY(-15px);
opacity: 0; opacity: 0;
transition: all 75ms ease-in; transition: all 75ms ease-in;
} }