Skip to content

Commit ee7eed6

Browse files
RealDiligentRealDiligent
andauthored
fix(ui-kit): give PaginationLink's aria-disabled a real visual/interaction effect (#8359)
PaginationLink renders an <a>, which has no native disabled attribute, and applied no styling keyed off aria-disabled — so the five miner-ui routes that set aria-disabled at page boundaries got only a screen-reader signal, with the link staying fully opaque, hover-active, and pointer-interactive. Adds aria-disabled:pointer-events-none aria-disabled:opacity-50 at the PaginationLink level (inherited by PaginationPrevious/PaginationNext), matching the aria-disabled: styling convention sidebar.tsx and calendar.tsx already use, with a class-list regression test. Closes #8307 Co-authored-by: RealDiligent <nft.gold.eth@gmail.com>
1 parent 2ae66d6 commit ee7eed6

2 files changed

Lines changed: 52 additions & 0 deletions

File tree

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { render, screen } from "@testing-library/react";
2+
import { describe, expect, it } from "vitest";
3+
4+
import {
5+
PaginationLink,
6+
PaginationNext,
7+
PaginationPrevious,
8+
} from "./pagination";
9+
10+
// Regression for #8307: PaginationLink (and PaginationPrevious/PaginationNext built on it) render an <a>,
11+
// which has no native disabled attribute — a consumer-supplied aria-disabled must produce a real
12+
// visual/interaction cue via the aria-disabled: Tailwind variant, matching sidebar.tsx/calendar.tsx.
13+
describe("PaginationLink aria-disabled styling (#8307)", () => {
14+
it("carries the aria-disabled: dim + pointer-events classes when aria-disabled is set", () => {
15+
render(
16+
<PaginationLink aria-disabled="true" aria-label="prev">
17+
1
18+
</PaginationLink>,
19+
);
20+
const link = screen.getByLabelText("prev");
21+
expect(link.className).toContain("aria-disabled:pointer-events-none");
22+
expect(link.className).toContain("aria-disabled:opacity-50");
23+
});
24+
25+
it("PaginationPrevious/PaginationNext inherit the aria-disabled styling from PaginationLink", () => {
26+
render(
27+
<nav>
28+
<PaginationPrevious aria-disabled="true" />
29+
<PaginationNext aria-disabled="true" />
30+
</nav>,
31+
);
32+
for (const label of ["Go to previous page", "Go to next page"]) {
33+
const el = screen.getByLabelText(label);
34+
expect(el.className).toContain("aria-disabled:pointer-events-none");
35+
expect(el.className).toContain("aria-disabled:opacity-50");
36+
}
37+
});
38+
39+
it("still renders (unchanged aria-current behavior) and the classes are present regardless — the variant only applies when aria-disabled is truthy at runtime", () => {
40+
render(
41+
<PaginationLink isActive aria-label="active">
42+
2
43+
</PaginationLink>,
44+
);
45+
const link = screen.getByLabelText("active");
46+
// isActive/aria-current is untouched by this fix.
47+
expect(link.getAttribute("aria-current")).toBe("page");
48+
});
49+
});

packages/loopover-ui-kit/src/components/pagination.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ const PaginationLink = ({
5252
variant: isActive ? "outline" : "ghost",
5353
size,
5454
}),
55+
// An <a> has no native disabled attribute, so a consumer-supplied aria-disabled needs an explicit
56+
// visual/interaction cue -- mirrors the aria-disabled: styling sidebar.tsx/calendar.tsx already use.
57+
"aria-disabled:pointer-events-none aria-disabled:opacity-50",
5558
className,
5659
)}
5760
{...props}

0 commit comments

Comments
 (0)