Compare commits

...

1 Commits

Author SHA1 Message Date
Jiayuan Zhang
557ac45e93 refactor(search): collapse cmd+k empty-state commands to primary action
Previously every registered Command (New Issue, New Project, three theme
switches, plus contextual Copy actions on issue pages) surfaced on empty
query, leaving only 3–5 rows for Recent in a 400px panel. Low-frequency
commands (theme, copy, New Project) are now revealed by typing, matching
the progressive-disclosure pattern already used for Pages and Switch
Workspace. Refs MUL-991.
2026-04-17 08:59:06 +08:00
2 changed files with 11 additions and 8 deletions

View File

@@ -161,19 +161,21 @@ describe("SearchCommand", () => {
expect(screen.queryByPlaceholderText("Type a command or search...")).not.toBeInTheDocument();
});
it("shows Commands by default but hides Pages and Switch Workspace until query", () => {
it("shows only New Issue by default and hides Pages / Switch Workspace / low-frequency commands until query", () => {
render(<SearchCommand />);
expect(screen.queryByText("Pages")).not.toBeInTheDocument();
expect(screen.queryByText("Switch Workspace")).not.toBeInTheDocument();
// Commands surface by default for discoverability.
// Only the primary creation action surfaces on empty query; everything
// else (theme, copy, New Project) must be revealed by typing.
expect(screen.getByText("Commands")).toBeInTheDocument();
expect(
screen.getByText((_, el) => el?.textContent === "New Issue" && el?.tagName === "SPAN"),
).toBeInTheDocument();
expect(
screen.getByText((_, el) => el?.textContent === "New Project" && el?.tagName === "SPAN"),
).toBeInTheDocument();
expect(screen.queryByText("New Project")).not.toBeInTheDocument();
expect(screen.queryByText("Switch to Light Theme")).not.toBeInTheDocument();
expect(screen.queryByText("Switch to Dark Theme")).not.toBeInTheDocument();
expect(screen.queryByText("Use System Theme")).not.toBeInTheDocument();
});
it("filters navigation pages by query", async () => {

View File

@@ -281,9 +281,10 @@ export function SearchCommand() {
const filteredCommands = useMemo(() => {
const q = query.trim().toLowerCase();
// No query: surface the whole Commands list so users can discover what's
// available without having to guess keywords (Linear/Raycast pattern).
if (!q) return commands;
// No query: only surface the primary creation action. Other commands
// (theme switches, copy actions, New Project) are revealed as the user
// types, leaving the empty-state space to Recent.
if (!q) return commands.filter((c) => c.key === "new-issue");
return commands.filter(
(c) =>
c.label.toLowerCase().includes(q) ||