Files
netbird/client/ui/frontend/src/components/TruncatedText.tsx
2026-06-02 11:37:56 +02:00

43 lines
1.3 KiB
TypeScript

import { useLayoutEffect, useRef, useState, type ReactNode } from "react";
import { Tooltip } from "@/components/Tooltip";
type Props = {
text: string;
className?: string;
tooltipContent?: ReactNode;
delayDuration?: number;
};
// Renders text with `truncate`; measures scrollWidth vs clientWidth after
// layout and wraps in a Tooltip only when the text actually overflows. Avoids
// the "tooltip on hover even though everything fits" annoyance. The caller
// supplies the wrapper styling (font, max-width, etc.) via className — this
// component only owns the truncate + measure + tooltip behavior.
export const TruncatedText = ({
text,
className,
tooltipContent,
delayDuration = 600,
}: Props) => {
const ref = useRef<HTMLSpanElement>(null);
const [overflowing, setOverflowing] = useState(false);
useLayoutEffect(() => {
const el = ref.current;
if (!el) return;
setOverflowing(el.scrollWidth > el.clientWidth);
}, [text]);
const span = (
<span ref={ref} className={className}>
{text}
</span>
);
if (!overflowing) return span;
return (
<Tooltip content={tooltipContent ?? text} delayDuration={delayDuration}>
{span}
</Tooltip>
);
};