Skip to content

Commit 369acc0

Browse files
JonasBaclaude
andcommitted
fix(cmdk): Filter empty resource nodes from group children in search mode
The matched-child filter in search mode only checked scores but not isEmptyResourceNode, so an async group container with 0 results nested inside a group (e.g. "Reverse DSN lookup" under "Navigate") would pass the filter and appear as a clickable action when the group label matched the query. Apply the same isEmptyResourceNode guard to the per-child filter that browse mode already uses, and add a regression test for the case. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2e92f67 commit 369acc0

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

static/app/components/commandPalette/ui/commandPalette.spec.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,35 @@ describe('CommandPalette', () => {
701701
).not.toBeInTheDocument();
702702
});
703703

704+
it('is omitted from search mode when nested inside a group whose label matches the query', async () => {
705+
render(
706+
<CommandPaletteProvider>
707+
<CMDKAction display={{label: 'Navigate'}}>
708+
<CMDKAction display={{label: 'Async Resource'}} resource={emptyResource}>
709+
{data =>
710+
data.map((_, i) => (
711+
<CMDKAction key={i} to="/x/" display={{label: 'Result'}} />
712+
))
713+
}
714+
</CMDKAction>
715+
</CMDKAction>
716+
<CMDKAction display={{label: 'Other'}} onAction={jest.fn()} />
717+
<CommandPalette onAction={jest.fn()} />
718+
</CommandPaletteProvider>
719+
);
720+
721+
const input = await screen.findByRole('textbox', {name: 'Search commands'});
722+
await userEvent.type(input, 'navigate');
723+
724+
// Wait for search to take effect — 'Other' should be filtered out since it doesn't match
725+
await waitFor(() => {
726+
expect(screen.queryByRole('option', {name: 'Other'})).not.toBeInTheDocument();
727+
});
728+
expect(
729+
screen.queryByRole('option', {name: 'Async Resource'})
730+
).not.toBeInTheDocument();
731+
});
732+
704733
it('is omitted from search mode even when the label matches the query', async () => {
705734
render(
706735
<CommandPaletteProvider>

static/app/components/commandPalette/ui/commandPalette.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,9 @@ function flattenActions(
518518

519519
const flattened = collected.flatMap((item): CMDKFlatItem[] => {
520520
if (item.children.length > 0) {
521-
const matched = item.children.filter(c => scores.get(c.key)?.score.matched);
521+
const matched = item.children.filter(
522+
c => scores.get(c.key)?.score.matched && !isEmptyResourceNode(c)
523+
);
522524
if (!matched.length) return [];
523525
return [
524526
// Suffix the header key so a group used as both a section header and

0 commit comments

Comments
 (0)