feat(react): add Tooltip to App.tsx

This commit includes the addition of the Tooltip component to the App.tsx in the react package. With this feature, application elements now display messages based on their status (success or error) upon interaction, enhancing the user experience. Additionally, a copy-to-clipboard functionality has been implemented.
This commit is contained in:
p-sw 2024-06-11 20:58:45 +09:00
parent ffb8504b09
commit 5dd74e4b3f

@ -29,7 +29,9 @@ import React, {
useContext, useContext,
useEffect, useEffect,
useRef, useRef,
useState,
} from "react"; } from "react";
import { Tooltip, TooltipContent } from "@components/Tooltip.tsx";
function buildThresholdList() { function buildThresholdList() {
const thresholds: number[] = []; const thresholds: number[] = [];
@ -49,6 +51,8 @@ function HashedHeaders(Level: `h${1 | 2 | 3 | 4 | 5 | 6}`) {
const internalRef = useRef<HTMLHeadingElement | null>(null); const internalRef = useRef<HTMLHeadingElement | null>(null);
const [_, setActiveHeadings] = useContext(HeadingContext); const [_, setActiveHeadings] = useContext(HeadingContext);
const { children, ...restProp } = prop;
useEffect(() => { useEffect(() => {
const observer = new IntersectionObserver( const observer = new IntersectionObserver(
([{ target, intersectionRatio }]) => { ([{ target, intersectionRatio }]) => {
@ -72,19 +76,58 @@ function HashedHeaders(Level: `h${1 | 2 | 3 | 4 | 5 | 6}`) {
}; };
}, [internalRef.current]); }, [internalRef.current]);
const [status, setStatus] = useState<"normal" | "error" | "success">(
"normal",
);
const messages = {
normal: "Click to copy link",
success: "Copied link!",
error: "Failed to copy..",
};
useEffect(() => {
if (status !== "normal") {
const timeout = setTimeout(() => {
setStatus("normal");
}, 3000);
return () => {
clearTimeout(timeout);
};
}
}, [status]);
return ( return (
<Level <Tooltip asChild position={"right"}>
{...prop} <Level
className={`${prop.className}`} ref={(el) => {
ref={(el) => { internalRef.current = el;
internalRef.current = el; if (typeof ref === "function") {
if (typeof ref === "function") { ref(el);
ref(el); } else if (el && ref) {
} else if (el && ref) { ref.current = el;
ref.current = el; }
} }}
}} className={`${prop.className} cursor-pointer select-none`}
/> onClick={async (e) => {
try {
await navigator.clipboard.writeText(
window.location.href.split("#")[0] + "#" + e.currentTarget.id,
);
setStatus("success");
} catch (e) {
setStatus("error");
}
}}
{...restProp}
>
{children}
<TooltipContent status={status} offset={"lg"} delay={"early"}>
<p className={"text-base font-normal whitespace-nowrap not-prose"}>
{messages[status]}
</p>
</TooltipContent>
</Level>
</Tooltip>
); );
}; };
} }