This commit is contained in:
Eugen Rochko 2020-06-16 00:41:27 +02:00
parent b1484cf3ce
commit 4d996426ac
19 changed files with 548 additions and 133 deletions

View file

@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import Tooltip from 'mastodon/components/tooltip';
export default class Button extends React.PureComponent {
@ -49,16 +50,17 @@ export default class Button extends React.PureComponent {
});
return (
<button
className={className}
disabled={this.props.disabled}
onClick={this.handleClick}
ref={this.setRef}
style={style}
title={this.props.title}
>
{this.props.text || this.props.children}
</button>
<Tooltip placement='bottom' overlay={this.props.title}>
<button
className={className}
disabled={this.props.disabled}
onClick={this.handleClick}
ref={this.setRef}
style={style}
>
{this.props.text || this.props.children}
</button>
</Tooltip>
);
}

View file

@ -1,20 +1,24 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import Tooltip from 'mastodon/components/tooltip';
export default class Icon extends React.PureComponent {
static propTypes = {
id: PropTypes.string.isRequired,
className: PropTypes.string,
title: PropTypes.node,
fixedWidth: PropTypes.bool,
};
render () {
const { id, className, fixedWidth, ...other } = this.props;
const { id, className, fixedWidth, title, ...other } = this.props;
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>
);
}

View file

@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import Icon from 'mastodon/components/icon';
import Tooltip from 'mastodon/components/tooltip';
export default class IconButton extends React.PureComponent {
@ -114,22 +115,23 @@ export default class IconButton extends React.PureComponent {
});
return (
<button
aria-label={title}
aria-pressed={pressed}
aria-expanded={expanded}
title={title}
className={classes}
onClick={this.handleClick}
onMouseDown={this.handleMouseDown}
onKeyDown={this.handleKeyDown}
onKeyPress={this.handleKeyPress}
style={style}
tabIndex={tabIndex}
disabled={disabled}
>
<Icon id={icon} fixedWidth aria-hidden='true' />
</button>
<Tooltip placement='bottom' overlay={title}>
<button
aria-label={title}
aria-pressed={pressed}
aria-expanded={expanded}
className={classes}
onClick={this.handleClick}
onMouseDown={this.handleMouseDown}
onKeyDown={this.handleKeyDown}
onKeyPress={this.handleKeyPress}
style={style}
tabIndex={tabIndex}
disabled={disabled}
>
<Icon id={icon} fixedWidth aria-hidden='true' />
</button>
</Tooltip>
);
}

View file

