Skip to content

(SP: 2) [Frontend] Q&A Viewed and Bookmark Indicators#402

Merged
ViktorSvertoka merged 2 commits intodevelopfrom
qa-viewed-bookmark-indicators
Mar 15, 2026
Merged

(SP: 2) [Frontend] Q&A Viewed and Bookmark Indicators#402
ViktorSvertoka merged 2 commits intodevelopfrom
qa-viewed-bookmark-indicators

Conversation

@ViktorSvertoka
Copy link
Member

@ViktorSvertoka ViktorSvertoka commented Mar 15, 2026

  • Add a Viewed indicator to Q&A accordion items after the user opens a question
  • Add a bookmark control for viewed questions
  • Persist viewed and bookmarked states in localStorage
  • Keep accordion item height stable when indicators appear
  • Ensure the accordion chevron stays visually centered
  • Cover the new behavior with component tests

Closes #401

Summary by CodeRabbit

  • New Features

    • Q&A items now show a "Viewed" badge and a bookmark control; bookmarks persist across sessions and sync across open tabs.
    • Bookmark controls become available after viewing a question and support keyboard/accessibility interactions.
    • Accordion triggers gain improved layout and support for optional content before/after the header.
  • Tests

    • Added tests covering viewed/bookmark persistence, fallback IDs for missing question IDs, and bookmark toggling.

@ViktorSvertoka ViktorSvertoka self-assigned this Mar 15, 2026
@ViktorSvertoka ViktorSvertoka requested a review from AM1007 as a code owner March 15, 2026 13:35
@ViktorSvertoka ViktorSvertoka added enhancement New feature or request UI Visual components, styling, layout changes UX User experience improvements, visual polish, interaction feedback labels Mar 15, 2026
@vercel
Copy link
Contributor

vercel bot commented Mar 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
devlovers-net Ignored Ignored Preview Mar 15, 2026 1:53pm

Request Review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1a4e62d2-6e8b-42c1-aef7-97d800660d7b

📥 Commits

Reviewing files that changed from the base of the PR and between 99d5738 and 7be66d5.

📒 Files selected for processing (2)
  • frontend/components/q&a/AccordionList.tsx
  • frontend/components/tests/q&a/accordion-list.test.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/components/q&a/AccordionList.tsx
  • frontend/components/tests/q&a/accordion-list.test.tsx

📝 Walkthrough

Walkthrough

Adds localStorage-backed viewed and bookmarked state to Q&A accordion items, introduces leading/trailing slots on AccordionTrigger, updates UI to show Viewed badge and bookmark control, and includes tests covering persisted state and cross-tab sync.

Changes

Cohort / File(s) Summary
Q&A Accordion State Management
frontend/components/q&a/AccordionList.tsx
Adds localStorage keys and helpers, stable question ID generation, initializes viewed/bookmarked sets on mount, subscribes to storage events, adds markAsViewed and toggleBookmark handlers, and renders Viewed badge + bookmark control.
Accordion Component Enhancement
frontend/components/ui/accordion.tsx
Extends AccordionTrigger API with optional leading and trailing props, adjusts trigger alignment classes, and tweaks ChevronDownIcon styling.
Component Tests
frontend/components/tests/q&a/accordion-list.test.tsx
Adds in-memory localStorage mock, updates AccordionTrigger mock signature to accept leading, trailing, and onClick, resets storage between tests, and adds tests for stable fallback IDs, viewed-state persistence, and bookmark toggling.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant User as "User (click)"
  participant Accordion as "AccordionList\n(Component)"
  participant Trigger as "AccordionTrigger\n(UI)"
  participant Storage as "localStorage"
  participant OtherTab as "Other Tab\n(storage event listener)"

  rect rgba(200,200,255,0.5)
  User->>Trigger: click open
  Trigger->>Accordion: onClick -> markAsViewed(questionId)
  Accordion->>Storage: read/write viewed set
  Storage-->>Accordion: persisted viewed IDs
  Accordion-->>Trigger: render Viewed badge + bookmark control
  end

  rect rgba(200,255,200,0.5)
  User->>Trigger: toggle bookmark
  Trigger->>Accordion: toggleBookmark(questionId)
  Accordion->>Storage: update bookmarked set
  Storage-->>OtherTab: storage event
  OtherTab->>Accordion: update state from storage event
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

refactor

Suggested reviewers

  • AM1007

Poem

🐰 A tap, a badge, a tiny mark —

local bits saved in the dark,
Across the tabs my bookmarks hop,
Viewed and kept, they never stop,
Hooray — a tidy Q&A spark!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: adding viewed indicators and bookmark controls to Q&A accordion items.
Linked Issues check ✅ Passed All coding requirements from issue #401 are implemented: viewed indicators, bookmark controls, localStorage persistence, stable item height, centered chevron, and component tests.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #401 requirements; no out-of-scope modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch qa-viewed-bookmark-indicators
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Tip

