From 4788dcade2e1e951be6f718b043182550b609714 Mon Sep 17 00:00:00 2001
From: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com>
Date: Fri, 24 Apr 2026 15:40:40 +0200
Subject: [PATCH] fix(ui): polish shared table pagination and provider spacing
(#10891)
---
ui/CHANGELOG.md | 1 +
.../providers-accounts-view.test.tsx | 58 ++++++++++++++++
.../providers/providers-accounts-view.tsx | 36 +++++-----
.../ui/table/data-table-pagination.test.tsx | 67 +++++++++++++++++++
.../ui/table/data-table-pagination.tsx | 3 +-
5 files changed, 147 insertions(+), 18 deletions(-)
create mode 100644 ui/components/providers/providers-accounts-view.test.tsx
create mode 100644 ui/components/ui/table/data-table-pagination.test.tsx
diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md
index e32bda3962..25a564cbcb 100644
--- a/ui/CHANGELOG.md
+++ b/ui/CHANGELOG.md
@@ -17,6 +17,7 @@ All notable changes to the **Prowler UI** are documented in this file.
- Mutelist improvements: table now supports name/reason search and visual count badges for finding targets [(#10846)](https://github.com/prowler-cloud/prowler/pull/10846)
- Resources now use batch-applied filters, render metadata JSON with syntax highlighting, and more [(#10861)](https://github.com/prowler-cloud/prowler/pull/10861)
- Added knip for dead code detection with `lint:knip` and `lint:knip:fix` scripts [(#10654)](https://github.com/prowler-cloud/prowler/pull/10654)
+- Table pagination controls now keep their arrows visible on hover in light theme, and more UI improvements [(#10862)](https://github.com/prowler-cloud/prowler/pull/10862)
---
diff --git a/ui/components/providers/providers-accounts-view.test.tsx b/ui/components/providers/providers-accounts-view.test.tsx
new file mode 100644
index 0000000000..9263277ea9
--- /dev/null
+++ b/ui/components/providers/providers-accounts-view.test.tsx
@@ -0,0 +1,58 @@
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+import type { FilterOption, MetaDataProps, ProviderProps } from "@/types";
+import type { ProvidersTableRow } from "@/types/providers-table";
+
+vi.mock("@/components/providers/add-provider-button", () => ({
+ AddProviderButton: () => ,
+}));
+
+vi.mock("@/components/providers/muted-findings-config-button", () => ({
+ MutedFindingsConfigButton: () => (
+
+ ),
+}));
+
+vi.mock("@/components/providers/providers-filters", () => ({
+ ProvidersFilters: () =>
Filters
,
+}));
+
+vi.mock("@/components/providers/providers-accounts-table", () => ({
+ ProvidersAccountsTable: () => Table
,
+}));
+
+vi.mock("@/components/providers/wizard", () => ({
+ ProviderWizardModal: () => ,
+}));
+
+import { ProvidersAccountsView } from "./providers-accounts-view";
+
+const filters: FilterOption[] = [];
+const providers: ProviderProps[] = [];
+const rows: ProvidersTableRow[] = [];
+const metadata: MetaDataProps = {
+ pagination: { page: 1, pages: 1, count: 0, itemsPerPage: [10] },
+ version: "latest",
+};
+
+describe("ProvidersAccountsView", () => {
+ it("keeps the same vertical spacing between filters and table as other views", () => {
+ render(
+ ,
+ );
+
+ expect(screen.getByTestId("providers-filters").parentElement).toHaveClass(
+ "flex",
+ "flex-col",
+ "gap-6",
+ );
+ expect(screen.getByTestId("providers-table")).toBeInTheDocument();
+ });
+});
diff --git a/ui/components/providers/providers-accounts-view.tsx b/ui/components/providers/providers-accounts-view.tsx
index 51329b5515..b53155d8c0 100644
--- a/ui/components/providers/providers-accounts-view.tsx
+++ b/ui/components/providers/providers-accounts-view.tsx
@@ -60,23 +60,25 @@ export function ProvidersAccountsView({
return (
<>
-
-
- openProviderWizard()} />
- >
- }
- />
-
+
+
+
+ openProviderWizard()} />
+ >
+ }
+ />
+
+
({
+ usePathname: () => "/providers",
+ useRouter: () => ({ push: vi.fn() }),
+ useSearchParams: () => new URLSearchParams(),
+}));
+
+vi.mock("@/lib", () => ({
+ getPaginationInfo: () => ({
+ currentPage: 2,
+ totalPages: 4,
+ totalEntries: 40,
+ itemsPerPageOptions: [10, 20, 50],
+ }),
+}));
+
+vi.mock("@/components/shadcn/select/select", () => ({
+ Select: ({ children }: { children: React.ReactNode }) => (
+ {children}
+ ),
+ SelectContent: ({ children }: { children: React.ReactNode }) => (
+ {children}
+ ),
+ SelectItem: ({
+ children,
+ value,
+ }: {
+ children: React.ReactNode;
+ value: string;
+ }) => ,
+ SelectTrigger: ({ children }: { children: React.ReactNode }) => (
+
+ ),
+ SelectValue: () => 10,
+}));
+
+import { DataTablePagination } from "./data-table-pagination";
+
+const metadata: MetaDataProps = {
+ pagination: {
+ page: 2,
+ pages: 4,
+ count: 40,
+ itemsPerPage: [10, 20, 50],
+ },
+ version: "latest",
+};
+
+describe("DataTablePagination", () => {
+ it("keeps navigation arrows visible on hover in light theme", () => {
+ render();
+
+ expect(screen.getByLabelText("Go to first page")).toHaveClass(
+ "hover:text-text-neutral-primary",
+ );
+ expect(screen.getByLabelText("Go to first page")).toHaveClass(
+ "hover:bg-bg-neutral-tertiary",
+ );
+ expect(screen.getByLabelText("Go to next page")).toHaveClass(
+ "hover:text-text-neutral-primary",
+ );
+ });
+});
diff --git a/ui/components/ui/table/data-table-pagination.tsx b/ui/components/ui/table/data-table-pagination.tsx
index 7f3f5eb83d..019d98c31d 100644
--- a/ui/components/ui/table/data-table-pagination.tsx
+++ b/ui/components/ui/table/data-table-pagination.tsx
@@ -40,7 +40,8 @@ interface DataTablePaginationProps {
const NAV_BUTTON_STYLES = {
base: "flex items-center justify-center rounded-full p-3 transition-colors",
- enabled: "text-text-neutral-secondary hover:text-white",
+ enabled:
+ "text-text-neutral-secondary hover:bg-bg-neutral-tertiary hover:text-text-neutral-primary",
disabled: "text-text-neutral-tertiary cursor-not-allowed pointer-events-none",
} as const;