Skip to content

Commit eca75ea

Browse files
committed
feat: add empty state for server list when there are 0 servers
1 parent 9a04d30 commit eca75ea

File tree

3 files changed

+56
-6
lines changed

3 files changed

+56
-6
lines changed

src/app/catalog/components/__tests__/servers.test.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,9 @@ describe("Servers", () => {
111111
/>,
112112
);
113113

114+
expect(screen.getByText("No results found")).toBeVisible();
114115
expect(
115-
screen.getByText('No servers found matching "nonexistent"'),
116+
screen.getByText(/couldn't find any servers matching "nonexistent"/),
116117
).toBeVisible();
117118
});
118119
});
@@ -122,12 +123,23 @@ describe("Servers", () => {
122123
render(<Servers servers={[]} viewMode="grid" searchQuery="" />);
123124

124125
expect(screen.getByText("No servers available")).toBeVisible();
126+
expect(
127+
screen.getByText(/no MCP servers in the catalog yet/i),
128+
).toBeVisible();
125129
});
126130

127131
it("shows no servers message in list mode", () => {
128132
render(<Servers servers={[]} viewMode="list" searchQuery="" />);
129133

130134
expect(screen.getByText("No servers available")).toBeVisible();
131135
});
136+
137+
it("displays illustration in empty state", () => {
138+
const { container } = render(
139+
<Servers servers={[]} viewMode="grid" searchQuery="" />,
140+
);
141+
142+
expect(container.querySelector("svg")).toBeInTheDocument();
143+
});
132144
});
133145
});
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { ReactNode } from "react";
2+
import { IllustrationEmptyInbox } from "@/components/illustrations/illustration-empty-inbox";
3+
import { IllustrationNoSearchResults } from "@/components/illustrations/illustration-no-search-results";
4+
5+
interface EmptyStateProps {
6+
variant: "no-servers" | "no-results";
7+
searchQuery?: string;
8+
actions?: ReactNode;
9+
}
10+
11+
export function EmptyState({ variant, searchQuery, actions }: EmptyStateProps) {
12+
const isNoResults = variant === "no-results";
13+
14+
return (
15+
<div className="flex items-center justify-center py-20">
16+
<div className="flex flex-col items-center text-center gap-4 max-w-md">
17+
{isNoResults ? (
18+
<IllustrationNoSearchResults className="size-32" />
19+
) : (
20+
<IllustrationEmptyInbox className="size-32" />
21+
)}
22+
23+
<div className="space-y-2">
24+
<h2 className="text-xl font-semibold tracking-tight">
25+
{isNoResults ? "No results found" : "No servers available"}
26+
</h2>
27+
<p className="text-muted-foreground">
28+
{isNoResults
29+
? `We couldn't find any servers matching "${searchQuery}". Try adjusting your search.`
30+
: "There are no MCP servers in the catalog yet. Check back later."}
31+
</p>
32+
</div>
33+
34+
{actions && <div className="flex gap-2 mt-2">{actions}</div>}
35+
</div>
36+
</div>
37+
);
38+
}

src/app/catalog/components/servers.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useRouter } from "next/navigation";
44
import { useMemo } from "react";
55
import type { V0ServerJson } from "@/generated/types.gen";
6+
import { EmptyState } from "./empty-state";
67
import { ServerCard } from "./server-card";
78
import { ServersTable } from "./servers-table";
89

@@ -42,11 +43,10 @@ export function Servers({ servers, viewMode, searchQuery }: ServersProps) {
4243

4344
if (filteredServers.length === 0) {
4445
return (
45-
<div className="p-12 text-center">
46-
{searchQuery
47-
? `No servers found matching "${searchQuery}"`
48-
: "No servers available"}
49-
</div>
46+
<EmptyState
47+
variant={searchQuery ? "no-results" : "no-servers"}
48+
searchQuery={searchQuery}
49+
/>
5050
);
5151
}
5252

0 commit comments

Comments
 (0)