Skip to content

fix: improve GroupCard keyboard accessibility#1517

Merged
simo6529 merged 6 commits intomainfrom
071025-5
Oct 8, 2025
Merged

fix: improve GroupCard keyboard accessibility#1517
simo6529 merged 6 commits intomainfrom
071025-5

Conversation

@simo6529
Copy link
Copy Markdown
Collaborator

@simo6529 simo6529 commented Oct 7, 2025

Summary by CodeRabbit

  • New Features
    • Group cards now include an explicit interactive button overlay with proper ARIA labeling; Enter/Space activate navigation.
  • Bug Fixes
    • More consistent navigation across mouse and keyboard; reduced accidental overlap via adjusted stacking.
  • Style
    • Updated stacking and layout classes so controls, links, and labels render reliably.
  • Tests
    • Added keyboard activation tests and reset navigation mocks for stability.

Signed-off-by: Simo <simo@6529.io>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Oct 7, 2025

Walkthrough

Replaces the card's outer click target with an explicit idle-state button overlay, adds keyboard activation (Enter/Space) and ARIA labeling, adjusts z-index/presentation classes across card subcomponents, and updates tests to target the role="button" element and cover keyboard navigation. Mocks are cleared before each test.

Changes

Cohort / File(s) Summary of Changes
GroupCard interactivity & accessibility
components/groups/page/list/card/GroupCard.tsx
Introduced isIdle and a full-size invisible button overlay for navigation; removed the previous onClick on the container; added aria-label/labeling and keyboard activation handling (Enter/Space); content rendering unchanged but gated by idle state.
Presentation / stacking adjustments
components/groups/page/list/card/GroupCardContent.tsx, components/groups/page/list/card/GroupCardHeader.tsx, components/groups/page/list/card/actions/GroupCardEditActions.tsx, components/groups/page/list/card/GroupCardConfigs.tsx
Updated Tailwind classes: added tw-relative, tw-z-20 to several elements and increased scroll controls' z-index from tw-z-[5] to tw-z-[20]; purely presentation/stacking changes.
Tests: navigation & keyboard coverage
__tests__/components/groups/page/list/card/GroupCard.test.tsx
Added userEvent import and beforeEach to clear router push mock; changed queries to getByRole("button"); updated click test and added Enter and Space key activation tests asserting navigation to /network?page=1&group={group.id}.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Card as GroupCard
  participant Router as Router.push

  rect rgb(232,240,255)
    note right of Card: Idle-state overlay (button) present when idle
    User->>Card: Click overlay button
    alt isIdle = true
      Card->>Router: push("/network?page=1&group={id}")
      Router-->>User: navigate
    else
      Card-->>User: no navigation
    end
  end

  rect rgb(240,255,232)
    note right of Card: Keyboard activation (Enter / Space)
    User->>Card: KeyDown (Enter or Space)
    alt isIdle = true and key ∈ {Enter, Space}
      Card->>Router: push("/network?page=1&group={id}")
      Router-->>User: navigate
    else
      Card-->>User: no action
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • ragnep

Poem

I tap my paw—click, hop, go!
An invisible button steals the show.
Enter, Space, a gentle press,
Routes align and tests confess.
Little rabbit hops—access! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly and succinctly describes the primary change, which is improving keyboard accessibility for the GroupCard component by introducing dedicated button overlays and enhanced Enter/Space key interactions, matching the implementation and test updates in this pull request.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 071025-5

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36443ea and da1d1a6.

📒 Files selected for processing (1)
  • __tests__/components/groups/page/list/card/GroupCard.test.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/components/groups/page/list/card/GroupCard.test.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
__tests__/components/groups/page/list/card/GroupCard.test.tsx (1)

92-95: Remove comments from the code.

As per coding guidelines for TypeScript files, comments should not be included in the code.

Apply this diff to remove the comments:

-    // Click the view to trigger state change
     fireEvent.click(container.querySelector('[data-testid="view"]')!);

-    // Should call the callback to notify parent of state change
     expect(setActive).toHaveBeenCalledWith(group.id);
🧹 Nitpick comments (1)
__tests__/components/groups/page/list/card/GroupCard.test.tsx (1)

