增加Tooltip组件。
This commit is contained in:
parent
8222cfc2e9
commit
4d4192c0f0
66
src/components/Tooltip.module.css
Normal file
66
src/components/Tooltip.module.css
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
@layer components {
|
||||||
|
.tooltip_container {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.tooltip {
|
||||||
|
position: absolute;
|
||||||
|
padding-inline: calc(var(--spacing) * 3);
|
||||||
|
padding-block: calc(var(--spacing) * 1);
|
||||||
|
border-radius: var(--border-radius-xxs);
|
||||||
|
color: light-dark(
|
||||||
|
oklch(from var(--color-neutral) calc(l + (1 - l) * 0.8) c h),
|
||||||
|
oklch(from var(--color-neutral) calc(l + (1 - l) * 0.7) c h)
|
||||||
|
);
|
||||||
|
background-color: light-dark(
|
||||||
|
oklch(from var(--color-qianbai) calc(l * 0.6) c h),
|
||||||
|
oklch(from var(--color-qihei) calc(l + (1 - l) * 0.2) c h)
|
||||||
|
);
|
||||||
|
font-size: var(--font-size-m);
|
||||||
|
width: fit-content;
|
||||||
|
max-width: 40em;
|
||||||
|
text-wrap: balance;
|
||||||
|
word-break: keep-all;
|
||||||
|
box-shadow: 0 4px 6px -1px oklch(from var(--color-black) l c h / 0.1),
|
||||||
|
0 2px 4px -2px oklch(from var(--color-black) l c h / 0.1);
|
||||||
|
pointer-events: none;
|
||||||
|
&.top {
|
||||||
|
bottom: 100%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
margin-bottom: calc(var(--spacing) * 4);
|
||||||
|
}
|
||||||
|
&.bottom {
|
||||||
|
top: 100%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
margin-top: calc(var(--spacing) * 4);
|
||||||
|
}
|
||||||
|
&.left {
|
||||||
|
top: 50%;
|
||||||
|
right: 100%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
margin-right: calc(var(--spacing) * 4);
|
||||||
|
}
|
||||||
|
&.right {
|
||||||
|
top: 50%;
|
||||||
|
left: 100%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
margin-left: calc(var(--spacing) * 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fade_enter {
|
||||||
|
opacity: 0%;
|
||||||
|
transition: opacity 200ms ease-in;
|
||||||
|
}
|
||||||
|
.fade_enter_active {
|
||||||
|
opacity: 100%;
|
||||||
|
}
|
||||||
|
.fade_exit {
|
||||||
|
opacity: 100%;
|
||||||
|
transition: opacity 200ms ease-out;
|
||||||
|
}
|
||||||
|
.fade_exit_active {
|
||||||
|
opacity: 0%;
|
||||||
|
}
|
||||||
|
}
|
46
src/components/Tooltip.tsx
Normal file
46
src/components/Tooltip.tsx
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import cx from 'clsx';
|
||||||
|
import { ReactNode, useRef, useState } from 'react';
|
||||||
|
import { CSSTransition } from 'react-transition-group';
|
||||||
|
import styles from './Tooltip.module.css';
|
||||||
|
|
||||||
|
interface TooltipProps {
|
||||||
|
content: ReactNode;
|
||||||
|
position?: 'top' | 'bottom' | 'left' | 'right';
|
||||||
|
children?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const positionMap = {
|
||||||
|
top: styles.top,
|
||||||
|
bottom: styles.bottom,
|
||||||
|
left: styles.left,
|
||||||
|
right: styles.right,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Tooltip({ content, position = 'top', children }: TooltipProps) {
|
||||||
|
const [show, setShow] = useState(false);
|
||||||
|
const contentRef = useRef<HTMLDivElement>();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={styles.tooltip_container}
|
||||||
|
onMouseEnter={() => setShow(true)}
|
||||||
|
onMouseLeave={() => setShow(false)}>
|
||||||
|
{children}
|
||||||
|
<CSSTransition
|
||||||
|
nodeRef={contentRef}
|
||||||
|
in={show}
|
||||||
|
unmountOnExit
|
||||||
|
classNames={{
|
||||||
|
enter: styles.fade_enter,
|
||||||
|
enterActive: styles.fade_enter_active,
|
||||||
|
exit: styles.fade_exit,
|
||||||
|
exitActive: styles.fade_exit_active,
|
||||||
|
}}
|
||||||
|
timeout={200}>
|
||||||
|
<div className={cx(styles.tooltip, positionMap[position])} ref={contentRef}>
|
||||||
|
{content}
|
||||||
|
</div>
|
||||||
|
</CSSTransition>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user