@ -8,6 +8,7 @@ import { isIOS } from '../is_mobile';
import classNames from 'classnames';
import { autoPlayGif, cropImages, displayMedia, useBlurhash } from '../initial_state';
import { decode } from 'blurhash';
import Tooltip from 'mastodon/components/tooltip';
const messages = defineMessages({
toggle_visible: { id: 'media_gallery.toggle_visible',
@ -165,9 +166,11 @@ class Item extends React.PureComponent {
if (attachment.get('type') === 'unknown') {
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}%` }}>
<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'>
<canvas width={32} height={32} ref={this.setCanvasRef} className='media-gallery__preview' />
</a>
<Tooltip placement='bottom' overlay={attachment.get('description')}>
<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'>
<canvas width={32} height={32} ref={this.setCanvasRef} className='media-gallery__preview' />
</a>
</Tooltip>
</div>
);
} else if (attachment.get('type') === 'image') {
@ -188,42 +191,44 @@ class Item extends React.PureComponent {
const y = ((focusY / -2) + .5) * 100;
thumbnail = (
<a
className='media-gallery__item-thumbnail'
href={attachment.get('remote_url') || originalUrl}
onClick={this.handleClick}
target='_blank'
rel='noopener noreferrer'
>
<img
src={previewUrl}
srcSet={srcSet}
sizes={sizes}
alt={attachment.get('description')}
title={attachment.get('description')}
style={{ objectPosition: `${x}% ${y}%` }}
onLoad={this.handleImageLoad}
/>
</a>
<Tooltip placement='bottom' overlay={attachment.get('description')}>
<a
className='media-gallery__item-thumbnail'
href={attachment.get('remote_url') || originalUrl}
onClick={this.handleClick}
target='_blank'
rel='noopener noreferrer'
>
<img
src={previewUrl}
srcSet={srcSet}
sizes={sizes}
alt={attachment.get('description')}
style={{ objectPosition: `${x}% ${y}%` }}
onLoad={this.handleImageLoad}
/>
</a>
</Tooltip>
);
} else if (attachment.get('type') === 'gifv') {
const autoPlay = !isIOS() && this.getAutoPlay();
thumbnail = (
<div className={classNames('media-gallery__gifv', { autoplay: autoPlay })}>
<video
className='media-gallery__item-gifv-thumbnail'
aria-label={attachment.get('description')}
title={attachment.get('description')}
role='application'
src={attachment.get('url')}
onClick={this.handleClick}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
autoPlay={autoPlay}
loop
muted
/>
<Tooltip placement='bottom' overlay={attachment.get('description')}>
<video
className='media-gallery__item-gifv-thumbnail'
aria-label={attachment.get('description')}
role='application'
src={attachment.get('url')}
onClick={this.handleClick}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
autoPlay={autoPlay}
loop
muted
/>
</Tooltip>
<span className='media-gallery__gifv__label'>GIF</span>
</div>

View file

@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import Tooltip from 'mastodon/components/tooltip';
export default class Permalink extends React.PureComponent {
@ -28,12 +29,14 @@ export default class Permalink extends React.PureComponent {
}
render () {
const { href, children, className, onInterceptClick, ...other } = this.props;
const { href, children, className, onInterceptClick, title, ...other } = this.props;
return (
<a target='_blank' href={href} onClick={this.handleClick} {...other} className={`permalink${className ? ' ' + className : ''}`}>
{children}
</a>
<Tooltip placement='top' overlay={title}>
<a target='_blank' href={href} onClick={this.handleClick} {...other} className={`permalink${className ? ' ' + className : ''}`}>
{children}
</a>
</Tooltip>
);
}

View file

@ -1,6 +1,7 @@
import React from 'react';
import { injectIntl, defineMessages } from 'react-intl';
import PropTypes from 'prop-types';
import Tooltip from 'mastodon/components/tooltip';
const messages = defineMessages({
today: { id: 'relative_time.today', defaultMessage: 'today' },
@ -181,11 +182,14 @@ class RelativeTimestamp extends React.Component {
const timeGiven = timestamp.includes('T');
const date = new Date(timestamp);
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 (
<time dateTime={timestamp} title={intl.formatDate(date, dateFormatOptions)}>
{relativeTime}
</time>
<Tooltip placement='top' overlay={formatted}>
<time dateTime={timestamp} aria-label={formatted}>
{relativeTime}
</time>
</Tooltip>
);
}

View file

@ -16,6 +16,7 @@ import { MediaGallery, Video, Audio } from '../features/ui/util/async-components
import { HotKeys } from 'react-hotkeys';
import classNames from 'classnames';
import Icon from 'mastodon/components/icon';
import Tooltip from 'mastodon/components/tooltip';
import { displayMedia } from '../initial_state';
// 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'>
<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'>
<div className='status__avatar'>
{statusAvatar}
</div>
<Tooltip placement='top' overlay={status.getIn(['account', 'acct'])}>
<a onClick={this.handleAccountClick} data-id={status.getIn(['account', 'id'])} href={status.getIn(['account', 'url'])} className='status__display-name' target='_blank' rel='noopener noreferrer'>
<div className='status__avatar'>
{statusAvatar}
</div>
<DisplayName account={status.get('account')} others={otherAccounts} />
</a>
<DisplayName account={status.get('account')} others={otherAccounts} />
</a>
</Tooltip>
</div>
<StatusContent status={status} onClick={this.handleClick} expanded={!status.get('hidden')} showThread={showThread} onExpandedToggle={this.handleExpandedToggle} collapsable onCollapsedToggle={this.handleCollapsedToggle} />

View 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;

View file

@ -11,6 +11,7 @@ import Avatar from 'mastodon/components/avatar';
import { shortNumberFormat } from 'mastodon/utils/numbers';
import { NavLink } from 'react-router-dom';
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
import Tooltip from 'mastodon/components/tooltip';
const messages = defineMessages({
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
@ -293,19 +294,34 @@ class Header extends ImmutablePureComponent {
<dt dangerouslySetInnerHTML={{ __html: proof.get('provider') }} />
<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) })}>
<Icon id='check' className='verified__mark' />
</span></a>
<Tooltip placement='top' overlay={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(proof.get('updated_at'), dateFormatOptions) })}>
<a href={proof.get('proof_url')} target='_blank' rel='noopener noreferrer'>
<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>
</dd>
</dl>
))}
{fields.map((pair, 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')}>
{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') }} />
<dd className={pair.get('verified_at') && 'verified'}>
{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>
</dl>
))}
@ -316,17 +332,23 @@ class Header extends ImmutablePureComponent {
</div>
<div className='account__header__extra__links'>
<NavLink isActive={this.isStatusesPageActive} activeClassName='active' to={`/accounts/${account.get('id')}`} title={intl.formatNumber(account.get('statuses_count'))}>
<strong>{shortNumberFormat(account.get('statuses_count'))}</strong> <FormattedMessage id='account.posts' defaultMessage='Toots' />
</NavLink>
<Tooltip placement='bottom' overlay={intl.formatNumber(account.get('statuses_count'))}>
<NavLink isActive={this.isStatusesPageActive} activeClassName='active' to={`/accounts/${account.get('id')}`}>
<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'))}>
<strong>{shortNumberFormat(account.get('following_count'))}</strong> <FormattedMessage id='account.follows' defaultMessage='Follows' />
</NavLink>
<Tooltip placement='bottom' overlay={intl.formatNumber(account.get('following_count'))}>
<NavLink exact activeClassName='active' to={`/accounts/${account.get('id')}/following`}>
<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'))}>
<strong>{shortNumberFormat(account.get('followers_count'))}</strong> <FormattedMessage id='account.followers' defaultMessage='Followers' />
</NavLink>
<Tooltip placement='bottom' overlay={intl.formatNumber(account.get('followers_count'))}>
<NavLink exact activeClassName='active' to={`/accounts/${account.get('id')}/followers`}>
<strong>{shortNumberFormat(account.get('followers_count'))}</strong> <FormattedMessage id='account.followers' defaultMessage='Followers' />
</NavLink>
</Tooltip>
</div>
</div>
</div>

View file

@ -3,6 +3,7 @@ import Avatar from '../../../components/avatar';
import DisplayName from '../../../components/display_name';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import Tooltip from 'mastodon/components/tooltip';
export default class AutosuggestAccount extends ImmutablePureComponent {
@ -14,10 +15,12 @@ export default class AutosuggestAccount extends ImmutablePureComponent {
const { account } = this.props;
return (
<div className='autosuggest-account' title={account.get('acct')}>
<div className='autosuggest-account-icon'><Avatar account={account} size={18} /></div>
<DisplayName account={account} />
</div>
<Tooltip placement='top' overlay={account.get('acct')}>
<div className='autosuggest-account'>
<div className='autosuggest-account-icon'><Avatar account={account} size={18} /></div>
<DisplayName account={account} />
</div>
</Tooltip>
);
}

View file

@ -7,6 +7,7 @@ import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import detectPassiveEvents from 'detect-passive-events';
import { buildCustomEmojis, categoriesFromEmojis } from '../../emoji/emoji';
import Tooltip from 'mastodon/components/tooltip';
const messages = defineMessages({
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
@ -358,13 +359,15 @@ class EmojiPickerDropdown extends React.PureComponent {
return (
<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}>
{button || <img
className={classNames('emojione', { 'pulse-loading': active && loading })}
alt='🙂'
src={`${assetHost}/emoji/1f602.svg`}
/>}
</div>
<Tooltip placement='top' overlay={title}>
<div ref={this.setTargetRef} className='emoji-button' aria-label={title} aria-expanded={active} role='button' onClick={this.onToggle} onKeyDown={this.onToggle} tabIndex={0}>
{button || <img
className={classNames('emojione', { 'pulse-loading': active && loading })}
alt='🙂'
src={`${assetHost}/emoji/1f602.svg`}
/>}
</div>
</Tooltip>
<Overlay show={active} placement={placement} target={this.findTarget}>
<EmojiPickerMenu

View file

@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import Tooltip from 'mastodon/components/tooltip';
const iconStyle = {
height: null,
@ -26,16 +27,17 @@ export default class TextIconButton extends React.PureComponent {
const { label, title, active, ariaControls } = this.props;
return (
<button
title={title}
aria-label={title}
className={`text-icon-button ${active ? 'active' : ''}`}
aria-expanded={active}
onClick={this.handleClick}
aria-controls={ariaControls} style={iconStyle}
>
{label}
</button>
<Tooltip placement='bottom' overlay={title}>
<button
aria-label={title}
className={`text-icon-button ${active ? 'active' : ''}`}
aria-expanded={active}
onClick={this.handleClick}
aria-controls={ariaControls} style={iconStyle}
>
{label}
</button>
</Tooltip>
);
}

View file

@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import classNames from 'classnames';
import { changeComposeSensitivity } from 'mastodon/actions/compose';
import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
import Tooltip from 'mastodon/components/tooltip';
const messages = defineMessages({
marked: { id: 'compose_form.sensitive.marked', defaultMessage: 'Media is marked as sensitive' },
@ -37,19 +38,21 @@ class SensitiveButton extends React.PureComponent {
return (
<div className='compose-form__sensitive-button'>
<label className={classNames('icon-button', { active })} title={intl.formatMessage(active ? messages.marked : messages.unmarked)}>
<input
name='mark-sensitive'
type='checkbox'
checked={active}
onChange={onClick}
disabled={disabled}
/>
<Tooltip placement='top' overlay={intl.formatMessage(active ? messages.marked : messages.unmarked)}>
<label className={classNames('icon-button', { active })} aria-label={intl.formatMessage(active ? messages.marked : messages.unmarked)}>
<input
name='mark-sensitive'
type='checkbox'
checked={active}
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' />
</label>
<FormattedMessage id='compose_form.sensitive.hide' defaultMessage='Mark media as sensitive' />
</label>
</Tooltip>
</div>
);
}

View file

@ -16,6 +16,7 @@ import { openModal } from 'mastodon/actions/modal';
import elephantUIPlane from '../../../images/elephant_ui_plane.svg';
import { mascot } from '../../initial_state';
import Icon from 'mastodon/components/icon';
import Tooltip from 'mastodon/components/tooltip';
import { logOut } from 'mastodon/utils/log_out';
const messages = defineMessages({
@ -97,21 +98,55 @@ class Compose extends React.PureComponent {
const { columns } = this.props;
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') && (
<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') && (
<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') && (
<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') && (
<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>
);
}

View file

@ -24,5 +24,6 @@
@import 'mastodon/tables';
@import 'mastodon/admin';
@import 'mastodon/dashboard';
@import 'mastodon/tooltips';
@import 'mastodon/rtl';
@import 'mastodon/accessibility';

View file

@ -1076,8 +1076,7 @@
}
.status__info .status__display-name {
display: block;
max-width: 100%;
display: inline-flex;
padding-right: 25px;
}

View 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);
}
}
}