Skip to content

Commit 96f60fb

Browse files
committed
Restore default tooltip styling for truncated titles
1 parent 3a985c1 commit 96f60fb

2 files changed

Lines changed: 65 additions & 9 deletions

File tree

components/PromptTreeItem.tsx

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import React, { useState, useRef, useEffect } from 'react';
1+
import React, { useState, useRef, useEffect, useLayoutEffect } from 'react';
22
// Fix: Correctly import the DocumentOrFolder type.
33
import type { DocumentOrFolder, DraggedNodeTransfer } from '../types';
44
import IconButton from './IconButton';
55
import { FileIcon, FolderIcon, FolderOpenIcon, TrashIcon, ChevronRightIcon, ChevronDownIcon, CopyIcon, ArrowUpIcon, ArrowDownIcon, CodeIcon, SaveIcon, LockClosedIcon, LockOpenIcon } from './Icons';
6+
import Tooltip from './Tooltip';
67

78
export interface DocumentNode extends DocumentOrFolder {
89
children: DocumentNode[];
@@ -139,10 +140,12 @@ const DocumentTreeItem: React.FC<DocumentTreeItemProps> = (props) => {
139140
const [dropPosition, setDropPosition] = useState<'before' | 'after' | 'inside' | null>(null);
140141
const [isHovered, setIsHovered] = useState(false);
141142
const [lockedRowHeight, setLockedRowHeight] = useState<number | null>(null);
143+
const [isTitleTruncated, setIsTitleTruncated] = useState(false);
142144

143145
const renameInputRef = useRef<HTMLInputElement>(null);
144146
const itemRef = useRef<HTMLLIElement>(null);
145147
const rowRef = useRef<HTMLDivElement>(null);
148+
const titleRef = useRef<HTMLSpanElement>(null);
146149

147150
const isSelected = selectedIds.has(node.id);
148151
const isFocused = focusedItemId === node.id;
@@ -190,6 +193,51 @@ const DocumentTreeItem: React.FC<DocumentTreeItemProps> = (props) => {
190193
}
191194
}, [isSelected, isRenaming]);
192195

196+
useLayoutEffect(() => {
197+
if (!isHovered || !areActionsVisible || isRenaming) {
198+
setIsTitleTruncated(false);
199+
return;
200+
}
201+
202+
const titleElement = titleRef.current;
203+
204+
if (!titleElement) {
205+
setIsTitleTruncated(false);
206+
return;
207+
}
208+
209+
const checkTruncation = () => {
210+
const truncated = titleElement.scrollWidth > titleElement.clientWidth + 0.5;
211+
setIsTitleTruncated(truncated);
212+
};
213+
214+
checkTruncation();
215+
216+
if (typeof window === 'undefined') {
217+
return;
218+
}
219+
220+
let frame: number | null = window.requestAnimationFrame(checkTruncation);
221+
222+
let resizeObserver: ResizeObserver | null = null;
223+
if (typeof ResizeObserver !== 'undefined') {
224+
resizeObserver = new ResizeObserver(checkTruncation);
225+
resizeObserver.observe(titleElement);
226+
}
227+
228+
window.addEventListener('resize', checkTruncation);
229+
230+
return () => {
231+
if (frame !== null) {
232+
window.cancelAnimationFrame(frame);
233+
}
234+
window.removeEventListener('resize', checkTruncation);
235+
if (resizeObserver) {
236+
resizeObserver.disconnect();
237+
}
238+
};
239+
}, [areActionsVisible, displayTitle, isHovered, isRenaming, searchTerm]);
240+
193241
const handleRenameStart = (e: React.MouseEvent) => {
194242
e.stopPropagation();
195243
setIsRenaming(true);
@@ -381,6 +429,7 @@ const DocumentTreeItem: React.FC<DocumentTreeItemProps> = (props) => {
381429
/>
382430
) : (
383431
<span
432+
ref={titleRef}
384433
className={`flex-1 px-1 ${
385434
areActionsVisible ? 'truncate' : 'whitespace-normal break-words'
386435
}`}
@@ -390,6 +439,20 @@ const DocumentTreeItem: React.FC<DocumentTreeItemProps> = (props) => {
390439
)}
391440
</div>
392441

442+
{isHovered && isTitleTruncated && titleRef.current && (
443+
<Tooltip
444+
targetRef={titleRef}
445+
content={(
446+
<span className="inline-flex max-w-xs whitespace-pre-wrap break-words text-left leading-snug gap-1">
447+
{emojiForNode && !isFolder && (
448+
<span aria-hidden="true">{emojiForNode}</span>
449+
)}
450+
<span>{highlightMatches(displayTitle, searchTerm)}</span>
451+
</span>
452+
)}
453+
/>
454+
)}
455+
393456
{!isRenaming && (
394457
<div
395458
className={`transition-opacity flex items-center ${

components/StatusBar.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React from 'react';
22
import Tooltip from './Tooltip';
3-
import Hint from './Hint';
43
import type { LLMStatus, DiscoveredLLMModel, DiscoveredLLMService, PreviewMetadata } from '../types';
54
import { DatabaseIcon, ChevronDownIcon, MinusIcon, PlusIcon, RefreshIcon } from './Icons';
65

@@ -54,8 +53,6 @@ const statusConfig: Record<LLMStatus, { text: string; color: string; tooltip: st
5453
},
5554
};
5655

57-
const zoomButtonTooltipClass = '!bg-transparent !shadow-none !p-0 text-inherit';
58-
5956
interface ZoomButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
6057
hint: string;
6158
icon: React.ReactNode;
@@ -98,11 +95,7 @@ const ZoomButton: React.FC<ZoomButtonProps> = ({ hint, icon, className = '', dis
9895
</button>
9996
</span>
10097
{hasHint && showTooltip && wrapperRef.current && (
101-
<Tooltip
102-
targetRef={wrapperRef}
103-
content={<Hint role="note">{hint}</Hint>}
104-
className={zoomButtonTooltipClass}
105-
/>
98+
<Tooltip targetRef={wrapperRef} content={hint} />
10699
)}
107100
</>
108101
);

0 commit comments

Comments
 (0)