WIP
This commit is contained in:
parent
b1484cf3ce
commit
4d996426ac
19 changed files with 548 additions and 133 deletions
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
|
|
||||||
export default class Button extends React.PureComponent {
|
export default class Button extends React.PureComponent {
|
||||||
|
|
||||||
|
@ -49,16 +50,17 @@ export default class Button extends React.PureComponent {
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<Tooltip placement='bottom' overlay={this.props.title}>
|
||||||
className={className}
|
<button
|
||||||
disabled={this.props.disabled}
|
className={className}
|
||||||
onClick={this.handleClick}
|
disabled={this.props.disabled}
|
||||||
ref={this.setRef}
|
onClick={this.handleClick}
|
||||||
style={style}
|
ref={this.setRef}
|
||||||
title={this.props.title}
|
style={style}
|
||||||
>
|
>
|
||||||
{this.props.text || this.props.children}
|
{this.props.text || this.props.children}
|
||||||
</button>
|
</button>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,24 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
|
|
||||||
export default class Icon extends React.PureComponent {
|
export default class Icon extends React.PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
id: PropTypes.string.isRequired,
|
id: PropTypes.string.isRequired,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
|
title: PropTypes.node,
|
||||||
fixedWidth: PropTypes.bool,
|
fixedWidth: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { id, className, fixedWidth, ...other } = this.props;
|
const { id, className, fixedWidth, title, ...other } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<i role='img' className={classNames('fa', `fa-${id}`, className, { 'fa-fw': fixedWidth })} {...other} />
|
<Tooltip placement='top' overlay={title}>
|
||||||
|
<i role='img' className={classNames('fa', `fa-${id}`, className, { 'fa-fw': fixedWidth })} {...other} />
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
|
|
||||||
export default class IconButton extends React.PureComponent {
|
export default class IconButton extends React.PureComponent {
|
||||||
|
|
||||||
|
@ -114,22 +115,23 @@ export default class IconButton extends React.PureComponent {
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<Tooltip placement='bottom' overlay={title}>
|
||||||
aria-label={title}
|
<button
|
||||||
aria-pressed={pressed}
|
aria-label={title}
|
||||||
aria-expanded={expanded}
|
aria-pressed={pressed}
|
||||||
title={title}
|
aria-expanded={expanded}
|
||||||
className={classes}
|
className={classes}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
onMouseDown={this.handleMouseDown}
|
onMouseDown={this.handleMouseDown}
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
onKeyPress={this.handleKeyPress}
|
onKeyPress={this.handleKeyPress}
|
||||||
style={style}
|
style={style}
|
||||||
tabIndex={tabIndex}
|
tabIndex={tabIndex}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
<Icon id={icon} fixedWidth aria-hidden='true' />
|
<Icon id={icon} fixedWidth aria-hidden='true' />
|
||||||
</button>
|
</button>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { isIOS } from '../is_mobile';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { autoPlayGif, cropImages, displayMedia, useBlurhash } from '../initial_state';
|
import { autoPlayGif, cropImages, displayMedia, useBlurhash } from '../initial_state';
|
||||||
import { decode } from 'blurhash';
|
import { decode } from 'blurhash';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
toggle_visible: { id: 'media_gallery.toggle_visible',
|
toggle_visible: { id: 'media_gallery.toggle_visible',
|
||||||
|
@ -165,9 +166,11 @@ class Item extends React.PureComponent {
|
||||||
if (attachment.get('type') === 'unknown') {
|
if (attachment.get('type') === 'unknown') {
|
||||||
return (
|
return (
|
||||||
<div className={classNames('media-gallery__item', { standalone })} key={attachment.get('id')} style={{ left: left, top: top, right: right, bottom: bottom, width: `${width}%`, height: `${height}%` }}>
|
<div className={classNames('media-gallery__item', { standalone })} key={attachment.get('id')} style={{ left: left, top: top, right: right, bottom: bottom, width: `${width}%`, height: `${height}%` }}>
|
||||||
<a className='media-gallery__item-thumbnail' href={attachment.get('remote_url') || attachment.get('url')} style={{ cursor: 'pointer' }} title={attachment.get('description')} target='_blank' rel='noopener noreferrer'>
|
<Tooltip placement='bottom' overlay={attachment.get('description')}>
|
||||||
<canvas width={32} height={32} ref={this.setCanvasRef} className='media-gallery__preview' />
|
<a className='media-gallery__item-thumbnail' href={attachment.get('remote_url') || attachment.get('url')} style={{ cursor: 'pointer' }} aria-label={attachment.get('description')} target='_blank' rel='noopener noreferrer'>
|
||||||
</a>
|
<canvas width={32} height={32} ref={this.setCanvasRef} className='media-gallery__preview' />
|
||||||
|
</a>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (attachment.get('type') === 'image') {
|
} else if (attachment.get('type') === 'image') {
|
||||||
|
@ -188,42 +191,44 @@ class Item extends React.PureComponent {
|
||||||
const y = ((focusY / -2) + .5) * 100;
|
const y = ((focusY / -2) + .5) * 100;
|
||||||
|
|
||||||
thumbnail = (
|
thumbnail = (
|
||||||
<a
|
<Tooltip placement='bottom' overlay={attachment.get('description')}>
|
||||||
className='media-gallery__item-thumbnail'
|
<a
|
||||||
href={attachment.get('remote_url') || originalUrl}
|
className='media-gallery__item-thumbnail'
|
||||||
onClick={this.handleClick}
|
href={attachment.get('remote_url') || originalUrl}
|
||||||
target='_blank'
|
onClick={this.handleClick}
|
||||||
rel='noopener noreferrer'
|
target='_blank'
|
||||||
>
|
rel='noopener noreferrer'
|
||||||
<img
|
>
|
||||||
src={previewUrl}
|
<img
|
||||||
srcSet={srcSet}
|
src={previewUrl}
|
||||||
sizes={sizes}
|
srcSet={srcSet}
|
||||||
alt={attachment.get('description')}
|
sizes={sizes}
|
||||||
title={attachment.get('description')}
|
alt={attachment.get('description')}
|
||||||
style={{ objectPosition: `${x}% ${y}%` }}
|
style={{ objectPosition: `${x}% ${y}%` }}
|
||||||
onLoad={this.handleImageLoad}
|
onLoad={this.handleImageLoad}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
} else if (attachment.get('type') === 'gifv') {
|
} else if (attachment.get('type') === 'gifv') {
|
||||||
const autoPlay = !isIOS() && this.getAutoPlay();
|
const autoPlay = !isIOS() && this.getAutoPlay();
|
||||||
|
|
||||||
thumbnail = (
|
thumbnail = (
|
||||||
<div className={classNames('media-gallery__gifv', { autoplay: autoPlay })}>
|
<div className={classNames('media-gallery__gifv', { autoplay: autoPlay })}>
|
||||||
<video
|
<Tooltip placement='bottom' overlay={attachment.get('description')}>
|
||||||
className='media-gallery__item-gifv-thumbnail'
|
<video
|
||||||
aria-label={attachment.get('description')}
|
className='media-gallery__item-gifv-thumbnail'
|
||||||
title={attachment.get('description')}
|
aria-label={attachment.get('description')}
|
||||||
role='application'
|
role='application'
|
||||||
src={attachment.get('url')}
|
src={attachment.get('url')}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
onMouseEnter={this.handleMouseEnter}
|
onMouseEnter={this.handleMouseEnter}
|
||||||
onMouseLeave={this.handleMouseLeave}
|
onMouseLeave={this.handleMouseLeave}
|
||||||
autoPlay={autoPlay}
|
autoPlay={autoPlay}
|
||||||
loop
|
loop
|
||||||
muted
|
muted
|
||||||
/>
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<span className='media-gallery__gifv__label'>GIF</span>
|
<span className='media-gallery__gifv__label'>GIF</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
|
|
||||||
export default class Permalink extends React.PureComponent {
|
export default class Permalink extends React.PureComponent {
|
||||||
|
|
||||||
|
@ -28,12 +29,14 @@ export default class Permalink extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { href, children, className, onInterceptClick, ...other } = this.props;
|
const { href, children, className, onInterceptClick, title, ...other } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a target='_blank' href={href} onClick={this.handleClick} {...other} className={`permalink${className ? ' ' + className : ''}`}>
|
<Tooltip placement='top' overlay={title}>
|
||||||
{children}
|
<a target='_blank' href={href} onClick={this.handleClick} {...other} className={`permalink${className ? ' ' + className : ''}`}>
|
||||||
</a>
|
{children}
|
||||||
|
</a>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { injectIntl, defineMessages } from 'react-intl';
|
import { injectIntl, defineMessages } from 'react-intl';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
today: { id: 'relative_time.today', defaultMessage: 'today' },
|
today: { id: 'relative_time.today', defaultMessage: 'today' },
|
||||||
|
@ -181,11 +182,14 @@ class RelativeTimestamp extends React.Component {
|
||||||
const timeGiven = timestamp.includes('T');
|
const timeGiven = timestamp.includes('T');
|
||||||
const date = new Date(timestamp);
|
const date = new Date(timestamp);
|
||||||
const relativeTime = futureDate ? timeRemainingString(intl, date, this.state.now, timeGiven) : timeAgoString(intl, date, this.state.now, year, timeGiven);
|
const relativeTime = futureDate ? timeRemainingString(intl, date, this.state.now, timeGiven) : timeAgoString(intl, date, this.state.now, year, timeGiven);
|
||||||
|
const formatted = intl.formatDate(date, dateFormatOptions);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<time dateTime={timestamp} title={intl.formatDate(date, dateFormatOptions)}>
|
<Tooltip placement='top' overlay={formatted}>
|
||||||
{relativeTime}
|
<time dateTime={timestamp} aria-label={formatted}>
|
||||||
</time>
|
{relativeTime}
|
||||||
|
</time>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { MediaGallery, Video, Audio } from '../features/ui/util/async-components
|
||||||
import { HotKeys } from 'react-hotkeys';
|
import { HotKeys } from 'react-hotkeys';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
import { displayMedia } from '../initial_state';
|
import { displayMedia } from '../initial_state';
|
||||||
|
|
||||||
// We use the component (and not the container) since we do not want
|
// We use the component (and not the container) since we do not want
|
||||||
|
@ -424,13 +425,15 @@ class Status extends ImmutablePureComponent {
|
||||||
<div className='status__info'>
|
<div className='status__info'>
|
||||||
<a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'><RelativeTimestamp timestamp={status.get('created_at')} /></a>
|
<a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'><RelativeTimestamp timestamp={status.get('created_at')} /></a>
|
||||||
|
|
||||||
<a onClick={this.handleAccountClick} data-id={status.getIn(['account', 'id'])} href={status.getIn(['account', 'url'])} title={status.getIn(['account', 'acct'])} className='status__display-name' target='_blank' rel='noopener noreferrer'>
|
<Tooltip placement='top' overlay={status.getIn(['account', 'acct'])}>
|
||||||
<div className='status__avatar'>
|
<a onClick={this.handleAccountClick} data-id={status.getIn(['account', 'id'])} href={status.getIn(['account', 'url'])} className='status__display-name' target='_blank' rel='noopener noreferrer'>
|
||||||
{statusAvatar}
|
<div className='status__avatar'>
|
||||||
</div>
|
{statusAvatar}
|
||||||
|
</div>
|
||||||
|
|
||||||
<DisplayName account={status.get('account')} others={otherAccounts} />
|
<DisplayName account={status.get('account')} others={otherAccounts} />
|
||||||
</a>
|
</a>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StatusContent status={status} onClick={this.handleClick} expanded={!status.get('hidden')} showThread={showThread} onExpandedToggle={this.handleExpandedToggle} collapsable onCollapsedToggle={this.handleCollapsedToggle} />
|
<StatusContent status={status} onClick={this.handleClick} expanded={!status.get('hidden')} showThread={showThread} onExpandedToggle={this.handleExpandedToggle} collapsable onCollapsedToggle={this.handleCollapsedToggle} />
|
||||||
|
|
22
app/javascript/mastodon/components/tooltip.js
Normal file
22
app/javascript/mastodon/components/tooltip.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Tooltip from 'rc-tooltip';
|
||||||
|
|
||||||
|
const OptionalTooltip = ({ overlay, children, ...other }) => {
|
||||||
|
if (overlay) {
|
||||||
|
return (
|
||||||
|
<Tooltip animation='zoom' mouseEnterDelay={0.2} destroyTooltipOnHide {...other} overlay={overlay}>
|
||||||
|
{children}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
OptionalTooltip.propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
overlay: PropTypes.node,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OptionalTooltip;
|
|
@ -11,6 +11,7 @@ import Avatar from 'mastodon/components/avatar';
|
||||||
import { shortNumberFormat } from 'mastodon/utils/numbers';
|
import { shortNumberFormat } from 'mastodon/utils/numbers';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
|
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||||
|
@ -293,19 +294,34 @@ class Header extends ImmutablePureComponent {
|
||||||
<dt dangerouslySetInnerHTML={{ __html: proof.get('provider') }} />
|
<dt dangerouslySetInnerHTML={{ __html: proof.get('provider') }} />
|
||||||
|
|
||||||
<dd className='verified'>
|
<dd className='verified'>
|
||||||
<a href={proof.get('proof_url')} target='_blank' rel='noopener noreferrer'><span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(proof.get('updated_at'), dateFormatOptions) })}>
|
<Tooltip placement='top' overlay={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(proof.get('updated_at'), dateFormatOptions) })}>
|
||||||
<Icon id='check' className='verified__mark' />
|
<a href={proof.get('proof_url')} target='_blank' rel='noopener noreferrer'>
|
||||||
</span></a>
|
<Icon id='check' className='verified__mark' />
|
||||||
|
</a>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<a href={proof.get('profile_url')} target='_blank' rel='noopener noreferrer'><span dangerouslySetInnerHTML={{ __html: ' '+proof.get('provider_username') }} /></a>
|
<a href={proof.get('profile_url')} target='_blank' rel='noopener noreferrer'><span dangerouslySetInnerHTML={{ __html: ' '+proof.get('provider_username') }} /></a>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
))}
|
))}
|
||||||
{fields.map((pair, i) => (
|
{fields.map((pair, i) => (
|
||||||
<dl key={i}>
|
<dl key={i}>
|
||||||
<dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} />
|
<dt>
|
||||||
|
<Tooltip placement='top' overlay={pair.get('name')}>
|
||||||
|
<span dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} />
|
||||||
|
</Tooltip>
|
||||||
|
</dt>
|
||||||
|
|
||||||
<dd className={pair.get('verified_at') && 'verified'} title={pair.get('value_plain')}>
|
<dd className={pair.get('verified_at') && 'verified'}>
|
||||||
{pair.get('verified_at') && <span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><Icon id='check' className='verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} />
|
{pair.get('verified_at') && (
|
||||||
|
<Tooltip placement='top' overlay={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}>
|
||||||
|
<Icon id='check' className='verified__mark' />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
{' '}
|
||||||
|
<Tooltip placement='top' overlay={pair.get('value_plain')}>
|
||||||
|
<span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} />
|
||||||
|
</Tooltip>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
))}
|
))}
|
||||||
|
@ -316,17 +332,23 @@ class Header extends ImmutablePureComponent {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='account__header__extra__links'>
|
<div className='account__header__extra__links'>
|
||||||
<NavLink isActive={this.isStatusesPageActive} activeClassName='active' to={`/accounts/${account.get('id')}`} title={intl.formatNumber(account.get('statuses_count'))}>
|
<Tooltip placement='bottom' overlay={intl.formatNumber(account.get('statuses_count'))}>
|
||||||
<strong>{shortNumberFormat(account.get('statuses_count'))}</strong> <FormattedMessage id='account.posts' defaultMessage='Toots' />
|
<NavLink isActive={this.isStatusesPageActive} activeClassName='active' to={`/accounts/${account.get('id')}`}>
|
||||||
</NavLink>
|
<strong>{shortNumberFormat(account.get('statuses_count'))}</strong> <FormattedMessage id='account.posts' defaultMessage='Toots' />
|
||||||
|
</NavLink>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<NavLink exact activeClassName='active' to={`/accounts/${account.get('id')}/following`} title={intl.formatNumber(account.get('following_count'))}>
|
<Tooltip placement='bottom' overlay={intl.formatNumber(account.get('following_count'))}>
|
||||||
<strong>{shortNumberFormat(account.get('following_count'))}</strong> <FormattedMessage id='account.follows' defaultMessage='Follows' />
|
<NavLink exact activeClassName='active' to={`/accounts/${account.get('id')}/following`}>
|
||||||
</NavLink>
|
<strong>{shortNumberFormat(account.get('following_count'))}</strong> <FormattedMessage id='account.follows' defaultMessage='Follows' />
|
||||||
|
</NavLink>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<NavLink exact activeClassName='active' to={`/accounts/${account.get('id')}/followers`} title={intl.formatNumber(account.get('followers_count'))}>
|
<Tooltip placement='bottom' overlay={intl.formatNumber(account.get('followers_count'))}>
|
||||||
<strong>{shortNumberFormat(account.get('followers_count'))}</strong> <FormattedMessage id='account.followers' defaultMessage='Followers' />
|
<NavLink exact activeClassName='active' to={`/accounts/${account.get('id')}/followers`}>
|
||||||
</NavLink>
|
<strong>{shortNumberFormat(account.get('followers_count'))}</strong> <FormattedMessage id='account.followers' defaultMessage='Followers' />
|
||||||
|
</NavLink>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import Avatar from '../../../components/avatar';
|
||||||
import DisplayName from '../../../components/display_name';
|
import DisplayName from '../../../components/display_name';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
|
|
||||||
export default class AutosuggestAccount extends ImmutablePureComponent {
|
export default class AutosuggestAccount extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
@ -14,10 +15,12 @@ export default class AutosuggestAccount extends ImmutablePureComponent {
|
||||||
const { account } = this.props;
|
const { account } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='autosuggest-account' title={account.get('acct')}>
|
<Tooltip placement='top' overlay={account.get('acct')}>
|
||||||
<div className='autosuggest-account-icon'><Avatar account={account} size={18} /></div>
|
<div className='autosuggest-account'>
|
||||||
<DisplayName account={account} />
|
<div className='autosuggest-account-icon'><Avatar account={account} size={18} /></div>
|
||||||
</div>
|
<DisplayName account={account} />
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import classNames from 'classnames';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import detectPassiveEvents from 'detect-passive-events';
|
||||||
import { buildCustomEmojis, categoriesFromEmojis } from '../../emoji/emoji';
|
import { buildCustomEmojis, categoriesFromEmojis } from '../../emoji/emoji';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
|
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
|
||||||
|
@ -358,13 +359,15 @@ class EmojiPickerDropdown extends React.PureComponent {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='emoji-picker-dropdown' onKeyDown={this.handleKeyDown}>
|
<div className='emoji-picker-dropdown' onKeyDown={this.handleKeyDown}>
|
||||||
<div ref={this.setTargetRef} className='emoji-button' title={title} aria-label={title} aria-expanded={active} role='button' onClick={this.onToggle} onKeyDown={this.onToggle} tabIndex={0}>
|
<Tooltip placement='top' overlay={title}>
|
||||||
{button || <img
|
<div ref={this.setTargetRef} className='emoji-button' aria-label={title} aria-expanded={active} role='button' onClick={this.onToggle} onKeyDown={this.onToggle} tabIndex={0}>
|
||||||
className={classNames('emojione', { 'pulse-loading': active && loading })}
|
{button || <img
|
||||||
alt='🙂'
|
className={classNames('emojione', { 'pulse-loading': active && loading })}
|
||||||
src={`${assetHost}/emoji/1f602.svg`}
|
alt='🙂'
|
||||||
/>}
|
src={`${assetHost}/emoji/1f602.svg`}
|
||||||
</div>
|
/>}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<Overlay show={active} placement={placement} target={this.findTarget}>
|
<Overlay show={active} placement={placement} target={this.findTarget}>
|
||||||
<EmojiPickerMenu
|
<EmojiPickerMenu
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
|
|
||||||
const iconStyle = {
|
const iconStyle = {
|
||||||
height: null,
|
height: null,
|
||||||
|
@ -26,16 +27,17 @@ export default class TextIconButton extends React.PureComponent {
|
||||||
const { label, title, active, ariaControls } = this.props;
|
const { label, title, active, ariaControls } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<Tooltip placement='bottom' overlay={title}>
|
||||||
title={title}
|
<button
|
||||||
aria-label={title}
|
aria-label={title}
|
||||||
className={`text-icon-button ${active ? 'active' : ''}`}
|
className={`text-icon-button ${active ? 'active' : ''}`}
|
||||||
aria-expanded={active}
|
aria-expanded={active}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
aria-controls={ariaControls} style={iconStyle}
|
aria-controls={ariaControls} style={iconStyle}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</button>
|
</button>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { changeComposeSensitivity } from 'mastodon/actions/compose';
|
import { changeComposeSensitivity } from 'mastodon/actions/compose';
|
||||||
import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
|
import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
marked: { id: 'compose_form.sensitive.marked', defaultMessage: 'Media is marked as sensitive' },
|
marked: { id: 'compose_form.sensitive.marked', defaultMessage: 'Media is marked as sensitive' },
|
||||||
|
@ -37,19 +38,21 @@ class SensitiveButton extends React.PureComponent {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='compose-form__sensitive-button'>
|
<div className='compose-form__sensitive-button'>
|
||||||
<label className={classNames('icon-button', { active })} title={intl.formatMessage(active ? messages.marked : messages.unmarked)}>
|
<Tooltip placement='top' overlay={intl.formatMessage(active ? messages.marked : messages.unmarked)}>
|
||||||
<input
|
<label className={classNames('icon-button', { active })} aria-label={intl.formatMessage(active ? messages.marked : messages.unmarked)}>
|
||||||
name='mark-sensitive'
|
<input
|
||||||
type='checkbox'
|
name='mark-sensitive'
|
||||||
checked={active}
|
type='checkbox'
|
||||||
onChange={onClick}
|
checked={active}
|
||||||
disabled={disabled}
|
onChange={onClick}
|
||||||
/>
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
|
||||||
<span className={classNames('checkbox', { active })} />
|
<span className={classNames('checkbox', { active })} />
|
||||||
|
|
||||||
<FormattedMessage id='compose_form.sensitive.hide' defaultMessage='Mark media as sensitive' />
|
<FormattedMessage id='compose_form.sensitive.hide' defaultMessage='Mark media as sensitive' />
|
||||||
</label>
|
</label>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { openModal } from 'mastodon/actions/modal';
|
||||||
import elephantUIPlane from '../../../images/elephant_ui_plane.svg';
|
import elephantUIPlane from '../../../images/elephant_ui_plane.svg';
|
||||||
import { mascot } from '../../initial_state';
|
import { mascot } from '../../initial_state';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
|
import Tooltip from 'mastodon/components/tooltip';
|
||||||
import { logOut } from 'mastodon/utils/log_out';
|
import { logOut } from 'mastodon/utils/log_out';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@ -97,21 +98,55 @@ class Compose extends React.PureComponent {
|
||||||
const { columns } = this.props;
|
const { columns } = this.props;
|
||||||
header = (
|
header = (
|
||||||
<nav className='drawer__header'>
|
<nav className='drawer__header'>
|
||||||
<Link to='/getting-started' className='drawer__tab' title={intl.formatMessage(messages.start)} aria-label={intl.formatMessage(messages.start)}><Icon id='bars' fixedWidth /></Link>
|
<Tooltip placement='bottom' overlay={intl.formatMessage(messages.start)}>
|
||||||
|
<Link to='/getting-started' className='drawer__tab' aria-label={intl.formatMessage(messages.start)}>
|
||||||
|
<Icon id='bars' fixedWidth />
|
||||||
|
</Link>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
{!columns.some(column => column.get('id') === 'HOME') && (
|
{!columns.some(column => column.get('id') === 'HOME') && (
|
||||||
<Link to='/timelines/home' className='drawer__tab' title={intl.formatMessage(messages.home_timeline)} aria-label={intl.formatMessage(messages.home_timeline)}><Icon id='home' fixedWidth /></Link>
|
<Tooltip placement='bottom' overlay={intl.formatMessage(messages.home_timeline)}>
|
||||||
|
<Link to='/timelines/home' className='drawer__tab' aria-label={intl.formatMessage(messages.home_timeline)}>
|
||||||
|
<Icon id='home' fixedWidth />
|
||||||
|
</Link>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!columns.some(column => column.get('id') === 'NOTIFICATIONS') && (
|
{!columns.some(column => column.get('id') === 'NOTIFICATIONS') && (
|
||||||
<Link to='/notifications' className='drawer__tab' title={intl.formatMessage(messages.notifications)} aria-label={intl.formatMessage(messages.notifications)}><Icon id='bell' fixedWidth /></Link>
|
<Tooltip placement='bottom' overlay={intl.formatMessage(messages.notifications)}>
|
||||||
|
<Link to='/notifications' className='drawer__tab' aria-label={intl.formatMessage(messages.notifications)}>
|
||||||
|
<Icon id='bell' fixedWidth />
|
||||||
|
</Link>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!columns.some(column => column.get('id') === 'COMMUNITY') && (
|
{!columns.some(column => column.get('id') === 'COMMUNITY') && (
|
||||||
<Link to='/timelines/public/local' className='drawer__tab' title={intl.formatMessage(messages.community)} aria-label={intl.formatMessage(messages.community)}><Icon id='users' fixedWidth /></Link>
|
<Tooltip placement='bottom' overlay={intl.formatMessage(messages.community)}>
|
||||||
|
<Link to='/timelines/public/local' className='drawer__tab' aria-label={intl.formatMessage(messages.community)}>
|
||||||
|
<Icon id='users' fixedWidth />
|
||||||
|
</Link>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!columns.some(column => column.get('id') === 'PUBLIC') && (
|
{!columns.some(column => column.get('id') === 'PUBLIC') && (
|
||||||
<Link to='/timelines/public' className='drawer__tab' title={intl.formatMessage(messages.public)} aria-label={intl.formatMessage(messages.public)}><Icon id='globe' fixedWidth /></Link>
|
<Tooltip placement='bottom' overlay={intl.formatMessage(messages.public)}>
|
||||||
|
<Link to='/timelines/public' className='drawer__tab' aria-label={intl.formatMessage(messages.public)}>
|
||||||
|
<Icon id='globe' fixedWidth />
|
||||||
|
</Link>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
<a href='/settings/preferences' className='drawer__tab' title={intl.formatMessage(messages.preferences)} aria-label={intl.formatMessage(messages.preferences)}><Icon id='cog' fixedWidth /></a>
|
|
||||||
<a href='/auth/sign_out' className='drawer__tab' title={intl.formatMessage(messages.logout)} aria-label={intl.formatMessage(messages.logout)} onClick={this.handleLogoutClick}><Icon id='sign-out' fixedWidth /></a>
|
<Tooltip placement='bottom' overlay={intl.formatMessage(messages.preferences)}>
|
||||||
|
<a href='/settings/preferences' className='drawer__tab' aria-label={intl.formatMessage(messages.preferences)}>
|
||||||
|
<Icon id='cog' fixedWidth />
|
||||||
|
</a>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip placement='bottom' overlay={intl.formatMessage(messages.logout)}>
|
||||||
|
<a href='/auth/sign_out' className='drawer__tab' aria-label={intl.formatMessage(messages.logout)} onClick={this.handleLogoutClick}>
|
||||||
|
<Icon id='sign-out' fixedWidth />
|
||||||
|
</a>
|
||||||
|
</Tooltip>
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,5 +24,6 @@
|
||||||
@import 'mastodon/tables';
|
@import 'mastodon/tables';
|
||||||
@import 'mastodon/admin';
|
@import 'mastodon/admin';
|
||||||
@import 'mastodon/dashboard';
|
@import 'mastodon/dashboard';
|
||||||
|
@import 'mastodon/tooltips';
|
||||||
@import 'mastodon/rtl';
|
@import 'mastodon/rtl';
|
||||||
@import 'mastodon/accessibility';
|
@import 'mastodon/accessibility';
|
||||||
|
|
|
@ -1076,8 +1076,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.status__info .status__display-name {
|
.status__info .status__display-name {
|
||||||
display: block;
|
display: inline-flex;
|
||||||
max-width: 100%;
|
|
||||||
padding-right: 25px;
|
padding-right: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
233
app/javascript/styles/mastodon/tooltips.scss
Normal file
233
app/javascript/styles/mastodon/tooltips.scss
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
//
|
||||||
|
// Tooltips
|
||||||
|
// --------------------------------------------------
|
||||||
|
$font-size-base: 14px;
|
||||||
|
$line-height-base: 1.5;
|
||||||
|
$border-radius-base: 5px;
|
||||||
|
$overlay-shadow: 0 0 4px rgba(0, 0, 0, 0.17);
|
||||||
|
//** Tooltip text color
|
||||||
|
$tooltip-color: #fff;
|
||||||
|
//** Tooltip background color
|
||||||
|
$tooltip-bg: #000;
|
||||||
|
$tooltip-opacity: 0.9;
|
||||||
|
|
||||||
|
//** Tooltip arrow width
|
||||||
|
$tooltip-arrow-width: 5px;
|
||||||
|
//** Tooltip distance with trigger
|
||||||
|
$tooltip-distance: $tooltip-arrow-width + 4;
|
||||||
|
//** Tooltip arrow color
|
||||||
|
$tooltip-arrow-color: $tooltip-bg;
|
||||||
|
|
||||||
|
// Base class
|
||||||
|
.rc-tooltip {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1070;
|
||||||
|
display: block;
|
||||||
|
visibility: visible;
|
||||||
|
// remove left/top by yiminghe
|
||||||
|
// left: -9999px;
|
||||||
|
// top: -9999px;
|
||||||
|
font-size: $font-size-base;
|
||||||
|
line-height: $line-height-base;
|
||||||
|
font-weight: 500;
|
||||||
|
opacity: $tooltip-opacity;
|
||||||
|
will-change: opacity, transform;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
&-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-top, &-placement-topLeft, &-placement-topRight {
|
||||||
|
padding: $tooltip-arrow-width 0 $tooltip-distance 0;
|
||||||
|
}
|
||||||
|
&-placement-right, &-placement-rightTop, &-placement-rightBottom {
|
||||||
|
padding: 0 $tooltip-arrow-width 0 $tooltip-distance;
|
||||||
|
}
|
||||||
|
&-placement-bottom, &-placement-bottomLeft, &-placement-bottomRight {
|
||||||
|
padding: $tooltip-distance 0 $tooltip-arrow-width 0;
|
||||||
|
}
|
||||||
|
&-placement-left, &-placement-leftTop, &-placement-leftBottom {
|
||||||
|
padding: 0 $tooltip-distance 0 $tooltip-arrow-width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapper for the tooltip content
|
||||||
|
.rc-tooltip-inner {
|
||||||
|
padding: 8px 12px;
|
||||||
|
color: $tooltip-color;
|
||||||
|
text-align: left;
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: $tooltip-bg;
|
||||||
|
border-radius: $border-radius-base;
|
||||||
|
box-shadow: $overlay-shadow;
|
||||||
|
max-width: 290px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
min-height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arrows
|
||||||
|
.rc-tooltip-arrow {
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-color: transparent;
|
||||||
|
border-style: solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rc-tooltip {
|
||||||
|
&-placement-top &-arrow,
|
||||||
|
&-placement-topLeft &-arrow,
|
||||||
|
&-placement-topRight &-arrow {
|
||||||
|
bottom: $tooltip-distance - $tooltip-arrow-width;
|
||||||
|
margin-left: -$tooltip-arrow-width;
|
||||||
|
border-width: $tooltip-arrow-width $tooltip-arrow-width 0;
|
||||||
|
border-top-color: $tooltip-arrow-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-top &-arrow {
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-topLeft &-arrow {
|
||||||
|
left: 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-topRight &-arrow {
|
||||||
|
right: 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-right &-arrow,
|
||||||
|
&-placement-rightTop &-arrow,
|
||||||
|
&-placement-rightBottom &-arrow {
|
||||||
|
left: $tooltip-distance - $tooltip-arrow-width;
|
||||||
|
margin-top: -$tooltip-arrow-width;
|
||||||
|
border-width: $tooltip-arrow-width $tooltip-arrow-width $tooltip-arrow-width 0;
|
||||||
|
border-right-color: $tooltip-arrow-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-right &-arrow {
|
||||||
|
top: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-rightTop &-arrow {
|
||||||
|
top: 15%;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-rightBottom &-arrow {
|
||||||
|
bottom: 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-left &-arrow,
|
||||||
|
&-placement-leftTop &-arrow,
|
||||||
|
&-placement-leftBottom &-arrow {
|
||||||
|
right: $tooltip-distance - $tooltip-arrow-width;
|
||||||
|
margin-top: -$tooltip-arrow-width;
|
||||||
|
border-width: $tooltip-arrow-width 0 $tooltip-arrow-width $tooltip-arrow-width;
|
||||||
|
border-left-color: $tooltip-arrow-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-left &-arrow {
|
||||||
|
top: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-leftTop &-arrow {
|
||||||
|
top: 15%;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-leftBottom &-arrow {
|
||||||
|
bottom: 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-bottom &-arrow,
|
||||||
|
&-placement-bottomLeft &-arrow,
|
||||||
|
&-placement-bottomRight &-arrow {
|
||||||
|
top: $tooltip-distance - $tooltip-arrow-width;
|
||||||
|
margin-left: -$tooltip-arrow-width;
|
||||||
|
border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;
|
||||||
|
border-bottom-color: $tooltip-arrow-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-bottom &-arrow {
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-bottomLeft &-arrow {
|
||||||
|
left: 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-placement-bottomRight &-arrow {
|
||||||
|
right: 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin effect(){
|
||||||
|
animation-duration: 50ms;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
& {
|
||||||
|
&-zoom-enter,
|
||||||
|
&-zoom-leave {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-zoom-enter,
|
||||||
|
&-zoom-appear {
|
||||||
|
opacity: 0;
|
||||||
|
@include effect();
|
||||||
|
animation-timing-function: cubic-bezier(0.18, 0.89, 0.32, 1.28);
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-zoom-leave {
|
||||||
|
@include effect();
|
||||||
|
animation-timing-function: cubic-bezier(0.6, -0.3, 0.74, 0.05);
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-zoom-enter,
|
||||||
|
&-zoom-appear {
|
||||||
|
&-active {
|
||||||
|
animation-name: rcToolTipZoomIn;
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-zoom-leave {
|
||||||
|
&-active {
|
||||||
|
animation-name: rcToolTipZoomOut;
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rcToolTipZoomIn {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
transform: scale(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
transform: scale(1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rcToolTipZoomOut {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
transform: scale(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
transform: scale(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -124,6 +124,7 @@
|
||||||
"promise.prototype.finally": "^3.1.2",
|
"promise.prototype.finally": "^3.1.2",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
"punycode": "^2.1.0",
|
"punycode": "^2.1.0",
|
||||||
|
"rc-tooltip": "^4.2.1",
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
"react-hotkeys": "^1.1.4",
|
"react-hotkeys": "^1.1.4",
|
||||||
|
|
74
yarn.lock
74
yarn.lock
|
@ -2,6 +2,11 @@
|
||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@ant-design/css-animation@^1.7.2":
|
||||||
|
version "1.7.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@ant-design/css-animation/-/css-animation-1.7.2.tgz#4ee5d2ec0fb7cc0a78b44e1c82628bd4621ac7e3"
|
||||||
|
integrity sha512-bvVOe7A+r7lws58B7r+fgnQDK90cV45AXuvGx6i5CCSX1W/M3AJnHsNggDANBxEtWdNdFWcDd5LorB+RdSIlBw==
|
||||||
|
|
||||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.1":
|
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.1":
|
||||||
version "7.10.1"
|
version "7.10.1"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.1.tgz#d5481c5095daa1c57e16e54c6f9198443afb49ff"
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.1.tgz#d5481c5095daa1c57e16e54c6f9198443afb49ff"
|
||||||
|
@ -988,7 +993,7 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.12.0"
|
regenerator-runtime "^0.12.0"
|
||||||
|
|
||||||
"@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
|
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.2.0", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
|
||||||
version "7.10.2"
|
version "7.10.2"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.2.tgz#d103f21f2602497d38348a32e008637d506db839"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.2.tgz#d103f21f2602497d38348a32e008637d506db839"
|
||||||
integrity sha512-6sF3uQw2ivImfVIl62RZ7MXhO2tap69WeWK57vAaimT6AZbE4FbqjdEJIN1UqoD6wI6B+1n9UiagafH1sxjOtg==
|
integrity sha512-6sF3uQw2ivImfVIl62RZ7MXhO2tap69WeWK57vAaimT6AZbE4FbqjdEJIN1UqoD6wI6B+1n9UiagafH1sxjOtg==
|
||||||
|
@ -2840,7 +2845,7 @@ class-utils@^0.3.5:
|
||||||
isobject "^3.0.0"
|
isobject "^3.0.0"
|
||||||
static-extend "^0.1.1"
|
static-extend "^0.1.1"
|
||||||
|
|
||||||
classnames@^2.2.5:
|
classnames@2.x, classnames@^2.2.5, classnames@^2.2.6:
|
||||||
version "2.2.6"
|
version "2.2.6"
|
||||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
|
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
|
||||||
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
|
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
|
||||||
|
@ -3744,6 +3749,11 @@ doctrine@^3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
|
|
||||||
|
dom-align@^1.7.0:
|
||||||
|
version "1.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/dom-align/-/dom-align-1.12.0.tgz#56fb7156df0b91099830364d2d48f88963f5a29c"
|
||||||
|
integrity sha512-YkoezQuhp3SLFGdOlr5xkqZ640iXrnHAwVYcDg8ZKRUtO7mSzSC2BA5V0VuyAwPSJA4CLIc6EDDJh4bEsD2+zA==
|
||||||
|
|
||||||
dom-helpers@^3.2.1, dom-helpers@^3.4.0:
|
dom-helpers@^3.2.1, dom-helpers@^3.4.0:
|
||||||
version "3.4.0"
|
version "3.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8"
|
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8"
|
||||||
|
@ -8769,7 +8779,7 @@ quote@^0.4.0:
|
||||||
resolved "https://registry.yarnpkg.com/quote/-/quote-0.4.0.tgz#10839217f6c1362b89194044d29b233fd7f32f01"
|
resolved "https://registry.yarnpkg.com/quote/-/quote-0.4.0.tgz#10839217f6c1362b89194044d29b233fd7f32f01"
|
||||||
integrity sha1-EIOSF/bBNiuJGUBE0psjP9fzLwE=
|
integrity sha1-EIOSF/bBNiuJGUBE0psjP9fzLwE=
|
||||||
|
|
||||||
raf@^3.1.0, raf@^3.4.1:
|
raf@^3.1.0, raf@^3.4.0, raf@^3.4.1:
|
||||||
version "3.4.1"
|
version "3.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
|
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
|
||||||
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
|
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
|
||||||
|
@ -8819,6 +8829,54 @@ raw-body@2.4.0:
|
||||||
iconv-lite "0.4.24"
|
iconv-lite "0.4.24"
|
||||||
unpipe "1.0.0"
|
unpipe "1.0.0"
|
||||||
|
|
||||||
|
rc-align@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/rc-align/-/rc-align-4.0.0.tgz#7a5b212051bdd840b406a6ad547076534a843691"
|
||||||
|
integrity sha512-0mKKfiZGo7VNiRCmnI4MTOG72pBFF0H08zebqcJyXcAm2hgAqTUtvt4I0pjMHh1WdYg+iQDjowpB5X8mZTN2vw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.10.1"
|
||||||
|
classnames "2.x"
|
||||||
|
dom-align "^1.7.0"
|
||||||
|
rc-util "^5.0.1"
|
||||||
|
resize-observer-polyfill "^1.5.1"
|
||||||
|
|
||||||
|
rc-animate@^3.0.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/rc-animate/-/rc-animate-3.1.0.tgz#051b689c2c7194e4c8ae016d32a0e5f9de6c8baa"
|
||||||
|
integrity sha512-8FsM+3B1H+0AyTyGggY6JyVldHTs1CyYT8CfTmG/nGHHXlecvSLeICJhcKgRLjUiQlctNnRtB1rwz79cvBVmrw==
|
||||||
|
dependencies:
|
||||||
|
"@ant-design/css-animation" "^1.7.2"
|
||||||
|
classnames "^2.2.6"
|
||||||
|
raf "^3.4.0"
|
||||||
|
rc-util "^5.0.1"
|
||||||
|
|
||||||
|
rc-tooltip@^4.2.1:
|
||||||
|
version "4.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-4.2.1.tgz#c1a2d5017ee03a771a9301c0dfdb46dfdf8fef94"
|
||||||
|
integrity sha512-oykuaGsHg7RFvPUaxUpxo7ScEqtH61C66x4JUmjlFlSS8gSx2L8JFtfwM1D68SLBxUqGqJObtxj4TED75gQTiA==
|
||||||
|
dependencies:
|
||||||
|
rc-trigger "^4.2.1"
|
||||||
|
|
||||||
|
rc-trigger@^4.2.1:
|
||||||
|
version "4.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-4.3.0.tgz#94ea1851d123359716d1dc3030083c015a92ecfb"
|
||||||
|
integrity sha512-jnGNzosXmDdivMBjPCYe/AfOXTpJU2/xQ9XukgoXDQEoZq/9lcI1r7eUIfq70WlWpLxlUEqQktiV3hwyy6Nw9g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.10.1"
|
||||||
|
classnames "^2.2.6"
|
||||||
|
raf "^3.4.1"
|
||||||
|
rc-align "^4.0.0"
|
||||||
|
rc-animate "^3.0.0"
|
||||||
|
rc-util "^5.0.1"
|
||||||
|
|
||||||
|
rc-util@^5.0.1:
|
||||||
|
version "5.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.0.4.tgz#297bd719b1bd00b3c947a884ab7ef0a07c55dce6"
|
||||||
|
integrity sha512-cd19RCrE0DJH6UcJ9+V3eaXA/5sNWyVKOKkWl8ZM2OqgNzVb8fv0obf/TkuvSN43tmTsgqY8k7OqpFYHhmef8g==
|
||||||
|
dependencies:
|
||||||
|
react-is "^16.12.0"
|
||||||
|
shallowequal "^1.1.0"
|
||||||
|
|
||||||
react-dom@^16.13.1:
|
react-dom@^16.13.1:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
|
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
|
||||||
|
@ -9425,6 +9483,11 @@ reselect@^4.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7"
|
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7"
|
||||||
integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==
|
integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==
|
||||||
|
|
||||||
|
resize-observer-polyfill@^1.5.1:
|
||||||
|
version "1.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
|
||||||
|
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
|
||||||
|
|
||||||
resolve-cwd@^2.0.0:
|
resolve-cwd@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
|
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
|
||||||
|
@ -9872,6 +9935,11 @@ shallow-equal@^1.2.1:
|
||||||
resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da"
|
resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da"
|
||||||
integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==
|
integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==
|
||||||
|
|
||||||
|
shallowequal@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
|
||||||
|
integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
|
||||||
|
|
||||||
shebang-command@^1.2.0:
|
shebang-command@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
||||||
|
|
Loading…
Reference in a new issue