67-83: LGTM! Keyboard navigation tests are comprehensive.

The tests properly cover click, Enter, and Space key navigation with the new button role, ensuring keyboard accessibility is functional.

As per coding guidelines, consider using userEvent instead of fireEvent for more realistic user interaction simulation:

-import { render, fireEvent } from "@testing-library/react";
+import { render } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";

Then update the tests:

 it("navigates to community view when idle", () => {
   const { getByRole } = renderComp();
-  fireEvent.click(getByRole("button"));
+  await userEvent.click(getByRole("button"));
   expect(push).toHaveBeenCalledWith(`/network?page=1&group=${group.id}`);
 });

 it("navigates to community view when pressing Enter", () => {
   const { getByRole } = renderComp();
-  fireEvent.keyDown(getByRole("button"), { key: "Enter" });
+  await userEvent.type(getByRole("button"), "{Enter}");
   expect(push).toHaveBeenCalledWith(`/network?page=1&group=${group.id}`);
 });

 it("navigates to community view when pressing Space", () => {
   const { getByRole } = renderComp();
-  fireEvent.keyDown(getByRole("button"), { key: " " });
+  await userEvent.type(getByRole("button"), "{Space}");
   expect(push).toHaveBeenCalledWith(`/network?page=1&group=${group.id}`);
 });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8c6af40 and b632366.

📒 Files selected for processing (2)
  • __tests__/components/groups/page/list/card/GroupCard.test.tsx (2 hunks)
  • components/groups/page/list/card/GroupCard.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props

Use TypeScript for implementation code

Files:

  • components/groups/page/list/card/GroupCard.tsx
  • __tests__/components/groups/page/list/card/GroupCard.test.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling

Use React functional components with hooks

Files:

  • components/groups/page/list/card/GroupCard.tsx
  • __tests__/components/groups/page/list/card/GroupCard.test.tsx
**/{__tests__/**/*.{ts,tsx},*.test.tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/{__tests__/**/*.{ts,tsx},*.test.tsx}: Place tests in tests directories or alongside components as ComponentName.test.tsx
Mock external dependencies and APIs in tests

Files:

  • __tests__/components/groups/page/list/card/GroupCard.test.tsx
__tests__/**

📄 CodeRabbit inference engine (tests/AGENTS.md)

Place Jest test suites under the __tests__ directory mirroring source folders (e.g., components, contexts, hooks, utils)

Files:

  • __tests__/components/groups/page/list/card/GroupCard.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use @testing-library/react and @testing-library/user-event for React component tests

Files:

  • __tests__/components/groups/page/list/card/GroupCard.test.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
__tests__/components/groups/page/list/card/GroupCard.test.tsx (1)

33-35: LGTM!

Clearing the mock before each test is a best practice that prevents test pollution.

components/groups/page/list/card/GroupCard.tsx (4)

3-9: LGTM!

The KeyboardEvent import is necessary for proper typing of the keyboard handler.


119-124: LGTM! Keyboard handler is correctly implemented.

The handler properly supports both Enter and Space keys for button activation, calls preventDefault() to prevent default browser behavior (like scrolling), and delegates to goToCommunityView which already guards against non-idle state.


126-126: LGTM!

The isIdle constant improves code readability and reduces duplication.


130-135: LGTM! Accessibility implementation is correct.

The ARIA semantics and focus management are properly implemented:

  • role="button" makes the div behave as a button for assistive technologies
  • tabIndex={isIdle ? 0 : -1} correctly manages focus (focusable when idle, not focusable otherwise)
  • aria-disabled={!isIdle} accurately reflects the interactive state
  • onKeyDown enables keyboard activation

This implementation follows WCAG 2.1 guidelines for keyboard accessibility.

Signed-off-by: Simo <simo@6529.io>
Signed-off-by: Simo <simo@6529.io>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Oct 8, 2025

@simo6529 simo6529 merged commit 58752a6 into main Oct 8, 2025
7 checks passed
@simo6529 simo6529 deleted the 071025-5 branch October 8, 2025 07:38
@coderabbitai coderabbitai Bot mentioned this pull request Oct 14, 2025
@coderabbitai coderabbitai Bot mentioned this pull request Nov 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants