diff --git a/apps/app/src/components/settings/KeyboardSettingsSection.test.tsx b/apps/app/src/components/settings/KeyboardSettingsSection.test.tsx
index aa5fe5f547c..18f42564d07 100644
--- a/apps/app/src/components/settings/KeyboardSettingsSection.test.tsx
+++ b/apps/app/src/components/settings/KeyboardSettingsSection.test.tsx
@@ -200,6 +200,110 @@ afterEach(() => {
});
describe("KeyboardSettingsSection", () => {
+ it("ranks visible label matches ahead of description matches across groups", () => {
+ render();
+
+ fireEvent.change(
+ screen.getByRole("textbox", { name: "Search keyboard shortcuts" }),
+ {
+ target: { value: " SiDeBaR " },
+ },
+ );
+
+ expect(
+ screen
+ .getAllByRole("button", { name: /^Record shortcut for / })[0]
+ ?.getAttribute("aria-label"),
+ ).toMatch(/^Record shortcut for Toggle sidebar,/);
+ });
+
+ it("ranks exact labels, label prefixes, label substrings, IDs, and descriptions in order", () => {
+ setPluginSlotRegistrations(
+ "test-shortcuts",
+ collectPluginAppRegistrations({
+ __bbPluginApp: true,
+ setup(app) {
+ for (const [id, title] of [
+ ["sidebar-open", "Open navigation"],
+ ["tools", "Sidebar tools"],
+ ["exact", "Sidebar"],
+ ["settings", "Sidebar settings"],
+ ]) {
+ app.commands.register({ id, title, run() {} });
+ }
+ },
+ }),
+ );
+ render();
+
+ fireEvent.change(
+ screen.getByRole("textbox", { name: "Search keyboard shortcuts" }),
+ {
+ target: { value: "sidebar" },
+ },
+ );
+
+ const labels = screen
+ .getAllByRole("button", { name: /^Record shortcut for / })
+ .map(
+ (recorder) =>
+ recorder.getAttribute("aria-label")?.split(", current shortcut")[0],
+ );
+ expect(labels.slice(0, 6)).toEqual([
+ "Record shortcut for Sidebar",
+ "Record shortcut for Sidebar tools",
+ "Record shortcut for Sidebar settings",
+ "Record shortcut for Toggle sidebar",
+ "Record shortcut for Open navigation",
+ "Record shortcut for Previous thread",
+ ]);
+ });
+
+ it("restores category and command order when the search is cleared", () => {
+ render();
+ const originalLabels = screen
+ .getAllByRole("button", { name: /^Record shortcut for / })
+ .map((recorder) => recorder.getAttribute("aria-label"));
+ const originalHeadings = screen
+ .getAllByRole("heading", { level: 3 })
+ .map((heading) => heading.textContent);
+ const search = screen.getByRole("textbox", {
+ name: "Search keyboard shortcuts",
+ });
+
+ fireEvent.change(search, { target: { value: "sidebar" } });
+ fireEvent.change(search, { target: { value: " " } });
+
+ expect(
+ screen
+ .getAllByRole("button", { name: /^Record shortcut for / })
+ .map((recorder) => recorder.getAttribute("aria-label")),
+ ).toEqual(originalLabels);
+ expect(
+ screen
+ .getAllByRole("heading", { level: 3 })
+ .map((heading) => heading.textContent),
+ ).toEqual(originalHeadings);
+ });
+
+ it("shows the empty state when no shortcut matches", () => {
+ render();
+
+ fireEvent.change(
+ screen.getByRole("textbox", { name: "Search keyboard shortcuts" }),
+ {
+ target: { value: "nonexistent-shortcut" },
+ },
+ );
+
+ expect(
+ screen.getByText("No shortcuts match “nonexistent-shortcut”."),
+ ).toBeDefined();
+ expect(
+ screen.queryAllByRole("button", { name: /^Record shortcut for / }),
+ ).toHaveLength(0);
+ });
+
it("lists commands without defaults and persists bindings under stable plugin IDs", () => {
setPluginSlotRegistrations(
"test-shortcuts",
diff --git a/apps/app/src/components/settings/KeyboardSettingsSection.tsx b/apps/app/src/components/settings/KeyboardSettingsSection.tsx
index 377a219593f..ad3449daab0 100644
--- a/apps/app/src/components/settings/KeyboardSettingsSection.tsx
+++ b/apps/app/src/components/settings/KeyboardSettingsSection.tsx
@@ -552,15 +552,24 @@ export function KeyboardSettingsSection() {
const visibleGroups = useMemo(() => {
const query = search.trim().toLowerCase();
if (query.length === 0) return commandGroups;
- return commandGroups.flatMap((group) => {
- const commands = group.commands.filter(
- (metadata) =>
- metadata.label.toLowerCase().includes(query) ||
- metadata.description.toLowerCase().includes(query) ||
- metadata.command.toLowerCase().includes(query),
- );
- return commands.length === 0 ? [] : [{ ...group, commands }];
- });
+ const commands = commandGroups
+ .flatMap((group) =>
+ group.commands.map((metadata) => {
+ const label = metadata.label.toLowerCase();
+ const rank = [
+ label === query,
+ label.startsWith(query),
+ label.includes(query),
+ metadata.command.toLowerCase().includes(query),
+ metadata.description.toLowerCase().includes(query),
+ ].findIndex(Boolean);
+ return { metadata, rank };
+ }),
+ )
+ .filter(({ rank }) => rank !== -1)
+ .sort((left, right) => left.rank - right.rank)
+ .map(({ metadata }) => metadata);
+ return commands.length === 0 ? [] : [{ label: "Search results", commands }];
}, [commandGroups, search]);
const latestSettingsRef = useRef({