feat(design): the NavRail primitive with optional short labels, the flat surfaces onto roles (E28 S3d3, B7/B5)

This commit is contained in:
2026-09-25 00:47:46 +02:00
parent 6354454cc9
commit 7fa8f4ebde
20 changed files with 342 additions and 101 deletions
@@ -0,0 +1,47 @@
// @vitest-environment jsdom
//
// E28 S3d (B7): the nav rail's row. Icon-only, its name is the module's full name (with an unread
// count, which was only ever drawn); with the labels on, the name is the short label the user SEES
// (WCAG 2.5.3), the full one staying in the tooltip. "You are here" is aria-current plus the tint.
import { afterEach, describe, expect, it, vi } from "vitest";
import { cleanup, render, screen } from "@testing-library/react";
import { Bell } from "lucide-react";
import { NavRailItem } from "./NavRail";
vi.mock("../../lib/hints", () => ({ hintsEnabled: () => true, subscribeHints: () => () => {} }));
afterEach(cleanup);
describe("NavRailItem", () => {
it("icon-only: the full name, the count in it, and the current page marked", () => {
render(
<NavRailItem
icon={Bell}
label="Notifications"
shortLabel="Alerts"
showLabel={false}
active
badge={3}
onClick={() => {}}
/>,
);
const row = screen.getByRole("button", { name: "Notifications (3)" });
expect(row.getAttribute("aria-current")).toBe("page");
expect(row.className).toContain("bg-accent/15");
expect(row.textContent).not.toContain("Alerts");
});
it("labelled: the name is the visible short label", () => {
render(
<NavRailItem
icon={Bell}
label="Notifications"
shortLabel="Alerts"
showLabel
onClick={() => {}}
/>,
);
const row = screen.getByRole("button", { name: "Alerts" });
expect(row.getAttribute("aria-current")).toBeNull();
});
});