From 100130a070de68c4e43e581dd543fdeba817225b Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Tue, 5 May 2026 15:39:29 -0700 Subject: [PATCH] feat(new-workspace): auto-highlight matching source for #NNN, GH URLs, Linear IDs When the typed value is unambiguously a source reference, snap the autocomplete highlight onto the matching source row once it appears instead of leaving it on the typed-text fallback. Enter then picks the intended source. Recognized patterns: - GitHub shorthand: #1234 - GitHub URL: https://github.com///issues/123 or /pull/123 - Linear identifier: STA-123 (case-insensitive [A-Z][A-Z0-9_]*-\d+) Stale-results behavior is unchanged: while debouncedQuery hasn't caught up to value, the typed-text row stays highlighted (Smart/Branches) or the highlight is cleared (GitHub/Linear) regardless of intent. Co-authored-by: Orca --- .../new-workspace/SmartWorkspaceNameField.tsx | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx b/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx index fbc6fc9cdb9..4d6087416a5 100644 --- a/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx +++ b/src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx @@ -465,6 +465,26 @@ export default function SmartWorkspaceNameField({ // entirely; the input's Enter handler falls through to onPlainEnter. const isQueryStale = value.trim().length > 0 && debouncedQuery.trim() !== value.trim() + // Why: when the typed value is unambiguously a source reference — a + // GitHub issue/PR shorthand ("#1234"), a github.com issue/pull URL, or a + // Linear identifier ("STA-123") — the user is clearly looking up that + // specific source rather than naming a workspace. Once a matching row + // appears in the results, snap the highlight onto it so Enter picks it + // instead of the typed-text fallback. + const sourceIntent = useMemo<'github' | 'linear' | null>(() => { + const trimmed = value.trim() + if (!trimmed) { + return null + } + if (/^#\d+$/.test(trimmed) || parseGitHubIssueOrPRLink(trimmed) !== null) { + return 'github' + } + if (/^[A-Za-z][A-Za-z0-9_]*-\d+$/.test(trimmed)) { + return 'linear' + } + return null + }, [value]) + useEffect(() => { if (rows.length === 0) { return @@ -478,10 +498,23 @@ export default function SmartWorkspaceNameField({ setCommandValue(typedTextRow ? typedTextRow.value : '') return } + if (sourceIntent === 'github') { + const githubRow = rows.find((row) => row.kind === 'github') + if (githubRow) { + setCommandValue(githubRow.value) + return + } + } else if (sourceIntent === 'linear') { + const linearRow = rows.find((row) => row.kind === 'linear') + if (linearRow) { + setCommandValue(linearRow.value) + return + } + } setCommandValue((current) => rows.some((row) => row.value === current) ? current : rows[0].value ) - }, [isQueryStale, rows]) + }, [isQueryStale, rows, sourceIntent]) const loading = githubLoading || branchesLoading || linearLoading const ActiveInputIcon = mode === 'text' ? CaseSensitive : loading ? LoaderCircle : Search