Repository navigation
🎃 Add a shared EmptyState component and use it for the "No … yet" screens #1001
Description
Part of the October Challenge #997.
Why
Every list page has its own "nothing here yet" block, and they have drifted apart. The Connectors page has a dashed card with an icon, a title, two lines of text and three buttons (connectors/page.tsx:389-421). MCP Servers uses a Card with a tinted icon and one button (mcp-server/page.tsx:170-176). The Audit Log, AI Skills and Knowledge Graph pages use centred text in different sizes and colours, and Roles and the connector's tool list use a single grey line. These are the first screens a new user sees, so they should look like one product and always say what to do next. A shared component also makes the next page cheaper to build.
Self-hosted vs Cloud
- Self-hosted: same in Community and Business. Frontend only: no API change, no
ee/code. - Cloud (
DEPLOYMENT_MODE=cloud): same. Some empty states depend on the role today: the AI Skills page tells non-admins to ask an admin (knowledge-graph/skills/page.tsx:235-252) and the Knowledge Graph text differs for admins (knowledge-graph/page.tsx:322-328). Keep that logic in the page; the component only renders what it is given. - Who can use it: everyone. The component shows no data, and action buttons keep the role checks their pages already have.
What to build
- Component:
packages/frontend/src/components/ui/empty-state.tsxexportingEmptyStatewith propsicon?: ReactNode,title: string,description?: ReactNode,actions?: ReactNode,variant?: 'page' | 'inline'(defaultpage),headingLevel?: 2 | 3,className?: string.page: the Connectors look (dashed--border-strongborder, 14px radius, icon tile on--brand-tint, centred,py-16).inline: compact centred text for an empty list inside a card (no border, smaller padding).- The title is a real heading so screen readers can jump to it. Actions wrap on phones; the Connectors buttons once spilled off-screen at 390 px (see the test below).
- Use the existing CSS variables and
cn()fromlib/utils, likecomponents/ui/card.tsx.
- Migrate these screens, keeping their wording:
app/connectors/page.tsx:389-421: "No connectors yet" (page).app/mcp-server/page.tsx:170-176: "No MCP servers configured yet." (page), and:177-180"No MCP servers match your search." (inline).app/logs/page.tsx:290-313: end of log, "No invocations match these filters." with Clear filters, and "No tool calls recorded yet." (inline, inside the table card).app/knowledge-graph/skills/page.tsx:235-252: "No skills yet".app/knowledge-graph/page.tsx:322-328: "No graph yet".app/settings/roles/page.tsx:295-298andapp/admin/roles/page.tsx:262-265: "No custom roles yet".app/connectors/[id]/page.tsx:1675-1678: "No tools configured…" andapp/mcp-server/[id]/page.tsx:973-977: "No tools available…" (inline).app/connectors/store/page.tsx:474-495: "No adapters available yet." and the "Nothing matches" variant.
- Add an action only where the page already has it (for example "Create your first MCP Server"). Do not invent new flows or rewrite copy.
Where to look
- The screens listed above.
packages/frontend/src/components/ui/card.tsx: the surface primitive and its styling conventions.packages/frontend/src/components/ui/button.tsx:ButtonandbuttonVariantsused by the actions.packages/frontend/tests/e2e/mobile.spec.ts:283-306: "empty connector list keeps its buttons on screen" finds the card withancestor::div[contains(@class,"border-dashed")]. Keep theborder-dashedclass on thepagevariant, or switch the selector to adata-testidin the same PR.
Acceptance criteria
- Every screen listed above uses
EmptyState, and the visible copy is unchanged (the diff moves markup, not text). - All existing Playwright tests pass,
mobile.spec.tsincluded (cd packages/frontend && npm run test:e2e). - New Playwright test: with
/api/connectorsand/api/mcp-serversstubbed to[], both empty states render title, description and actions, and at 390 px width no action overflows the viewport. - Light and dark theme screenshots of three migrated screens in the PR.
-
npm run lintandnpx tsc --noEmit -p tsconfig.jsonpass inpackages/frontend.
Out of scope
- New copy or illustrations.
- Loading skeletons and error states (a separate component, follow-up).
- The onboarding flow under
app/welcome.
Size
M (1–2 days)
How to claim
Comment "I'd like to work on this" and we'll assign you. Rules in #997.
Activity
Asymtode712 commentedon Oct 10, 2026
I'd like to work on this
helpcodeai commentedon Oct 12, 2026
@Asymtode712 sorry for the wait, it's yours, assigned. The issue lists the screens to convert; if you find more "No ... yet" screens than the ones listed, leave the extra ones for a second PR so the first stays easy to review.