You can get early access to new features in CodeRabbit.

Enable the early_access setting to enable early access features such as new models, tools, and more.

Copy link
Contributor

@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: 4

🧹 Nitpick comments (1)
frontend/components/tests/q&a/accordion-list.test.tsx (1)

35-53: Forward all trigger props in the mock to avoid hiding interaction regressions.

The mock currently drops non-onClick props. Forwarding the rest keeps test behavior closer to production trigger usage.

Mock fidelity improvement
   AccordionTrigger: ({
     children,
     leading,
     trailing,
-    onClick,
+    ...props
   }: {
     children: React.ReactNode;
     leading?: React.ReactNode;
     trailing?: React.ReactNode;
-    onClick?: () => void;
-  }) => (
+  } & React.ButtonHTMLAttributes<HTMLButtonElement>) => (
     <div>
       {leading}
-      <button type="button" onClick={onClick}>
+      <button type="button" {...props}>
         {children}
       </button>
       {trailing}
     </div>
   ),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/components/tests/q`&a/accordion-list.test.tsx around lines 35 - 53,
The mock AccordionTrigger currently destructures only children, leading,
trailing, and onClick and drops any other props; update the AccordionTrigger
mock to accept a rest props object (e.g., ...props) alongside the named props
and spread those props onto the rendered <button> so all incoming trigger props
(aria attributes, className, disabled, data-*, etc.) are forwarded; keep the
same component name AccordionTrigger and ensure the button still uses the
onClick handler and renders leading/children/trailing as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/components/q`&a/AccordionList.tsx:
- Around line 67-70: The writeStoredQuestionIds function calls
window.localStorage.setItem directly which can throw in restricted environments
or when quota is exceeded; update writeStoredQuestionIds to first check typeof
window !== 'undefined' and that window.localStorage is available, then wrap
JSON.stringify([...ids]) and localStorage.setItem(storageKey, ...) in a
try/catch, swallowing or emitting a non-fatal warning (e.g., console.warn) on
error so clicks/bookmarks don’t break; reference the function name
writeStoredQuestionIds and the parameters storageKey and ids when making this
change.
- Around line 372-381: The storage listener in handleStorage currently ignores
clear events (when e.key === null), leaving stale UI; update handleStorage (the
function named handleStorage) so that when e.key === null it performs the same
updates as when CACHE_KEY, QA_VIEWED_STORAGE_KEY, or QA_BOOKMARK_STORAGE_KEY
change: call refreshCachedTerms() and re-read both viewed/bookmarked IDs via
setViewedItems(readStoredQuestionIds(QA_VIEWED_STORAGE_KEY)) and
setBookmarkedItems(readStoredQuestionIds(QA_BOOKMARK_STORAGE_KEY)); keep the
existing per-key branches but add an early branch for e.key === null to sync
cross-tab localStorage.clear() events.
- Around line 495-545: The bookmark control is currently nested inside the
AccordionTrigger which breaks accessibility; move the bookmark span out of the
trigger and render it via the AccordionTrigger/trailing prop so it becomes a
sibling interactive control. Locate the AccordionTrigger usage (the component
wrapping q.question) and remove the nested span with role="button" and its
tabIndex/aria-* props from inside the trigger; instead render a standalone
bookmark control in the trailing prop that uses toggleBookmark(questionId) for
onClick and onKeyDown, applies the same isViewed/isBookmarked-based aria-label
and aria-pressed logic, and preserves the Badge and Bookmark visuals and
focus/hover classes so it remains keyboard-accessible and not nested inside the
trigger.

---

Nitpick comments:
In `@frontend/components/tests/q`&a/accordion-list.test.tsx:
- Around line 35-53: The mock AccordionTrigger currently destructures only
children, leading, trailing, and onClick and drops any other props; update the
AccordionTrigger mock to accept a rest props object (e.g., ...props) alongside
the named props and spread those props onto the rendered <button> so all
incoming trigger props (aria attributes, className, disabled, data-*, etc.) are
forwarded; keep the same component name AccordionTrigger and ensure the button
still uses the onClick handler and renders leading/children/trailing as before.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e3ec166a-1110-47dc-be42-e08bf04b8a84

📥 Commits

Reviewing files that changed from the base of the PR and between ac0525c and 99d5738.

📒 Files selected for processing (3)
  • frontend/components/q&a/AccordionList.tsx
  • frontend/components/tests/q&a/accordion-list.test.tsx
  • frontend/components/ui/accordion.tsx

@ViktorSvertoka ViktorSvertoka merged commit 605926d into develop Mar 15, 2026
7 checks passed
@ViktorSvertoka ViktorSvertoka deleted the qa-viewed-bookmark-indicators branch March 15, 2026 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request UI Visual components, styling, layout changes UX User experience improvements, visual polish, interaction feedback

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant