mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-04-09 04:18:32 +02:00
parent
c9a3b45ad4
commit
ffd14435a4
@ -1,4 +1,9 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, {
|
||||
useState,
|
||||
useEffect,
|
||||
useCallback,
|
||||
useLayoutEffect,
|
||||
} from "react";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
@ -28,6 +33,7 @@ import { FiAlertTriangle } from "react-icons/fi";
|
||||
|
||||
import { Slider } from "@/components/ui/slider";
|
||||
import { useUser } from "@/components/user/UserProvider";
|
||||
import { TruncatedText } from "@/components/ui/truncatedText";
|
||||
|
||||
interface LLMPopoverProps {
|
||||
llmProviders: LLMProviderDescriptor[];
|
||||
@ -158,9 +164,7 @@ export default function LLMPopover({
|
||||
size: 16,
|
||||
className: "flex-none my-auto text-black",
|
||||
})}
|
||||
<span className="line-clamp-1 ">
|
||||
{getDisplayNameForModel(name)}
|
||||
</span>
|
||||
<TruncatedText text={getDisplayNameForModel(name)} />
|
||||
{(() => {
|
||||
if (currentAssistant?.llm_model_version_override === name) {
|
||||
return (
|
||||
|
@ -4,10 +4,7 @@ import React, {
|
||||
ForwardedRef,
|
||||
forwardRef,
|
||||
useContext,
|
||||
useState,
|
||||
useCallback,
|
||||
useLayoutEffect,
|
||||
useRef,
|
||||
} from "react";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
@ -50,9 +47,9 @@ import {
|
||||
} from "@dnd-kit/sortable";
|
||||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import { CirclePlus, CircleX, PinIcon } from "lucide-react";
|
||||
import { CircleX, PinIcon } from "lucide-react";
|
||||
import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
|
||||
import { turborepoTraceAccess } from "next/dist/build/turborepo-access-trace";
|
||||
import { TruncatedText } from "@/components/ui/truncatedText";
|
||||
|
||||
interface HistorySidebarProps {
|
||||
liveAssistant?: Persona | null;
|
||||
@ -101,24 +98,6 @@ const SortableAssistant: React.FC<SortableAssistantProps> = ({
|
||||
...(isDragging ? { zIndex: 1000, position: "relative" as const } : {}),
|
||||
};
|
||||
|
||||
const nameRef = useRef<HTMLParagraphElement>(null);
|
||||
const hiddenNameRef = useRef<HTMLSpanElement>(null);
|
||||
const [isNameTruncated, setIsNameTruncated] = useState(false);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const checkTruncation = () => {
|
||||
if (nameRef.current && hiddenNameRef.current) {
|
||||
const visibleWidth = nameRef.current.offsetWidth;
|
||||
const fullTextWidth = hiddenNameRef.current.offsetWidth;
|
||||
setIsNameTruncated(fullTextWidth > visibleWidth);
|
||||
}
|
||||
};
|
||||
|
||||
checkTruncation();
|
||||
window.addEventListener("resize", checkTruncation);
|
||||
return () => window.removeEventListener("resize", checkTruncation);
|
||||
}, [assistant.name]);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={setNodeRef}
|
||||
@ -146,27 +125,11 @@ const SortableAssistant: React.FC<SortableAssistantProps> = ({
|
||||
} relative flex items-center gap-x-2 py-1 px-2 rounded-md`}
|
||||
>
|
||||
<AssistantIcon assistant={assistant} size={16} className="flex-none" />
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<p
|
||||
ref={nameRef}
|
||||
className="text-base text-left w-fit line-clamp-1 text-ellipsis text-black dark:text-[#D4D4D4]"
|
||||
>
|
||||
{assistant.name}
|
||||
</p>
|
||||
</TooltipTrigger>
|
||||
{isNameTruncated && (
|
||||
<TooltipContent>{assistant.name}</TooltipContent>
|
||||
)}
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<span
|
||||
ref={hiddenNameRef}
|
||||
className="absolute left-[-9999px] whitespace-nowrap"
|
||||
>
|
||||
{assistant.name}
|
||||
</span>
|
||||
<TruncatedText
|
||||
className="text-base mr-4 text-left w-fit line-clamp-1 text-ellipsis text-black dark:text-[#D4D4D4]"
|
||||
text={assistant.name}
|
||||
/>
|
||||
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
|
86
web/src/components/ui/truncatedText.tsx
Normal file
86
web/src/components/ui/truncatedText.tsx
Normal file
@ -0,0 +1,86 @@
|
||||
import React, {
|
||||
useState,
|
||||
useRef,
|
||||
useLayoutEffect,
|
||||
HTMLAttributes,
|
||||
} from "react";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
|
||||
interface TruncatedTextProps extends HTMLAttributes<HTMLSpanElement> {
|
||||
text: string;
|
||||
tooltipClassName?: string;
|
||||
tooltipSide?: "top" | "right" | "bottom" | "left";
|
||||
tooltipSideOffset?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders passed in text on a single line. If text is truncated,
|
||||
* shows a tooltip on hover with the full text.
|
||||
*/
|
||||
export function TruncatedText({
|
||||
text,
|
||||
tooltipClassName,
|
||||
tooltipSide = "right",
|
||||
tooltipSideOffset = 5,
|
||||
className = "",
|
||||
...rest
|
||||
}: TruncatedTextProps) {
|
||||
const [isTruncated, setIsTruncated] = useState(false);
|
||||
const visibleRef = useRef<HTMLSpanElement>(null);
|
||||
const hiddenRef = useRef<HTMLSpanElement>(null);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
function checkTruncation() {
|
||||
if (visibleRef.current && hiddenRef.current) {
|
||||
const visibleWidth = visibleRef.current.offsetWidth;
|
||||
const fullTextWidth = hiddenRef.current.offsetWidth;
|
||||
setIsTruncated(fullTextWidth > visibleWidth);
|
||||
}
|
||||
}
|
||||
|
||||
checkTruncation();
|
||||
window.addEventListener("resize", checkTruncation);
|
||||
return () => window.removeEventListener("resize", checkTruncation);
|
||||
}, [text]);
|
||||
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span
|
||||
ref={visibleRef}
|
||||
// Ensure the text can actually truncate via line-clamp or overflow
|
||||
className={`line-clamp-1 break-all flex-grow ${className}`}
|
||||
{...rest}
|
||||
>
|
||||
{text}
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
{/* Hide offscreen to measure full text width */}
|
||||
<span
|
||||
ref={hiddenRef}
|
||||
className="absolute left-[-9999px] whitespace-nowrap pointer-events-none"
|
||||
aria-hidden="true"
|
||||
>
|
||||
{text}
|
||||
</span>
|
||||
{isTruncated && (
|
||||
<TooltipContent
|
||||
side={tooltipSide}
|
||||
sideOffset={tooltipSideOffset}
|
||||
className={tooltipClassName}
|
||||
>
|
||||
<p className="text-xs max-w-[200px] whitespace-normal break-words">
|
||||
{text}
|
||||
</p>
|
||||
</TooltipContent>
|
||||
)}
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user