feat(ui): unify comment assignee selector with icons and fix click flash
Add renderTriggerValue/renderOption to the comment thread's assignee selector so it shows agent icons, matching the new issue dialog. Fix the InlineEntitySelector flash on click by only auto-opening on keyboard focus (not pointer-triggered focus). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import { InlineEntitySelector, type InlineEntityOption } from "./InlineEntitySel
|
|||||||
import { MarkdownBody } from "./MarkdownBody";
|
import { MarkdownBody } from "./MarkdownBody";
|
||||||
import { MarkdownEditor, type MarkdownEditorRef, type MentionOption } from "./MarkdownEditor";
|
import { MarkdownEditor, type MarkdownEditorRef, type MentionOption } from "./MarkdownEditor";
|
||||||
import { StatusBadge } from "./StatusBadge";
|
import { StatusBadge } from "./StatusBadge";
|
||||||
|
import { AgentIcon } from "./AgentIconPicker";
|
||||||
import { formatDateTime } from "../lib/utils";
|
import { formatDateTime } from "../lib/utils";
|
||||||
|
|
||||||
interface CommentWithRunMeta extends IssueComment {
|
interface CommentWithRunMeta extends IssueComment {
|
||||||
@@ -385,6 +386,32 @@ export function CommentThread({
|
|||||||
emptyMessage="No assignees found."
|
emptyMessage="No assignees found."
|
||||||
onChange={setReassignTarget}
|
onChange={setReassignTarget}
|
||||||
className="text-xs h-8"
|
className="text-xs h-8"
|
||||||
|
renderTriggerValue={(option) => {
|
||||||
|
if (!option) return <span className="text-muted-foreground">Assignee</span>;
|
||||||
|
const agentId = option.id.startsWith("agent:") ? option.id.slice("agent:".length) : null;
|
||||||
|
const agent = agentId ? agentMap?.get(agentId) : null;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{agent ? (
|
||||||
|
<AgentIcon icon={agent.icon} className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
||||||
|
) : null}
|
||||||
|
<span className="truncate">{option.label}</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
renderOption={(option) => {
|
||||||
|
if (!option.id) return <span className="truncate">{option.label}</span>;
|
||||||
|
const agentId = option.id.startsWith("agent:") ? option.id.slice("agent:".length) : null;
|
||||||
|
const agent = agentId ? agentMap?.get(agentId) : null;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{agent ? (
|
||||||
|
<AgentIcon icon={agent.icon} className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
||||||
|
) : null}
|
||||||
|
<span className="truncate">{option.label}</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Button size="sm" disabled={!canSubmit} onClick={handleSubmit}>
|
<Button size="sm" disabled={!canSubmit} onClick={handleSubmit}>
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export const InlineEntitySelector = forwardRef<HTMLButtonElement, InlineEntitySe
|
|||||||
const [highlightedIndex, setHighlightedIndex] = useState(0);
|
const [highlightedIndex, setHighlightedIndex] = useState(0);
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const shouldPreventCloseAutoFocusRef = useRef(false);
|
const shouldPreventCloseAutoFocusRef = useRef(false);
|
||||||
|
const isPointerDownRef = useRef(false);
|
||||||
|
|
||||||
const allOptions = useMemo<InlineEntityOption[]>(
|
const allOptions = useMemo<InlineEntityOption[]>(
|
||||||
() => [{ id: "", label: noneLabel, searchText: noneLabel }, ...options],
|
() => [{ id: "", label: noneLabel, searchText: noneLabel }, ...options],
|
||||||
@@ -97,7 +98,11 @@ export const InlineEntitySelector = forwardRef<HTMLButtonElement, InlineEntitySe
|
|||||||
"inline-flex min-w-0 items-center gap-1 rounded-md border border-border bg-muted/40 px-2 py-1 text-sm font-medium text-foreground transition-colors hover:bg-accent/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
"inline-flex min-w-0 items-center gap-1 rounded-md border border-border bg-muted/40 px-2 py-1 text-sm font-medium text-foreground transition-colors hover:bg-accent/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
onFocus={() => setOpen(true)}
|
onPointerDown={() => { isPointerDownRef.current = true; }}
|
||||||
|
onFocus={() => {
|
||||||
|
if (!isPointerDownRef.current) setOpen(true);
|
||||||
|
isPointerDownRef.current = false;
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{renderTriggerValue
|
{renderTriggerValue
|
||||||
? renderTriggerValue(currentOption)
|
? renderTriggerValue(currentOption)
|
||||||
|
|||||||
Reference in New Issue
Block a user