diff --git a/src/renderer/src/components/sidebar/AddRepoStartSteps.test.tsx b/src/renderer/src/components/sidebar/AddRepoStartSteps.test.tsx
index 9eadd3a5dad..ace7b22bc85 100644
--- a/src/renderer/src/components/sidebar/AddRepoStartSteps.test.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoStartSteps.test.tsx
@@ -51,7 +51,17 @@ function renderServerPathStartStep(runtimeEnvironmentId: string | null): string
)
}
-async function renderLocalStartStepDom(isSshLikely: boolean): Promise<{
+type LocalStartStepDomOptions = {
+ isAdding?: boolean
+ addProjectBusyLabel?: string | null
+ nestedScanInProgress?: boolean
+ nestedScanId?: string | null
+}
+
+async function renderLocalStartStepDom(
+ isSshLikely: boolean,
+ options: LocalStartStepDomOptions = {}
+): Promise<{
container: HTMLDivElement
root: Root
}> {
@@ -61,19 +71,21 @@ async function renderLocalStartStepDom(isSshLikely: boolean): Promise<{
await act(async () => {
root.render(
-
+
+
+
)
})
@@ -210,6 +222,62 @@ describe('AddRepoLocalStartStep', () => {
})
})
+ it('clears the ⏎ selection when focus leaves the action list', async () => {
+ const { container, root } = await renderLocalStartStepDom(false)
+ const outsideButton = document.createElement('button')
+ document.body.appendChild(outsideButton)
+
+ await act(async () => {
+ outsideButton.focus()
+ })
+
+ expect(document.activeElement).toBe(outsideButton)
+ expect(findButton(container, 'Browse folder').textContent).not.toContain('⏎')
+ expect(findButton(container, 'Clone from URL').textContent).not.toContain('⏎')
+
+ await act(async () => {
+ root.unmount()
+ })
+ })
+
+ it('does not show an ⏎ selection while add actions are busy', async () => {
+ const { container, root } = await renderLocalStartStepDom(false, {
+ isAdding: true,
+ addProjectBusyLabel: 'Scanning repositories',
+ nestedScanInProgress: true,
+ nestedScanId: 'scan-1'
+ })
+ const stopScanButton = container.querySelector(
+ 'button[aria-label="Stop scan"]'
+ )
+
+ await act(async () => {
+ stopScanButton?.focus()
+ })
+
+ expect(document.activeElement).toBe(stopScanButton)
+ expect(findButton(container, 'Browse folder').textContent).not.toContain('⏎')
+ expect(findButton(container, 'Clone from URL').textContent).not.toContain('⏎')
+
+ await act(async () => {
+ root.unmount()
+ })
+ })
+
+ it('hides the visual ⏎ chip from assistive technology', async () => {
+ const { container, root } = await renderLocalStartStepDom(false)
+ const browseButton = findButton(container, 'Browse folder')
+ const enterChip = Array.from(browseButton.querySelectorAll('[aria-hidden="true"]')).find(
+ (entry) => entry.textContent?.includes('⏎')
+ )
+
+ expect(enterChip).toBeTruthy()
+
+ await act(async () => {
+ root.unmount()
+ })
+ })
+
it('roves selection down the action list with the ArrowDown key', async () => {
const { container, root } = await renderLocalStartStepDom(false)
diff --git a/src/renderer/src/components/sidebar/AddRepoStartSteps.tsx b/src/renderer/src/components/sidebar/AddRepoStartSteps.tsx
index ea41778251e..8fc9d45953d 100644
--- a/src/renderer/src/components/sidebar/AddRepoStartSteps.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoStartSteps.tsx
@@ -99,9 +99,13 @@ export function AddRepoLocalStartStep({
// The white fill + ⏎ chip is a roving selection indicator, not a fixed "primary" badge:
// it follows keyboard focus so Enter always activates the highlighted action. Browse is
// autofocused on open, so it starts selected; Tab and ↑/↓ move the highlight.
- const [selectedKind, setSelectedKind] = useState(primaryAction.kind)
+ const [selectedKind, setSelectedKind] = useState(primaryAction.kind)
useEffect(() => {
+ if (isAdding) {
+ setSelectedKind(null)
+ return
+ }
if (!isAdding) {
browseActionRef.current?.focus()
}
@@ -125,6 +129,16 @@ export function AddRepoLocalStartStep({
buttons[nextIndex]?.focus()
}
+ const handleActionsBlur = (event: React.FocusEvent): void => {
+ if (!(event.relatedTarget instanceof HTMLButtonElement)) {
+ setSelectedKind(null)
+ return
+ }
+ if (!event.relatedTarget.matches('button[data-add-repo-action]')) {
+ setSelectedKind(null)
+ }
+ }
+
return (
<>
@@ -141,7 +155,12 @@ export function AddRepoLocalStartStep({
) : null}
-
+
(
-
+
+
+
)
const AddRepoPrimaryStartAction = ({