Skip to content

Commit 7d87660

Browse files
fix(chat): address fifth round of PR review feedback
- Re-add inputValue to SlashCommandPreviewPopover anchor effect deps so the virtual anchor re-measures when typing shifts the chip's position - Clamp slash menu selectedIndex in onUpdate when filtered results shrink, matching the existing mention-menu clamping behavior - Return true (consume event) when Enter/Tab closes empty mention popup so the event does not propagate to insert a paragraph break - Mirror focus-on-dismiss effect in v2 workspace ChatInputFooter so the editor regains focus after the question overlay unmounts - Fix trailing-slash paths rendering empty label in ClickableFilePath by using || instead of ?? for the basename fallback
1 parent 96c31b7 commit 7d87660

4 files changed

Lines changed: 24 additions & 5 deletions

File tree

apps/desktop/src/renderer/components/Chat/ChatInterface/components/TiptapPromptEditor/SlashCommandPreviewPopover.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export function SlashCommandPreviewPopover({
3434
const anchorRef = useRef<HTMLDivElement>(null);
3535

3636
// Position the virtual anchor over the slash-command chip in the editor.
37+
// biome-ignore lint/correctness/useExhaustiveDependencies: inputValue re-measures anchor when typing shifts the chip's position
3738
useLayoutEffect(() => {
3839
const el = anchorRef.current;
3940
if (!el) return;
@@ -52,7 +53,7 @@ export function SlashCommandPreviewPopover({
5253
el.style.top = `${rect.top}px`;
5354
el.style.width = `${rect.width}px`;
5455
el.style.height = `${rect.height}px`;
55-
}, [editor]);
56+
}, [editor, inputValue]);
5657

5758
const slashPreviewInput = normalizeSlashPreviewInput(inputValue);
5859
const parsedInput = useMemo(() => parseSlashInput(inputValue), [inputValue]);

apps/desktop/src/renderer/components/Chat/ChatInterface/components/TiptapPromptEditor/TiptapPromptEditor.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,10 @@ export function TiptapPromptEditor({
297297
...prev,
298298
commands: props.items,
299299
tiptapCommand: props.command,
300+
selectedIndex: Math.min(
301+
prev.selectedIndex,
302+
Math.max(0, props.items.length - 1),
303+
),
300304
}
301305
: null,
302306
);
@@ -477,9 +481,9 @@ export function TiptapPromptEditor({
477481
mention.tiptapCommand({ path: file.relativePath });
478482
return true;
479483
}
480-
// No results — close the popup then let Enter fall through to submit
484+
// No results — close the popup and consume the event
481485
setMentionState(null);
482-
return false;
486+
return true;
483487
}
484488
return false;
485489
},

apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/WorkspaceChatInterface/components/ChatInputFooter/ChatInputFooter.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import {
33
PromptInputAttachment,
44
PromptInputAttachments,
55
type PromptInputMessage,
6+
usePromptInputController,
67
} from "@superset/ui/ai-elements/prompt-input";
78
import type { ThinkingLevel } from "@superset/ui/ai-elements/thinking-toggle";
89
import type { ChatStatus, FileUIPart } from "ai";
910
import type React from "react";
1011
import type { ReactNode } from "react";
11-
import { useCallback, useRef, useState } from "react";
12+
import { useCallback, useEffect, useRef, useState } from "react";
1213
import { QuestionInputOverlay } from "renderer/components/Chat/ChatInterface/components/ChatInputFooter/components/QuestionInputOverlay";
1314
import { IssueLinkCommand } from "renderer/components/Chat/ChatInterface/components/IssueLinkCommand";
1415
import { TiptapPromptEditor } from "renderer/components/Chat/ChatInterface/components/TiptapPromptEditor";
@@ -94,6 +95,19 @@ export function ChatInputFooter({
9495
onQuestionCancel,
9596
}: ChatInputFooterProps) {
9697
useFocusPromptOnPane(isFocused);
98+
99+
// Re-focus the editor when the question overlay dismisses.
100+
const { textInput } = usePromptInputController();
101+
const prevPendingQuestionRef = useRef(pendingQuestion);
102+
useEffect(() => {
103+
const prev = prevPendingQuestionRef.current;
104+
prevPendingQuestionRef.current = pendingQuestion;
105+
if (prev != null && pendingQuestion == null) {
106+
const id = requestAnimationFrame(() => textInput.focus());
107+
return () => cancelAnimationFrame(id);
108+
}
109+
}, [pendingQuestion, textInput]);
110+
97111
const [issueLinkOpen, setIssueLinkOpen] = useState(false);
98112
const [linkedIssues, setLinkedIssues] = useState<LinkedIssue[]>([]);
99113
const inputRootRef = useRef<HTMLDivElement>(null);

packages/ui/src/components/ai-elements/clickable-file-path.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function ClickableFilePath({
2424
className,
2525
}: ClickableFilePathProps) {
2626
const label =
27-
display ?? (path.includes("/") ? (path.split("/").pop() ?? path) : path);
27+
display ?? (path.includes("/") ? path.split("/").pop() || path : path);
2828

2929
if (!onOpen) {
3030
return <span className={className}>{label}</span>;

0 commit comments

Comments
 (0)