feat: Add keyboard shortcuts to tooltips

This commit is contained in:
Tom Moor
2019-08-28 23:30:27 -07:00
parent b56f8e7870
commit 579eaf325b
6 changed files with 74 additions and 76 deletions

View File

@ -51,7 +51,7 @@ const Modal = ({
<Content column> <Content column>
{title && <h1>{title}</h1>} {title && <h1>{title}</h1>}
<Close onClick={onRequestClose}> <Close onClick={onRequestClose}>
<CloseIcon size={40} /> <CloseIcon size={40} color="currentColor" />
<Esc>esc</Esc> <Esc>esc</Esc>
</Close> </Close>
{children} {children}
@ -98,8 +98,8 @@ const Close = styled.a`
position: fixed; position: fixed;
top: 16px; top: 16px;
right: 16px; right: 16px;
opacity: 0.5; opacity: 0.75;
color: ${props => props.theme.textSecondary}; color: ${props => props.theme.text};
&:hover { &:hover {
opacity: 1; opacity: 1;

View File

@ -1,58 +0,0 @@
// @flow
import * as React from 'react';
import { observable } from 'mobx';
import { observer } from 'mobx-react';
import styled from 'styled-components';
import { CloseIcon } from 'outline-icons';
import Tooltip from './Tooltip';
import Flex from 'shared/components/Flex';
type Props = {
id: string,
children: React.Node,
disabled?: boolean,
};
@observer
class Tip extends React.Component<Props> {
@observable
isHidden: boolean = window.localStorage.getItem(this.storageId) === 'hidden';
get storageId() {
return `tip-${this.props.id}`;
}
hide = () => {
window.localStorage.setItem(this.storageId, 'hidden');
this.isHidden = true;
};
render() {
const { children } = this.props;
if (this.props.disabled || this.isHidden) return null;
return (
<Wrapper align="flex-start">
<span>{children}</span>
<Tooltip tooltip="Hide this message" placement="bottom">
<Close type="close" size={32} color="#000" onClick={this.hide} />
</Tooltip>
</Wrapper>
);
}
}
const Close = styled(CloseIcon)`
margin-top: 8px;
`;
const Wrapper = styled(Flex)`
background: ${props => props.theme.primary};
color: ${props => props.theme.text};
padding: 8px 16px;
border-radius: 4px;
font-weight: 400;
`;
export default Tip;

View File

@ -5,6 +5,7 @@ import Tippy from '@tippy.js/react';
type Props = { type Props = {
tooltip: React.Node, tooltip: React.Node,
shortcut?: React.Node,
placement?: 'top' | 'bottom' | 'left' | 'right', placement?: 'top' | 'bottom' | 'left' | 'right',
children: React.Node, children: React.Node,
delay?: number, delay?: number,
@ -19,6 +20,7 @@ class Tooltip extends React.Component<Props> {
render() { render() {
const { const {
shortcut,
tooltip, tooltip,
delay = 50, delay = 50,
children, children,
@ -28,12 +30,22 @@ class Tooltip extends React.Component<Props> {
} = this.props; } = this.props;
const Component = block ? 'div' : 'span'; const Component = block ? 'div' : 'span';
let content = tooltip;
if (shortcut) {
content = (
<React.Fragment>
{tooltip} &middot; <Shortcut>{shortcut}</Shortcut>
</React.Fragment>
);
}
return ( return (
<StyledTippy <StyledTippy
arrow arrow
arrowType="round" arrowType="round"
animation="shift-away" animation="shift-away"
content={tooltip} content={content}
delay={delay} delay={delay}
duration={[200, 150]} duration={[200, 150]}
inertia inertia
@ -45,6 +57,21 @@ class Tooltip extends React.Component<Props> {
} }
} }
const Shortcut = styled.kbd`
position: relative;
top: -2px;
display: inline-block;
padding: 2px 4px;
font: 10px 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier,
monospace;
line-height: 10px;
color: ${props => props.theme.tooltipBackground};
vertical-align: middle;
background-color: ${props => props.theme.tooltipText};
border-radius: 3px;
`;
const StyledTippy = styled(Tippy)` const StyledTippy = styled(Tippy)`
font-size: 13px; font-size: 13px;
background-color: ${props => props.theme.tooltipBackground}; background-color: ${props => props.theme.tooltipBackground};

View File

@ -24,6 +24,7 @@ import Search from 'scenes/Search';
import CollectionMenu from 'menus/CollectionMenu'; import CollectionMenu from 'menus/CollectionMenu';
import Actions, { Action, Separator } from 'components/Actions'; import Actions, { Action, Separator } from 'components/Actions';
import Heading from 'components/Heading'; import Heading from 'components/Heading';
import Tooltip from 'components/Tooltip';
import CenteredContent from 'components/CenteredContent'; import CenteredContent from 'components/CenteredContent';
import { ListPlaceholder } from 'components/LoadingPlaceholder'; import { ListPlaceholder } from 'components/LoadingPlaceholder';
import Mask from 'components/Mask'; import Mask from 'components/Mask';
@ -104,9 +105,16 @@ class CollectionScene extends React.Component<Props> {
return ( return (
<Actions align="center" justify="flex-end"> <Actions align="center" justify="flex-end">
<Action> <Action>
<Button onClick={this.onNewDocument} icon={<PlusIcon />}> <Tooltip
New doc tooltip="New document"
</Button> shortcut="n"
delay={500}
placement="bottom"
>
<Button onClick={this.onNewDocument} icon={<PlusIcon />}>
New doc
</Button>
</Tooltip>
</Action> </Action>
<Separator /> <Separator />
<Action> <Action>

View File

@ -19,6 +19,7 @@ import DocumentMenu from 'menus/DocumentMenu';
import NewChildDocumentMenu from 'menus/NewChildDocumentMenu'; import NewChildDocumentMenu from 'menus/NewChildDocumentMenu';
import DocumentShare from 'scenes/DocumentShare'; import DocumentShare from 'scenes/DocumentShare';
import Button from 'components/Button'; import Button from 'components/Button';
import Tooltip from 'components/Tooltip';
import Modal from 'components/Modal'; import Modal from 'components/Modal';
import Badge from 'components/Badge'; import Badge from 'components/Badge';
import Collaborators from 'components/Collaborators'; import Collaborators from 'components/Collaborators';
@ -182,14 +183,21 @@ class Header extends React.Component<Props> {
)} )}
{canEdit && ( {canEdit && (
<Action> <Action>
<Button <Tooltip
icon={<EditIcon />} tooltip="Edit document"
onClick={this.handleEdit} shortcut="e"
neutral delay={500}
small placement="bottom"
> >
Edit <Button
</Button> icon={<EditIcon />}
onClick={this.handleEdit}
neutral
small
>
Edit
</Button>
</Tooltip>
</Action> </Action>
)} )}
{canEdit && {canEdit &&
@ -198,9 +206,16 @@ class Header extends React.Component<Props> {
<NewChildDocumentMenu <NewChildDocumentMenu
document={document} document={document}
label={ label={
<Button icon={<PlusIcon />} neutral> <Tooltip
New doc tooltip="New document"
</Button> shortcut="n"
delay={500}
placement="bottom"
>
<Button icon={<PlusIcon />} neutral>
New doc
</Button>
</Tooltip>
} }
/> />
</Action> </Action>

View File

@ -34,7 +34,13 @@ class KeyboardShortcutsButton extends React.Component<Props> {
<KeyboardShortcuts /> <KeyboardShortcuts />
</Modal> </Modal>
<Button onClick={this.handleOpenKeyboardShortcuts}> <Button onClick={this.handleOpenKeyboardShortcuts}>
<Tooltip tooltip="Keyboard shortcuts" placement="left" block> <Tooltip
tooltip="Keyboard shortcuts"
shortcut="?"
placement="left"
delay={500}
block
>
<KeyboardIcon /> <KeyboardIcon />
</Tooltip> </Tooltip>
</Button> </Button>