feat: further Tooltip improvements
This commit is contained in:
@@ -22,22 +22,6 @@
|
||||
|
||||
&--has-tooltip {
|
||||
position: relative;
|
||||
|
||||
}
|
||||
|
||||
.btn__tooltip {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translate(-50%, -10px);
|
||||
}
|
||||
|
||||
.btn__content {
|
||||
&:hover {
|
||||
.btn__tooltip {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&--icon-style-without-border {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { isValidElement } from 'react';
|
||||
import React, { Fragment, isValidElement } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Props } from './types';
|
||||
|
||||
@@ -21,31 +21,31 @@ const icons = {
|
||||
|
||||
const baseClass = 'btn';
|
||||
|
||||
const ButtonContents = ({ children, icon, tooltip }) => {
|
||||
const ButtonContents = ({ children, icon, tooltip, showTooltip }) => {
|
||||
const BuiltInIcon = icons[icon];
|
||||
|
||||
return (
|
||||
<span
|
||||
className={`${baseClass}__content`}
|
||||
>
|
||||
<Fragment>
|
||||
<Tooltip
|
||||
className={`${baseClass}__tooltip`}
|
||||
show={tooltip}
|
||||
show={showTooltip}
|
||||
>
|
||||
{tooltip}
|
||||
</Tooltip>
|
||||
{children && (
|
||||
<span className={`${baseClass}__label`}>
|
||||
{children}
|
||||
</span>
|
||||
)}
|
||||
{icon && (
|
||||
<span className={`${baseClass}__icon`}>
|
||||
{isValidElement(icon) && icon}
|
||||
{BuiltInIcon && <BuiltInIcon />}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
<span className={`${baseClass}__content`}>
|
||||
{children && (
|
||||
<span className={`${baseClass}__label`}>
|
||||
{children}
|
||||
</span>
|
||||
)}
|
||||
{icon && (
|
||||
<span className={`${baseClass}__icon`}>
|
||||
{isValidElement(icon) && icon}
|
||||
{BuiltInIcon && <BuiltInIcon />}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -70,6 +70,8 @@ const Button: React.FC<Props> = (props) => {
|
||||
tooltip,
|
||||
} = props;
|
||||
|
||||
const [showTooltip, setShowTooltip] = React.useState(false);
|
||||
|
||||
const classes = [
|
||||
baseClass,
|
||||
className && className,
|
||||
@@ -85,6 +87,7 @@ const Button: React.FC<Props> = (props) => {
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
function handleClick(event) {
|
||||
setShowTooltip(false);
|
||||
if (type !== 'submit' && onClick) event.preventDefault();
|
||||
if (onClick) onClick(event);
|
||||
}
|
||||
@@ -94,6 +97,8 @@ const Button: React.FC<Props> = (props) => {
|
||||
type,
|
||||
className: classes,
|
||||
disabled,
|
||||
onMouseEnter: tooltip ? () => setShowTooltip(true) : undefined,
|
||||
onMouseLeave: tooltip ? () => setShowTooltip(false) : undefined,
|
||||
onClick: !disabled ? handleClick : undefined,
|
||||
rel: newTab ? 'noopener noreferrer' : undefined,
|
||||
target: newTab ? '_blank' : undefined,
|
||||
@@ -109,6 +114,7 @@ const Button: React.FC<Props> = (props) => {
|
||||
<ButtonContents
|
||||
icon={icon}
|
||||
tooltip={tooltip}
|
||||
showTooltip={showTooltip}
|
||||
>
|
||||
{children}
|
||||
</ButtonContents>
|
||||
@@ -124,6 +130,7 @@ const Button: React.FC<Props> = (props) => {
|
||||
<ButtonContents
|
||||
icon={icon}
|
||||
tooltip={tooltip}
|
||||
showTooltip={showTooltip}
|
||||
>
|
||||
{children}
|
||||
</ButtonContents>
|
||||
@@ -141,6 +148,7 @@ const Button: React.FC<Props> = (props) => {
|
||||
<ButtonContents
|
||||
icon={icon}
|
||||
tooltip={tooltip}
|
||||
showTooltip={showTooltip}
|
||||
>
|
||||
{children}
|
||||
</ButtonContents>
|
||||
|
||||
@@ -14,22 +14,8 @@
|
||||
width: 0px;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.tooltip {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import React, { useState, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Copy from '../../icons/Copy';
|
||||
import Tooltip from '../Tooltip';
|
||||
@@ -18,14 +18,6 @@ const CopyToClipboard: React.FC<Props> = ({
|
||||
const [hovered, setHovered] = useState(false);
|
||||
const { t } = useTranslation('general');
|
||||
|
||||
useEffect(() => {
|
||||
if (copied && !hovered) {
|
||||
setTimeout(() => {
|
||||
setCopied(false);
|
||||
}, 1500);
|
||||
}
|
||||
}, [copied, hovered]);
|
||||
|
||||
if (value) {
|
||||
return (
|
||||
<button
|
||||
@@ -44,13 +36,15 @@ const CopyToClipboard: React.FC<Props> = ({
|
||||
ref.current.select();
|
||||
ref.current.setSelectionRange(0, value.length + 1);
|
||||
document.execCommand('copy');
|
||||
|
||||
setCopied(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Copy />
|
||||
<Tooltip>
|
||||
<Tooltip
|
||||
show={hovered || copied}
|
||||
delay={copied ? 0 : undefined}
|
||||
>
|
||||
{copied && (successMessage ?? t('copied'))}
|
||||
{!copied && (defaultMessage ?? t('copy'))}
|
||||
</Tooltip>
|
||||
|
||||
@@ -30,7 +30,6 @@ export const MultiValueRemove: React.FC<MultiValueRemoveProps<OptionType>> = (pr
|
||||
<Tooltip
|
||||
className={`${baseClass}__tooltip`}
|
||||
show={showTooltip}
|
||||
delay={350}
|
||||
>
|
||||
{t('remove')}
|
||||
</Tooltip>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
$caretSize: 6;
|
||||
|
||||
.tooltip {
|
||||
opacity: 0;
|
||||
background-color: var(--theme-elevation-800);
|
||||
@@ -7,27 +9,33 @@
|
||||
z-index: 2;
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
transform: translate3d(-50%, -20%, 0);
|
||||
transform: translate3d(-50%, calc(#{$caretSize}px * -1), 0);
|
||||
padding: base(.2) base(.4);
|
||||
color: var(--theme-elevation-0);
|
||||
line-height: base(.75);
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
border-radius: 2px;
|
||||
transition: opacity .2s ease-in-out;
|
||||
visibility: hidden;
|
||||
|
||||
span {
|
||||
position: absolute;
|
||||
transform: translateX(-50%);
|
||||
top: calc(100% - #{base(.0625)});
|
||||
left: 50%;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border: 10px solid transparent;
|
||||
border-top-color: var(--theme-elevation-800);
|
||||
}
|
||||
&::after {
|
||||
content: ' ';
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translate3d(-50%, 100%, 0);
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: #{$caretSize}px solid transparent;
|
||||
border-right: #{$caretSize}px solid transparent;
|
||||
border-top: #{$caretSize}px solid var(--theme-elevation-800);
|
||||
}
|
||||
|
||||
&--show {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition: opacity .2s ease-in-out;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ const Tooltip: React.FC<Props> = (props) => {
|
||||
className,
|
||||
children,
|
||||
show: showFromProps = true,
|
||||
delay,
|
||||
delay = 350,
|
||||
} = props;
|
||||
|
||||
const [show, setShow] = React.useState(showFromProps);
|
||||
@@ -16,7 +16,7 @@ const Tooltip: React.FC<Props> = (props) => {
|
||||
useEffect(() => {
|
||||
let timerId: NodeJS.Timeout;
|
||||
|
||||
// do not use the delay on out
|
||||
// do not use the delay on transition-out
|
||||
if (delay && showFromProps) {
|
||||
timerId = setTimeout(() => {
|
||||
setShow(showFromProps);
|
||||
@@ -39,7 +39,6 @@ const Tooltip: React.FC<Props> = (props) => {
|
||||
].filter(Boolean).join(' ')}
|
||||
>
|
||||
{children}
|
||||
<span />
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -14,7 +14,10 @@ const Error: React.FC<Props> = (props) => {
|
||||
|
||||
if (showError) {
|
||||
return (
|
||||
<Tooltip className={baseClass}>
|
||||
<Tooltip
|
||||
className={baseClass}
|
||||
delay={0}
|
||||
>
|
||||
{message}
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
@@ -105,11 +105,11 @@ export const AddNewRelation: React.FC<Props> = ({ path, hasMany, relationTo, val
|
||||
className={`${baseClass}__add-button`}
|
||||
onMouseEnter={() => setShowTooltip(true)}
|
||||
onMouseLeave={() => setShowTooltip(false)}
|
||||
onClick={() => setShowTooltip(false)}
|
||||
>
|
||||
<Tooltip
|
||||
className={`${baseClass}__tooltip`}
|
||||
show={showTooltip}
|
||||
delay={350}
|
||||
>
|
||||
{t('addNewLabel', { label: relatedCollections[0].labels.singular })}
|
||||
</Tooltip>
|
||||
|
||||
@@ -60,7 +60,6 @@ export const MultiValueLabel: React.FC<MultiValueProps<Option>> = (props) => {
|
||||
<Tooltip
|
||||
className={`${baseClass}__tooltip`}
|
||||
show={showTooltip}
|
||||
delay={350}
|
||||
>
|
||||
{t('editLabel', { label: '' })}
|
||||
</Tooltip>
|
||||
|
||||
@@ -57,7 +57,6 @@ export const SingleValue: React.FC<SingleValueProps<Option>> = (props) => {
|
||||
<Tooltip
|
||||
className={`${baseClass}__tooltip`}
|
||||
show={showTooltip}
|
||||
delay={350}
|
||||
>
|
||||
{t('editLabel', { label: '' })}
|
||||
</Tooltip>
|
||||
|
||||
Reference in New Issue
Block a user