From f0224dbb8db6f8d5e355d6f3c556655cc84a41e1 Mon Sep 17 00:00:00 2001 From: nanlebenthel-web Date: Wed, 29 Jul 2026 17:51:30 +0100 Subject: [PATCH] fix(frontend): a11y, docs, and test coverage across 4 components - fix(Navbar): wire the mobile menu through useModalDialog for focus trap and Escape-to-close; hamburger button aria-expanded reflects the menu open state - fix(MobileMockup): expose the CSS phone illustration as a single accessible unit via role="img" + aria-label, hide decorative inner nodes from assistive tech (fixed pixel dimensions already prevent layout shift; component has no raster/next/image asset) - test(Features): add render coverage asserting all feature titles and card count - docs(ui): add Card behavior notes to UI_COMPONENTS.md, cross-checked against Card.tsx's actual prop signature Closes #1028 Closes #1029 Closes #1030 Closes #1031 --- frontend/src/components/Features.test.tsx | 24 ++++++++++++ frontend/src/components/MobileMockup.tsx | 10 +++-- frontend/src/components/Navbar.tsx | 42 +++++++++++++-------- frontend/src/components/ui/UI_COMPONENTS.md | 6 +++ 4 files changed, 63 insertions(+), 19 deletions(-) create mode 100644 frontend/src/components/Features.test.tsx diff --git a/frontend/src/components/Features.test.tsx b/frontend/src/components/Features.test.tsx new file mode 100644 index 00000000..b6014f11 --- /dev/null +++ b/frontend/src/components/Features.test.tsx @@ -0,0 +1,24 @@ +import { describe, it, expect } from "vitest"; +import { render, screen } from "@testing-library/react"; +import { Features } from "./Features"; + +describe("Features", () => { + it("renders all expected feature titles", () => { + render(); + + expect(screen.getByText("Per-Second Streaming")).toBeInTheDocument(); + expect(screen.getByText("Zero Overhead")).toBeInTheDocument(); + expect(screen.getByText("Institutional Grade")).toBeInTheDocument(); + }); + + it("renders exactly three feature cards", () => { + render(); + + const heading = screen.getByRole("heading", { level: 3, name: "Per-Second Streaming" }); + const cardGrid = heading.closest("div.grid"); + expect(cardGrid).not.toBeNull(); + + const headings = screen.getAllByRole("heading", { level: 3 }); + expect(headings).toHaveLength(3); + }); +}); diff --git a/frontend/src/components/MobileMockup.tsx b/frontend/src/components/MobileMockup.tsx index 28464c37..5e41ee6c 100644 --- a/frontend/src/components/MobileMockup.tsx +++ b/frontend/src/components/MobileMockup.tsx @@ -13,9 +13,13 @@ export const MobileMockup = () => { }, []); return ( -
+
{/* Phone Case/Outer Frame */} -
+ ); }; diff --git a/frontend/src/components/Navbar.tsx b/frontend/src/components/Navbar.tsx index 038ee642..50efaa97 100644 --- a/frontend/src/components/Navbar.tsx +++ b/frontend/src/components/Navbar.tsx @@ -6,6 +6,7 @@ import Link from "next/link"; import { useWallet } from "@/context/wallet-context"; import { ModeToggle } from "./ModeToggle"; import { WalletButton } from "./wallet/WalletButton"; +import { useModalDialog } from "@/hooks/useModalDialog"; const NAV_LINKS = [ { href: "/", label: "Home" }, @@ -69,23 +70,32 @@ export const Navbar = () => {
{isMobileMenuOpen && ( -
- {NAV_LINKS.map((link) => ( - setIsMobileMenuOpen(false)} - > - {link.label} - - ))} - -
+ setIsMobileMenuOpen(false)} /> )} ); }; + +const MobileMenu = ({ onClose }: { onClose: () => void }) => { + const dialogRef = useModalDialog({ onClose }); + + return ( +
+ {NAV_LINKS.map((link) => ( + + {link.label} + + ))} + +
+ ); +}; diff --git a/frontend/src/components/ui/UI_COMPONENTS.md b/frontend/src/components/ui/UI_COMPONENTS.md index 306c57d0..0a24d156 100644 --- a/frontend/src/components/ui/UI_COMPONENTS.md +++ b/frontend/src/components/ui/UI_COMPONENTS.md @@ -116,6 +116,12 @@ A glass-morphism card container with optional hover and glow effects. | `glow` | `boolean` | `false` | Adds a glowing shadow effect | | `hover` | `boolean` | `true` | Enables hover lift effect | +### Behavior Notes + +- **glow**: Applies the `glow-card` class for an accent-colored ambient glow around the card +- **hover** (default `true`): Lifts the card 1px on hover and adds an accent-tinted border/shadow; set `hover={false}` for static cards +- `children` is required — `Card` renders only the passed content inside the glass container + ### Usage Examples ```tsx