Skip to content

Commit e45d033

Browse files
committed
fix: clear the pointer highlight when returning to the scope list
Cancelling a delete, finishing a delete, or backing out of the create view remounts the cmdk list with the first item auto-highlighted while the hover flag from the previous view survived, so a stray Enter in the empty search selected Base. Every path back to the list now clears the flag through a shared returnToList handler.
1 parent 284dada commit e45d033

2 files changed

Lines changed: 41 additions & 6 deletions

File tree

src/components/configuration/ScopeSelector.test.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,16 @@ async function renderListView() {
9696
return handlers;
9797
}
9898

99-
async function openDeleteConfirmation(user: ReturnType<typeof userEvent.setup>) {
100-
const handlers = await renderListView();
99+
async function openDeleteConfirmationFromList(user: ReturnType<typeof userEvent.setup>) {
101100
const deleteButton = screen.getByRole('button', { name: 'com_scope_delete' });
102101
deleteButton.focus();
103102
await user.keyboard('{Enter}');
104103
await screen.findByText('com_scope_delete_confirm');
104+
}
105+
106+
async function openDeleteConfirmation(user: ReturnType<typeof userEvent.setup>) {
107+
const handlers = await renderListView();
108+
await openDeleteConfirmationFromList(user);
105109
return handlers;
106110
}
107111

@@ -186,6 +190,21 @@ describe('ScopeSelector Enter key handling', () => {
186190
expect(onOpenChange).not.toHaveBeenCalled();
187191
});
188192

193+
it('does not select the auto-highlighted Base scope with Enter after cancelling a delete reached by hovering', async () => {
194+
const user = userEvent.setup();
195+
const { onSelect, onOpenChange } = await renderListView();
196+
await user.hover(screen.getByText('Engineering'));
197+
await openDeleteConfirmationFromList(user);
198+
const cancelButton = screen.getByRole('button', { name: 'com_ui_cancel' });
199+
cancelButton.focus();
200+
await user.keyboard('{Enter}');
201+
const searchInput = await screen.findByRole('combobox');
202+
searchInput.focus();
203+
await user.keyboard('{Enter}');
204+
expect(onSelect).not.toHaveBeenCalled();
205+
expect(onOpenChange).not.toHaveBeenCalled();
206+
});
207+
189208
it('selects a scope with Enter after hovering it with the mouse', async () => {
190209
const user = userEvent.setup();
191210
const { onSelect, onOpenChange } = await renderListView();

src/components/configuration/ScopeSelector.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ export function ScopeSelector({
100100
highlightedRef.current = false;
101101
}, []);
102102

103+
/** Returning to the list remounts the cmdk view with the first item auto-highlighted, so a highlight carried over from the previous view must not let Enter select it. */
104+
const returnToList = useCallback(() => {
105+
setShowCreate(false);
106+
setDeleteTarget(null);
107+
highlightedRef.current = false;
108+
}, []);
109+
103110
const close = useCallback(() => {
104111
onOpenChange(false);
105112
resetState();
@@ -208,13 +215,22 @@ export function ScopeSelector({
208215
) {
209216
onSelect({ type: 'BASE' });
210217
}
211-
setDeleteTarget(null);
218+
returnToList();
212219
setDeleting(false);
213220
} catch (err) {
214221
setDeleting(false);
215222
onError?.(err instanceof Error ? err.message : localize('com_scope_delete_error'));
216223
}
217-
}, [deleteTarget, deleting, queryClient, currentSelection, onSelect, onError, localize]);
224+
}, [
225+
deleteTarget,
226+
deleting,
227+
queryClient,
228+
currentSelection,
229+
onSelect,
230+
onError,
231+
localize,
232+
returnToList,
233+
]);
218234

219235
const roleScopes = useMemo(
220236
() => scopes.filter((s) => s.principalType === PrincipalType.ROLE),
@@ -255,7 +271,7 @@ export function ScopeSelector({
255271
<Button
256272
type="secondary"
257273
label={localize('com_ui_cancel')}
258-
onClick={() => setDeleteTarget(null)}
274+
onClick={returnToList}
259275
disabled={deleting}
260276
/>
261277
<Button
@@ -288,7 +304,7 @@ export function ScopeSelector({
288304
<div className="flex items-center gap-2 border-b border-(--cui-color-stroke-default) pb-2">
289305
<button
290306
type="button"
291-
onClick={() => setShowCreate(false)}
307+
onClick={returnToList}
292308
aria-label={localize('com_ui_back')}
293309
className="flex cursor-pointer items-center text-(--cui-color-text-muted) hover:text-(--cui-color-text-default)"
294310
>

0 commit comments

Comments
 (0)