style(notifications): the Earlier fold reads as a section heading, like its siblings

It was a ghost button in body type under two uppercase section labels. It is now
the heading itself, its text the disclosure's button (24px tall, past the
WCAG 2.5.8 floor).
This commit is contained in:
2026-10-28 20:42:18 +01:00
parent f49dc6532f
commit a5666bfde9
2 changed files with 19 additions and 10 deletions
@@ -139,6 +139,8 @@ describe("NotificationsPanel · order", () => {
expect(rows()).toEqual(["Ready 1"]);
const fold = screen.getByRole("button", { name: "inbox.earlier:2" });
expect(fold.getAttribute("aria-expanded")).toBe("false");
// A section heading like "Needs you" and "Recent", its text the disclosure's button.
expect(fold.closest("h2")).not.toBeNull();
fireEvent.click(fold);
expect(fold.getAttribute("aria-expanded")).toBe("true");
expect(rows()).toEqual(["Ready 1", "Activity 3", "Ready 2"]);
@@ -46,6 +46,7 @@ import { channelYouTubeUrl, formatDate } from "../../lib/format";
import { entryKey, keyOf, orderInbox, type InboxEntry } from "../../lib/inboxOrder";
import { Button } from "../../components/ui/Button";
import { IconButton } from "../../components/ui/IconButton";
import { Pressable } from "../../components/ui/Pressable";
import { LEVEL_STYLE } from "../../components/ui/toastLevels";
import { PageToolbar } from "../../components/ui/PageShell";
import { PageMenu } from "../../components/ui/PageMenu";
@@ -481,16 +482,22 @@ export default function NotificationsPanel() {
)}
{order.earlier.length > 0 && (
<section>
<Button
variant="ghost"
size="sm"
aria-expanded={earlierOpen}
onClick={() => setEarlierOpen((o) => !o)}
icon={earlierOpen ? <ChevronDown /> : <ChevronRight />}
className={earlierOpen ? "mb-2" : undefined}
>
{t("inbox.earlier", { count: order.earlier.length })}
</Button>
{/* A heading like its siblings, its text the disclosure's button (the ARIA
disclosure pattern); 24px tall so the target clears the WCAG 2.5.8 floor. */}
<SectionLabel className={earlierOpen ? "mb-2" : undefined}>
<Pressable
aria-expanded={earlierOpen}
onClick={() => setEarlierOpen((o) => !o)}
className="min-h-6 inline-flex items-center gap-1 uppercase hover:text-fg transition"
>
{earlierOpen ? (
<ChevronDown className="size-3.5" aria-hidden />
) : (
<ChevronRight className="size-3.5" aria-hidden />
)}
{t("inbox.earlier", { count: order.earlier.length })}
</Pressable>
</SectionLabel>
{earlierOpen && (
<NavGrid className="flex flex-col gap-2">{order.earlier.map(entry)}</NavGrid>
)}