diff --git a/changes/44326-empty-states b/changes/44326-empty-states new file mode 100644 index 0000000000..eb0fa0a62f --- /dev/null +++ b/changes/44326-empty-states @@ -0,0 +1,3 @@ +- UI table controls stay visible when empty. On Hosts, Reports, Policies, and Software pages, search bars, filters, dropdowns, remain visible but disabled when empty — avoids layout shift when the first item is added. Item count remains visible. +- UI has action-oriented empty state copy. Headers describe current state ("No hosts", "No policies for this fleet") instead of prompting action. Body text explains what to expect. CTA buttons are explicit ("Add policy", "Schedule a report") and permission gated. +- UI shows consistent page descriptions and learn more links (added to Settings. Fleets, Ticket destinations, Certificates, and Identity provider pages). diff --git a/frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx b/frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx index 9be8d1ffb7..3653ae90d8 100644 --- a/frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx +++ b/frontend/pages/ManageControlsPage/Variables/Variables.tests.tsx @@ -64,9 +64,11 @@ describe("Custom variables", () => { "Add a custom variable to make it available in scripts and profiles." ) ).toBeInTheDocument(); - expect( - screen.getByRole("button", { name: "Add custom variable" }) - ).toBeInTheDocument(); + // Header button and EmptyState CTA button both render + const addButtons = screen.getAllByRole("button", { + name: /Add custom variable/, + }); + expect(addButtons).toHaveLength(2); }); }); diff --git a/frontend/pages/ManageControlsPage/Variables/Variables.tsx b/frontend/pages/ManageControlsPage/Variables/Variables.tsx index f68a3bb8a9..3c16373200 100644 --- a/frontend/pages/ManageControlsPage/Variables/Variables.tsx +++ b/frontend/pages/ManageControlsPage/Variables/Variables.tsx @@ -167,43 +167,19 @@ const Variables = () => { ); - const renderPageDescription = () => ( - - {isPremiumTier - ? "Manage custom variables that will be available in scripts and profiles across all fleets." - : "Manage custom variables that will be available in scripts and profiles."}{" "} - - - } - /> - ); + const isEmpty = !isLoading && data?.count === 0; - if (isLoading) { - return ( -
-
- {renderPageDescription()} -
+ const renderContent = () => { + if (isLoading) { + return (
-
- ); - } + ); + } - if (data?.count === 0) { - return ( -
-
- {renderPageDescription()} -
+ if (isEmpty) { + return ( { ) : undefined } /> - {showAddModal && ( - setShowAddModal(false)} - onSave={onSaveVariable} - /> - )} -
- ); - } + ); + } - return ( -
-
- {renderPageDescription()} - {canEdit && ( - ( - - )} - /> - )} -
+ return ( ref={paginatedListRef} pageSize={VARIABLES_PAGE_SIZE} @@ -281,6 +231,44 @@ const Variables = () => { } /> + ); + }; + + return ( +
+
+ + {isPremiumTier + ? "Manage custom variables that will be available in scripts and profiles across all fleets." + : "Manage custom variables that will be available in scripts and profiles."}{" "} + + + } + /> + {canEdit && ( + ( + + )} + /> + )} +
+ {renderContent()} {showAddModal && ( setShowAddModal(false)} diff --git a/frontend/pages/policies/edit/components/PolicyResults/PolicyResults.tsx b/frontend/pages/policies/edit/components/PolicyResults/PolicyResults.tsx index a624631bde..353849ac5a 100644 --- a/frontend/pages/policies/edit/components/PolicyResults/PolicyResults.tsx +++ b/frontend/pages/policies/edit/components/PolicyResults/PolicyResults.tsx @@ -165,12 +165,21 @@ const PolicyResults = ({ } if (finishedWithNoResults) { + const hostVerb = targetsTotalCount === 1 ? "host is" : "hosts are"; + const errorsMessage = errors?.length ? ( + <> + {" "} + or review the Errors tab for details + + ) : null; return ( 1 ? "s" : "" - } you targeted reported "Online" or check out the "Errors" table.`} + header="No results returned" + info={ + <> + Check whether the {hostVerb} online{errorsMessage}. + + } /> ); } diff --git a/frontend/pages/queries/edit/components/QueryResults/QueryResults.tsx b/frontend/pages/queries/edit/components/QueryResults/QueryResults.tsx index bd4c28414d..adac968ecd 100644 --- a/frontend/pages/queries/edit/components/QueryResults/QueryResults.tsx +++ b/frontend/pages/queries/edit/components/QueryResults/QueryResults.tsx @@ -156,12 +156,21 @@ const QueryResults = ({ }; const renderNoResults = () => { + const hostVerb = targetsTotalCount === 1 ? "host is" : "hosts are"; + const errorsMessage = errors?.length ? ( + <> + {" "} + or review the Errors tab for details + + ) : null; return ( 1 ? "s" : "" - } you targeted reported "Online" or check out the "Errors" table.`} + header="No results returned" + info={ + <> + Check whether the {hostVerb} online{errorsMessage}. + + } /> ); };