Skip to content

feat: add dedicated FAQ page#80

Open
saurabhhhcodes wants to merge 6 commits into
kunalverma2512:mainfrom
saurabhhhcodes:feat/faq-page-31
Open

feat: add dedicated FAQ page#80
saurabhhhcodes wants to merge 6 commits into
kunalverma2512:mainfrom
saurabhhhcodes:feat/faq-page-31

Conversation

@saurabhhhcodes
Copy link
Copy Markdown

@saurabhhhcodes saurabhhhcodes commented May 19, 2026

Summary

Adds a dedicated FAQ page for CodeLens and wires the existing FAQ CTA/footer navigation to the new route.

Fixes #31

Changes

  • added /faq route and a full-page FAQ experience
  • moved reusable FAQ content into src/data/faqs.js
  • reused the existing FAQ section data so Explore and the standalone page stay consistent
  • added a footer FAQ link for easier discovery

Validation

  • I ran local checks relevant to this change
  • I updated documentation when needed

Local checks run:

node node_modules/eslint/bin/eslint.js src/App.jsx src/pages/FAQPage.jsx src/components/explore/FAQSection.jsx src/components/shared/Footer.jsx src/data/faqs.js
git diff --check

Notes:

  • Targeted ESLint for changed files passed.
  • Full repo lint currently reports pre-existing issues in unrelated files.
  • npm run build is blocked in this macOS environment by the Rolldown native binding code-signature error after a fresh install; the failure occurs before app source bundling.

Summary by CodeRabbit

  • New Features

    • Added a dedicated FAQ page at /faq with indexed topics, topic chips, expandable Q&A, sidebar index buttons, smooth scrolling, and a “Go Back” button; Footer now links to the new FAQ.
  • Refactor

    • Centralized FAQ content into a shared data source (four FAQ entries) for reuse across the site.
  • Accessibility & UX

    • Improved accordion with ARIA attributes, per-item IDs, and smoother expand/collapse transitions.
  • Style

    • Updated “View All FAQs” link styling and added a bottom CTA section.

Review Change Stack


Suggested GSSoC labels if accepted: gssoc:approved, level:beginner, quality:clean, type:feature, type:design.

@github-actions
Copy link
Copy Markdown

🚀 PR Received Successfully

Hello @saurabhhhcodes,

Thank you for taking the initiative to contribute to this project.

Please ensure that your PR follows all project guidelines properly before requesting review.

⚠️ Important Instructions

  • Maintain proper code quality and structure
  • Do not make unnecessary changes/files
  • Ensure responsiveness across devices
  • Follow existing project conventions strictly
  • Attach screenshots/videos for UI-related changes
  • Resolve merge conflicts before requesting review
  • Avoid AI-generated low quality PRs or copied implementations

📌 Mandatory for GSSoC'26 Participants

Joining the community group and announcement channel is compulsory for all contributors participating through GSSoC'26.

Failure to follow contribution guidelines may lead to PR rejection.

We appreciate your effort and wish you a great open-source journey ahead. ✨

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a centralized faqs data module and a new FAQPage with hero chips, a left index of selectable questions, an accordion list with accessibility attributes and scroll-to behavior, a CTA, and integrates the page via a /faq route and Footer link. Existing FAQSection now imports shared data.

Changes

FAQ Page Feature

Layer / File(s) Summary
FAQ Data Module
frontend/src/data/faqs.js
Creates a shared faqs export containing an array of FAQ objects with id, category, q, and a fields.
FAQSection: use shared data & accessibility fixes
frontend/src/components/explore/FAQSection.jsx
Switches FAQSection to import faqs, uses item.id for key, adds per-item id/aria-controls/aria-expanded/aria-hidden with panel ids, replaces inline maxHeight collapse with CSS grid row transitions, and updates "View All FAQs" styling.
FAQPage component (hero, index, accordion, CTA)
frontend/src/pages/FAQPage.jsx
Implements FAQPage with supportTopics chips, openIdx state, per-item refs, toggleFaq with optional scroll-to behavior, left-side index buttons that call toggleFaq(index, true), accordion list keyed to openIdx with aria attributes, and a bottom CTA with a Go Back button.
Routing & integration into existing UI
frontend/src/App.jsx, frontend/src/components/shared/Footer.jsx
Replaces FAQSection import with FAQPage in App.jsx and registers a /faq route; adds a "FAQ" routed Link to the Footer's Platform list.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Router
  participant FAQPage
  participant FAQIndex
  participant Accordion
  Client->>Router: navigate to /faq
  Router->>FAQPage: render FAQPage
  FAQPage->>FAQIndex: build index from faqs
  FAQPage->>Accordion: render accordion items from faqs
  FAQIndex->>FAQPage: toggleFaq(index, scroll=true)
  FAQPage->>Accordion: open item (openIdx change) and requestAnimationFrame scroll
  Accordion->>Client: reveal answer panel (item.a)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Suggested labels

type:refactor

Poem

🐰 I hopped along the code-lined trail,
Found questions nested like a tale,
Chips to guide and answers to show,
I nudged the routes so readers know,
A friendly page where FAQs grow.

🚥 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 'feat: add dedicated FAQ page' directly and clearly summarizes the main change—creation of a new FAQ page component with routing.
Linked Issues check ✅ Passed The PR successfully addresses all core coding requirements from issue #31: implements a standalone FAQ page component, registers a /faq route, maintains clean/responsive layout, adds smooth accordion interactions, ensures accessibility, and preserves existing app flow.
Out of Scope Changes check ✅ Passed All changes are scoped to FAQ page creation and related routing. Footer FAQ link is a necessary routing connection; FAQSection refactoring supports data reusability without expanding scope beyond the issue.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@kunalverma2512
Copy link
Copy Markdown
Owner

@coderabbitai review this entire PR thoroughly and point out every area that can be improved, optimized, or made more logically consistent so the overall implementation becomes cleaner, stronger, and production-ready for the project.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== App.jsx ==="
cat frontend/src/App.jsx

echo ""
echo "=== FAQPage.jsx ==="
cat frontend/src/pages/FAQPage.jsx

echo ""
echo "=== FAQSection.jsx ==="
cat frontend/src/components/explore/FAQSection.jsx

echo ""
echo "=== Footer.jsx ==="
cat frontend/src/components/shared/Footer.jsx

echo ""
echo "=== faqs.js ==="
cat frontend/src/data/faqs.js

Length of output: 24720


@kunalverma2512, here is a thorough, file-by-file review of PR #80 covering correctness, logic, accessibility, UX, and production-readiness.


1. src/data/faqs.js — Shared Data Layer

A. Missing id field on each entry
Both FAQPage and FAQSection use item.q (question text) or index as the React key. If the question text ever changes or two questions share similar phrasing, React's reconciliation will break. Add a stable id:

export const faqs = [
  { id: "what-is-codelens", q: "What is CodeLens?", a: "..." },
  { id: "problem-solved",   q: "What problem does CodeLens solve?", a: "..." },
  { id: "data-privacy",     q: "Is my repository data private?", a: "..." },
  { id: "contribute",       q: "How can I contribute to CodeLens?", a: "..." },
];

B. Only 4 entries for a dedicated help-center page
A standalone /faq route with 4 questions feels sparse. The hero section implies categories ("Platform tracking", "Data privacy", "Open source", "Account setup"), but none of the FAQ objects carry a category field — the chips are completely disconnected from the data. Consider adding a category field and either filtering or grouping by it, or remove the misleading chips.


2. src/pages/FAQPage.jsx — Core New Component

A. Critical: State logic inconsistency between sidebar and accordion

The sidebar calls setOpenIdx(index) (always opens), but the accordion button toggles:

// Sidebar — always opens, never closes
onClick={() => setOpenIdx(index)}

// Accordion — toggles open/closed
onClick={() => setOpenIdx(isOpen ? null : index)}

Clicking the sidebar on an already-open item does nothing visible to the user, which is confusing. Unify the behavior:

// Sidebar — mirror the accordion toggle
onClick={() => setOpenIdx(openIdx === index ? null : index)}

B. openIdx initialized to 0 vs. null in FAQSection

FAQPage pre-opens the first item (useState(0)), while FAQSection starts with everything collapsed (useState(null)). There's no reason for this difference since they use the same data. Decide on one default and apply it consistently. For a help-center page, starting closed (null) is the more accessible convention (users should choose what they want to read).

C. Missing scroll-to-item when clicking the FAQ Index sidebar

Clicking a sidebar button updates openIdx but the viewport stays put. On mobile (where the sidebar stacks above the accordion), the selected item may be off-screen. Use useRef and scrollIntoView:

const itemRefs = useRef([]);

// in sidebar onClick:
onClick={() => {
  setOpenIdx(index);
  itemRefs.current[index]?.scrollIntoView({ behavior: "smooth", block: "start" });
}}

// on each accordion article:
ref={(el) => (itemRefs.current[index] = el)}

D. Accessibility gaps

Issue Location Fix
+ / - <span> not hidden from screen readers Accordion toggle button Add aria-hidden="true" to the span
No aria-controls on accordion buttons Each <button> Add aria-controls={item.id} and id={item.id} on the panel <div>
No id on answer panel <div> after button Add id={item.id}

Corrected button:

<button
  type="button"
  onClick={() => setOpenIdx(isOpen ? null : index)}
  className="..."
  aria-expanded={isOpen}
  aria-controls={`faq-panel-${item.id}`}
>
  <span className="...">{item.q}</span>
  <span className="text-4xl font-black leading-none" aria-hidden="true">
    {isOpen ? "−" : "+"}
  </span>
</button>
<div id={`faq-panel-${item.id}`} ...>

E. key={item.q} is fragile

Use the stable id proposed above: key={item.id}.

F. supportTopics array is hardcoded and disconnected from data

const supportTopics = [
  "Platform tracking",
  "Data privacy",
  "Open source",
  "Account setup",
];

These four labels don't map to any FAQ entry. Either derive them from a category field on the FAQ objects, or remove the chips to avoid implying filterable categories that don't work.

G. "Back To Explore" CTA always hardcodes /explore

If a user arrives at /faq from the Footer or any other path, clicking the CTA always sends them to /explore regardless of history. A simple improvement:

import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
// ...
<button onClick={() => navigate(-1)}>Go Back</button>

Or at minimum label it "Explore the Platform" to set correct expectations.

H. No document <title> for SEO

The page has no <title> update. Use the React Router <title> element (v7) or a <Helmet> equivalent:

// React Router v7
<title>FAQ – CodeLens</title>

3. src/components/explore/FAQSection.jsx

A. type="button" missing on accordion toggle

// ❌ current
<button onClick={() => toggle(index)} className="...">

// ✅ fix
<button type="button" onClick={() => toggle(index)} className="...">

Without type="button", if this component is ever nested in a <form>, clicking will submit the form.

B. key={index} is an anti-pattern

// ❌ current
<div key={index} ...>

// ✅ fix — once id is added to faqs.js
<div key={item.id} ...>

C. maxHeight: "500px" will clip long answers

style={{ maxHeight: isOpen ? "500px" : "0px" }}

If any answer exceeds ~500px of rendered height (especially on mobile), it will be silently truncated with no scroll or indicator. Use CSS Grid animation instead:

<div
  className="overflow-hidden transition-all duration-300 ease-in-out"
  style={{ maxHeight: isOpen ? "1000px" : "0px" }} // or use a ref-measured value
>

Or better, use a CSS Grid approach:

<div
  className={`grid transition-all duration-300 ease-in-out ${isOpen ? "grid-rows-[1fr]" : "grid-rows-[0fr]"}`}
>
  <div className="overflow-hidden">
    <p className="...">{item.a}</p>
  </div>
</div>

D. "border-3" is not a valid Tailwind CSS class

className="border-3 border-black ..."  // ❌ — no such class in default Tailwind config

Tailwind's border-width scale goes border (1px), border-2 (2px), border-4 (4px). border-3 silently produces no border. Change to border-2 or border-4.


4. src/App.jsx

A. Missing blank line before FAQPage import

Minor but inconsistent with the rest of the file's import style — the FAQPage import is placed directly before export default function App() without a blank line. Group it with the other page imports.

// ❌ current (at bottom, right before export)
import FAQPage from "./pages/FAQPage";
export default function App() {

// ✅ fix — move into the page imports block above
import TermsPage from "./pages/TermsPage";
import PrivacyPage from "./pages/PrivacyPage";
import FAQPage from "./pages/FAQPage";  // ← here
import NotFoundPage from "./pages/NotFoundPage";

5. src/components/shared/Footer.jsx

A. /codeforces is a protected route in the public Platform list

{ to: "/dashboard", label: "Dashboard" },
{ to: "/explore",   label: "Explore" },
{ to: "/faq",       label: "FAQ" },        // ✅ public — correct
{ to: "/codeforces", label: "Codeforces" }, // ⚠️ protected route

Unauthenticated users clicking "Codeforces" from the footer will be redirected to login, with no explanation. Either remove it from the footer, add an auth-aware wrapper, or add a tooltip/badge (e.g., "Login required"). This isn't introduced by this PR but is exposed now that you're auditing footer links.


Summary of Issues by Priority

Priority File Issue
🔴 High FAQPage.jsx Sidebar & accordion state logic inconsistency
🔴 High FAQSection.jsx border-3 is not a valid Tailwind class — no border rendered
🔴 High FAQSection.jsx maxHeight: 500px clips long answers
🟠 Medium FAQPage.jsx No scroll-to-item on sidebar click
🟠 Medium FAQPage.jsx supportTopics chips disconnected from FAQ data
🟠 Medium FAQPage.jsx Missing aria-controls / aria-hidden on toggle
🟠 Medium faqs.js No id field — fragile key usage in both components
🟠 Medium FAQSection.jsx Missing type="button" on accordion toggle
🟡 Low FAQPage.jsx openIdx initialized to 0 instead of null
🟡 Low FAQPage.jsx "Back To Explore" ignores navigation history
🟡 Low FAQPage.jsx No page <title> for SEO
🟡 Low App.jsx FAQPage import placement out of group
✅ Actions performed

Full review triggered.

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: 1

🧹 Nitpick comments (2)
frontend/src/pages/FAQPage.jsx (1)

80-99: ⚡ Quick win

Bind each toggle button to its panel with ARIA ids.

Add aria-controls on the button, and id + aria-labelledby on the panel; mark the symbol as decorative.

♿ Proposed fix
 {faqs.map((item, index) => {
   const isOpen = openIdx === index;
+  const panelId = `faq-panel-${index}`;
+  const buttonId = `faq-button-${index}`;

   return (
     <article
       key={item.q}
       className="border-4 border-black bg-white shadow-[8px_8px_0_0_rgba(0,0,0,1)]"
     >
       <button
         type="button"
         onClick={() => setOpenIdx(isOpen ? null : index)}
         className="flex w-full items-center justify-between gap-6 p-6 text-left sm:p-8"
         aria-expanded={isOpen}
+        aria-controls={panelId}
+        id={buttonId}
       >
         <span className="text-2xl font-black uppercase leading-tight tracking-tight sm:text-4xl">
           {item.q}
         </span>
-        <span className="text-4xl font-black leading-none">
+        <span className="text-4xl font-black leading-none" aria-hidden="true">
           {isOpen ? "-" : "+"}
         </span>
       </button>

       {isOpen && (
-        <div className="border-t-4 border-black px-6 py-6 sm:px-8">
+        <div
+          id={panelId}
+          aria-labelledby={buttonId}
+          className="border-t-4 border-black px-6 py-6 sm:px-8"
+        >
           <p className="max-w-3xl text-base font-bold leading-relaxed text-black sm:text-lg">
             {item.a}
           </p>
         </div>
       )}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/FAQPage.jsx` around lines 80 - 99, The button and panel
need ARIA linking: give the toggle button a unique id (e.g.,
`faq-button-${index}`) and add aria-controls pointing to the panel id; give the
panel a matching id (e.g., `faq-panel-${index}`) and aria-labelledby referencing
the button id; mark the decorative +/- span as aria-hidden="true". Update the
JSX around the toggle (where setOpenIdx, isOpen, index, item.q/item.a are used)
to generate these ids so each button-panel pair is uniquely bound.
frontend/src/data/faqs.js (1)

1-18: ⚡ Quick win

Add a stable id field to each FAQ item.

Using mutable text (q) as identity is actively causing issues across two components. FAQPage.jsx renders FAQs with key={item.q} at two locations (lines 56 and 77), and FAQSection.jsx uses key={index} at line 23. Both patterns are fragile: if question text is edited or the list is reordered, React loses component identity and state association. Add a stable id to each FAQ and consume it downstream.

♻️ Proposed change
 export const faqs = [
   {
+    id: "what-is-codelens",
     q: "What is CodeLens?",
     a: "CodeLens is a platform that helps developers track their coding progress across different platforms like Codeforces, LeetCode, and GitHub in one place.",
   },
   {
+    id: "problem-codelens-solves",
     q: "What problem does CodeLens solve?",
     a: "It brings all your coding activity into one place so you can understand your progress, stay consistent, and know what to improve next.",
   },
   {
+    id: "repository-data-privacy",
     q: "Is my repository data private?",
     a: "CodeLens only uses publicly available data from connected platforms and does not store any sensitive information.",
   },
   {
+    id: "how-to-contribute",
     q: "How can I contribute to CodeLens?",
     a: "You can contribute by solving issues, adding features, improving UI, or fixing bugs. Check the repository and start with beginner-friendly issues.",
   },
 ];
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/data/faqs.js` around lines 1 - 18, The faqs array items lack
stable IDs which breaks React identity in FAQPage.jsx (uses key={item.q}) and
FAQSection.jsx (uses key={index}); add a unique, stable id property to each
object in the exported faqs array (e.g., "id": "faq-1", etc.) and update the
consuming components to use key={item.id} instead of key={item.q} or key={index}
so component identity is preserved when text changes or items reorder.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/pages/FAQPage.jsx`:
- Around line 55-59: The button's onClick currently always sets open via
setOpenIdx(index) while the accordion header uses toggle logic; change the
button's handler to the same toggle pattern used by the accordion header by
calling setOpenIdx(prev => (prev === index ? null : index)) so it closes when
already open and opens otherwise; locate the onClick on the button that
references setOpenIdx and update it to use the toggle function, keeping openIdx
and index as the comparison keys.

---

Nitpick comments:
In `@frontend/src/data/faqs.js`:
- Around line 1-18: The faqs array items lack stable IDs which breaks React
identity in FAQPage.jsx (uses key={item.q}) and FAQSection.jsx (uses
key={index}); add a unique, stable id property to each object in the exported
faqs array (e.g., "id": "faq-1", etc.) and update the consuming components to
use key={item.id} instead of key={item.q} or key={index} so component identity
is preserved when text changes or items reorder.

In `@frontend/src/pages/FAQPage.jsx`:
- Around line 80-99: The button and panel need ARIA linking: give the toggle
button a unique id (e.g., `faq-button-${index}`) and add aria-controls pointing
to the panel id; give the panel a matching id (e.g., `faq-panel-${index}`) and
aria-labelledby referencing the button id; mark the decorative +/- span as
aria-hidden="true". Update the JSX around the toggle (where setOpenIdx, isOpen,
index, item.q/item.a are used) to generate these ids so each button-panel pair
is uniquely bound.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4c9c87f3-447a-453f-a027-cb1b819b5faa

📥 Commits

Reviewing files that changed from the base of the PR and between 47f72c6 and cb866f4.

📒 Files selected for processing (5)
  • frontend/src/App.jsx
  • frontend/src/components/explore/FAQSection.jsx
  • frontend/src/components/shared/Footer.jsx
  • frontend/src/data/faqs.js
  • frontend/src/pages/FAQPage.jsx

Comment thread frontend/src/pages/FAQPage.jsx Outdated
@saurabhhhcodes
Copy link
Copy Markdown
Author

Addressed the CodeRabbit review feedback in commit 8034de9.\n\nChanges made:\n- added stable FAQ id and category fields, then derived the support topic chips from FAQ data\n- made FAQ page/index toggle behavior consistent and defaulted the page to collapsed state\n- added sidebar scroll-to-item behavior for mobile/stacked layouts\n- added aria-controls, aria-expanded, and hidden decorative toggle icons\n- replaced fragile keys with stable IDs\n- fixed the landing FAQ accordion to avoid answer clipping with a grid-row transition\n- added missing type="button" and fixed invalid border-3 Tailwind class\n- moved the FAQ import into the page import group\n\nValidation:\n- npm run build\n- npx eslint src/data/faqs.js src/pages/FAQPage.jsx src/components/explore/FAQSection.jsx src/App.jsx\n- git diff --check

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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/explore/FAQSection.jsx`:
- Around line 48-55: The FAQ panel div with id `landing-faq-panel-${item.id}` is
kept mounted for animation but lacks hidden semantics; update that div to
include aria-hidden={isOpen ? "false" : "true"} (or aria-hidden={!isOpen}) and
add accessible region attributes such as role="region" and aria-labelledby
pointing to the question toggle (e.g., `landing-faq-button-${item.id}`), and
ensure the toggle button that controls `isOpen` has the matching id so screen
readers know which heading labels the region.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5551b5b4-74d0-4685-bb30-0029b2c16390

📥 Commits

Reviewing files that changed from the base of the PR and between cb866f4 and 8034de9.

📒 Files selected for processing (4)
  • frontend/src/App.jsx
  • frontend/src/components/explore/FAQSection.jsx
  • frontend/src/data/faqs.js
  • frontend/src/pages/FAQPage.jsx

Comment thread frontend/src/components/explore/FAQSection.jsx
@saurabhhhcodes
Copy link
Copy Markdown
Author

Pushed 712bea4 to address the remaining CodeRabbit accessibility note.

Updated the landing FAQ accordion so each animated panel is now explicitly bound to its toggle:

  • stable button and panel ids
  • aria-controls on the toggle
  • role="region" and aria-labelledby on the panel
  • aria-hidden follows the collapsed/open state

Validation:

  • node node_modules/vite/bin/vite.js build
  • node node_modules/eslint/bin/eslint.js src/components/explore/FAQSection.jsx
  • git diff --check

@kunalverma2512
Copy link
Copy Markdown
Owner

@coderabbitai please check whether @saurabhhhcodes resolved every level issues you mentioned before or something else
also again recheck everything so that we may be confident before merging

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== App.jsx ==="
cat frontend/src/App.jsx

echo ""
echo "=== FAQPage.jsx ==="
cat frontend/src/pages/FAQPage.jsx

echo ""
echo "=== FAQSection.jsx ==="
cat frontend/src/components/explore/FAQSection.jsx

echo ""
echo "=== Footer.jsx ==="
cat frontend/src/components/shared/Footer.jsx

echo ""
echo "=== faqs.js ==="
cat frontend/src/data/faqs.js

Length of output: 26164


@kunalverma2512, here is the full verification of every item @saurabhhhcodes addressed. 11 of 12 original issues are resolved, and I spotted one new accessibility issue introduced in the latest commit.


Verification Report

✅ All High-Priority Issues — Fixed

Issue Status
🔴 Sidebar & accordion state inconsistency ✅ Both now call toggleFaq() which toggles uniformly
🔴 border-3 invalid Tailwind class ✅ Changed to border-2
🔴 maxHeight: 500px clips long answers ✅ Replaced with CSS grid grid-rows-[1fr/0fr] transition

✅ All Medium-Priority Issues — Fixed

Issue Status
🟠 No scroll-to-item on sidebar click itemRefs + scrollIntoView via requestAnimationFrame
🟠 supportTopics chips disconnected from data ✅ Now derived: [...new Set(faqs.map(f => f.category))]
🟠 Missing aria-controls / aria-hidden ✅ Both present on FAQPage and FAQSection toggles
🟠 No stable id in faqs.js ✅ Each entry has id and category
🟠 Missing type="button" on FAQSection toggle ✅ Added

✅ / ⚠️ Low-Priority Issues — Mostly Fixed

Issue Status
🟡 openIdx initialized to 0 ✅ Changed to null
🟡 No <title> for SEO <title>FAQ - CodeLens</title> present
🟡 FAQPage import out of group ✅ Now correctly placed before NotFoundPage
🟡 "Back To Explore" hardcodes /explore ⚠️ Still to="/explore" — not fixed, but low impact

🆕 New Issue Found — Medium Priority

FAQPage.jsx: aria-controls points to a conditionally-rendered panel

The answer panel in FAQPage is rendered only when isOpen is true:

{isOpen && (
  <div id={`faq-panel-${item.id}`} ...>  // ← Only exists in DOM when open
    ...
  </div>
)}

But the toggle button always has:

aria-controls={`faq-panel-${item.id}`}

When the panel is collapsed, the id it references doesn't exist in the DOM, so screen readers cannot find or announce the controlled region. FAQSection.jsx already handles this correctly by always rendering the panel and using grid-rows-[0fr] to collapse it visually.

The fix is to adopt the same pattern used in FAQSection.jsx:

<article key={item.id} ref={(el) => { itemRefs.current[index] = el; }} className="...">
  <button
    type="button"
    onClick={() => toggleFaq(index)}
    aria-expanded={isOpen}
    aria-controls={`faq-panel-${item.id}`}
    className="..."
  >
    <span className="...">{item.q}</span>
    <span aria-hidden="true">{isOpen ? "−" : "+"}</span>
  </button>

  {/* Always in DOM — collapsed via CSS grid, not conditional rendering */}
  <div
    id={`faq-panel-${item.id}`}
    role="region"
    aria-labelledby={`faq-btn-${item.id}`}
    aria-hidden={!isOpen}
    className={`grid transition-all duration-300 ease-in-out border-t-4 border-black ${
      isOpen ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
    }`}
  >
    <div className="overflow-hidden">
      <p className="px-6 py-6 sm:px-8 max-w-3xl text-base font-bold leading-relaxed text-black sm:text-lg">
        {item.a}
      </p>
    </div>
  </div>
</article>

Summary for Merge Decision

The PR is in good shape overall — all high and medium issues from the original review are resolved. Before merging, it's worth asking @saurabhhhcodes to fix the aria-controls / conditional rendering issue above (medium severity, screen-reader regression introduced in the latest accessibility commit). The "Back To Explore" link is low priority and can be deferred if needed.

@kunalverma2512
Copy link
Copy Markdown
Owner

@coderabbitai what do you mean by hardcoding /explore
if that not then whats better ?

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Tip

For best results, initiate chat on the files or code changes.

@kunalverma2512 — great question! Here's the simple explanation:

"Hardcoding /explore" means the "Back To Explore" button in FAQPage.jsx always navigates to /explore, no matter how the user arrived at the FAQ page:

// ❌ Hardcoded — always goes to /explore, even if user came from /dashboard or /faq via Footer
<Link to="/explore">Back To Explore</Link>

The problem: If a user clicks "FAQ" from the Footer (while on /dashboard), and then clicks "Back To Explore" — they'll be sent to /explore instead of back to /dashboard where they came from. It's unexpected.

The better alternative — navigate(-1):

import { useNavigate } from "react-router-dom";

const navigate = useNavigate();

// ✅ Goes back to wherever the user came from
<button type="button" onClick={() => navigate(-1)}>
  ← Go Back
</button>

This uses the browser's history stack, so the user always returns to the page they were on before — whether that was /explore, /dashboard, or anywhere else.

If you want to keep it simple and always go to /explore, that's fine too — just relabel the button to something like "Explore the Platform" instead of "Back To Explore", so users aren't misled into thinking it's a back button. This was flagged as low priority, so it won't block the merge either way.

ʕ •ᴥ•ʔ

@kunalverma2512
Copy link
Copy Markdown
Owner

@saurabhhhcodes implement the better alternative that coderabbitai mentioned

put neccessary screenshot of final result and also put a video also showcasing result (via drive link)

@saurabhhhcodes
Copy link
Copy Markdown
Author

Implemented the requested follow-up in 30c5e49.

What changed:

  • Replaced the hardcoded /explore footer CTA with navigate(-1), so the FAQ page now returns the user to the page they came from.
  • Renamed the CTA to Go Back so the action matches the browser-history behavior.
  • Also fixed the still-valid accessibility issue from CodeRabbit by keeping each FAQ answer panel mounted and collapsing it with grid rows, so aria-controls always points to an existing role="region" panel.

Validation:

  • Targeted lint passed for the touched FAQ files:
    • node node_modules/.bin/eslint src/pages/FAQPage.jsx src/components/explore/FAQSection.jsx src/data/faqs.js
  • Production build passed:
    • node node_modules/.bin/vite build
  • git diff --check passed.
  • Local visual smoke test passed on /faq at desktop 1440x1200 and mobile 390x1200 viewports.
  • CodeRabbit is green on the latest commit.

The PR should be ready for your review again.

@saurabhhhcodes
Copy link
Copy Markdown
Author

Pushed one more small polish commit: c9b6285.

What changed:

  • contained the FAQ page to viewport width so the standalone FAQ layout does not inherit wider document/header overflow on mobile
  • stacked the topic chips on small screens and reduced mobile shadow offset slightly
  • allowed FAQ index labels to wrap safely on narrow screens

Validation run after this commit:

  • node node_modules/eslint/bin/eslint.js src/pages/FAQPage.jsx src/components/explore/FAQSection.jsx src/data/faqs.js src/App.jsx
  • node node_modules/vite/bin/vite.js build
  • git diff --check
  • Chrome headless visual smoke test for /faq at desktop 1440x1200 and mobile 430x1200

CodeRabbit was already green on the prior head, and this latest change is scoped to responsive containment only. The PR should be ready for maintainer review again.

@saurabhhhcodes
Copy link
Copy Markdown
Author

Quick follow-up: this PR is still clean and mergeable from my side after the last polish commit. Since the PR already carries the GSSoC labels and mentor tag, please merge it when you get a chance if there is no further feedback.

@kunalverma2512
Copy link
Copy Markdown
Owner

@saurabhhhcodes attach screen shot plus working site video for that page and also show browser console while opring faq page

@saurabhhhcodes
Copy link
Copy Markdown
Author

Hi! Checking back on this PR since the branch is still cleanly mergeable on GitHub. If there are any requested adjustments, I can turn them around quickly.

@kunalverma2512
Copy link
Copy Markdown
Owner

@coderabbitai

Please perform one final deep and complete review of this PR from a production-quality perspective before merge.

Do a holistic review of the entire implementation and verify whether this contribution is genuinely clean, professional, scalable, and well integrated with the existing CodeLens codebase.

Please specifically review:

  • Whether the dedicated FAQ page architecture is logically designed and maintainable
  • Whether the implementation follows existing project structure, design system, responsiveness, and UI/UX consistency
  • Whether the reusable FAQ data layer is implemented properly without duplication or future maintainability issues
  • Whether the routing, navigation flow, and browser history behavior are correct and production-ready
  • Whether all accessibility improvements are now correctly implemented without regressions
  • Whether the accordion logic, animations, state handling, and responsive behavior are optimized and reliable
  • Whether there are still any edge cases, accessibility issues, UI breaking cases, overflow problems, hydration/rendering concerns, or performance issues remaining
  • Whether the implementation is fully compatible with the rest of the frontend architecture and shared components
  • Whether any unnecessary complexity, overengineering, or inconsistent logic still exists
  • Whether the mobile responsiveness and viewport containment fixes are properly handled across different screen sizes
  • Whether semantic HTML, ARIA bindings, keyboard accessibility, and screen reader compatibility are now correctly implemented
  • Whether there are any hidden issues that may affect future scaling of the FAQ system

Also verify:

  1. Did the contributor properly resolve every issue and suggestion raised in previous reviews?
  2. Is the final implementation truly merge-ready and production-quality?
  3. Is this contribution professionally implemented according to modern frontend engineering standards?
  4. Are there any remaining improvements or risks before merge?

Please review the actual final state carefully instead of only checking incremental diffs so we can confidently decide whether this PR should be merged.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 24, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== App.jsx ==="
cat frontend/src/App.jsx

echo ""
echo "=== FAQPage.jsx ==="
cat frontend/src/pages/FAQPage.jsx

echo ""
echo "=== FAQSection.jsx ==="
cat frontend/src/components/explore/FAQSection.jsx

echo ""
echo "=== Footer.jsx ==="
cat frontend/src/components/shared/Footer.jsx

echo ""
echo "=== faqs.js ==="
cat frontend/src/data/faqs.js

echo ""
echo "=== Project structure around pages ==="
fd --type f --extension jsx --extension js src/pages
fd --type f --extension jsx --extension js src/data

echo ""
echo "=== Check for duplicate FAQ data ==="
rg -n "question\|answer\|faq\|FAQ" --type js --type jsx -g '!node_modules' -g '!*.test.*'

echo ""
echo "=== Check all imports of faqs.js ==="
rg -n "from.*faqs\|require.*faqs" --type js --type jsx

echo ""
echo "=== Check route setup ==="
rg -n "faq\|FAQ" frontend/src/App.jsx

echo ""
echo "=== Check keyboard accessibility - any onKeyDown handlers ==="
rg -n "onKeyDown\|onKeyPress\|onKeyUp\|tabIndex\|role=" frontend/src/pages/FAQPage.jsx
rg -n "onKeyDown\|onKeyPress\|onKeyUp\|tabIndex\|role=" frontend/src/components/explore/FAQSection.jsx

echo ""
echo "=== Check for any console.log left in ==="
rg -n "console\." frontend/src/pages/FAQPage.jsx frontend/src/components/explore/FAQSection.jsx frontend/src/data/faqs.js

echo ""
echo "=== Check Tailwind classes used in FAQ files ==="
rg -n "border-3\|text-\|bg-\|grid-rows\|overflow" frontend/src/pages/FAQPage.jsx frontend/src/components/explore/FAQSection.jsx

echo ""
echo "=== Check aria attributes ==="
rg -n "aria-" frontend/src/pages/FAQPage.jsx frontend/src/components/explore/FAQSection.jsx

echo ""
echo "=== Check useNavigate usage ==="
rg -n "navigate\|useNavigate\|Link to" frontend/src/pages/FAQPage.jsx

echo ""
echo "=== Check if panels always mounted in FAQPage ==="
rg -n "isOpen &&\|isOpen ?\|{isOpen" frontend/src/pages/FAQPage.jsx

echo ""
echo "=== Look at existing page components for style consistency ==="
cat frontend/src/pages/ExplorePage.jsx 2>/dev/null || echo "ExplorePage.jsx not found"

echo ""
echo "=== Check package.json for React Router version ==="
cat frontend/package.json | python3 -c "import json,sys; d=json.load(sys.stdin); deps={**d.get('dependencies',{}), **d.get('devDependencies',{})}; print({k:v for k,v in deps.items() if 'react' in k.lower() or 'router' in k.lower() or 'vite' in k.lower()})"

Length of output: 30148


@kunalverma2512, here is the final, holistic production-readiness review of PR #80 in its current state, covering every dimension you listed.


✅ Issues from All Previous Reviews — Resolution Status

# Issue Status
1 Sidebar/accordion state inconsistency ✅ Fixed — unified toggleFaq()
2 border-3 invalid Tailwind class ✅ Fixed → border-2
3 maxHeight: 500px clips answers ✅ Fixed → CSS grid grid-rows-[1fr/0fr]
4 No scroll-to-item on sidebar click ✅ Fixed — itemRefs + scrollIntoView via rAF
5 supportTopics disconnected from data ✅ Fixed — derived from faqs.map(f => f.category)
6 Missing aria-controls / aria-hidden ✅ Fixed on both FAQPage and FAQSection
7 No stable id in faqs.js ✅ Fixed — each entry has id and category
8 Missing type="button" ✅ Fixed in FAQSection
9 openIdx initialized to 0 ✅ Fixed → null
10 No <title> for SEO ✅ Fixed — <title>FAQ - CodeLens</title> (valid React 19 metadata hoisting)
11 FAQPage import out of group ✅ Fixed — now between PrivacyPage and NotFoundPage
12 aria-controls pointing to conditionally-rendered panel ✅ Fixed — panels always mounted, collapsed via grid-rows-[0fr]
13 Hardcoded /explore in CTA ✅ Fixed → navigate(-1)

🔍 Final Deep Review — Remaining Findings

🟠 Medium — navigate(-1) Has No Fallback

When a user lands directly on /faq (from a bookmark, a shared link, a Google search, or a new tab), window.history.length will be 1 and navigate(-1) will silently do nothing or navigate outside the app entirely. A minimal, production-safe fix:

const handleGoBack = () => {
  if (window.history.length > 1) {
    navigate(-1);
  } else {
    navigate("/explore");
  }
};

// Then in JSX:
<button type="button" onClick={handleGoBack} className="...">
  Go Back
</button>

🟠 Medium — CTA Section Copy Conflicts with Button Label

The bottom section reads "Still Curious? / Explore The Platform." but the action button says "Go Back". These are semantically opposite — one implies forward exploration, the other implies backward navigation. This will confuse users. Either:

  • Change the heading to "Done Exploring?" / "All Caught Up?" to match "Go Back", or
  • Change the button to "Explore The Platform" (which would justify keeping navigate('/explore') instead of navigate(-1))

🟡 Low — width: 100vw May Cause Horizontal Overflow on Windows/Linux

// FAQPage.jsx – line 24
<main style={{ width: "100vw", maxWidth: "100vw" }} className="overflow-x-hidden bg-white text-black">

On Windows and Linux where the browser renders a visible scrollbar (~15–17px), 100vw includes the scrollbar width, but the layout width does not. This can create a brief horizontal scrollbar or layout shift. The overflow-x-hidden on the <main> hides internal overflow but doesn't prevent the element itself from overflowing its parent. The safer approach:

<main className="w-full overflow-x-hidden bg-white text-black">

w-full (100%) is relative to the parent, which respects the scrollbar gutter. This is typically how other pages in the project are structured (e.g., ExplorePage uses w-full).


🟡 Low — Only 3 Unique Topic Chips, Leaving Odd Desktop Grid

faqs.js has two entries with category: "Platform tracking", meaning [...new Set(...)] yields only 3 unique categories: "Platform tracking", "Data privacy", "Open source". The chip grid is sm:grid-cols-2, so on tablet/desktop the 3rd chip renders alone in the second row, which looks unbalanced. Consider either:

  • Adding a 4th category (e.g., "Open source" → "Contributing"), or
  • Using grid-cols-3 for exactly 3 chips

🟡 Low — requestAnimationFrame Scroll May Fire Before Paint

// FAQPage.jsx
if (shouldScroll) {
  window.requestAnimationFrame(() => {
    itemRefs.current[index]?.scrollIntoView({ behavior: "smooth", block: "start" });
  });
}

requestAnimationFrame fires before the browser's next paint, but the React re-render (which expands the grid row) may not have committed to the DOM yet at that point. On slower devices the scroll will target the element before it has expanded, potentially landing short. A double-rAF or setTimeout(fn, 0) is more reliable:

requestAnimationFrame(() => requestAnimationFrame(() => {
  itemRefs.current[index]?.scrollIntoView({ behavior: "smooth", block: "start" });
}));

🟡 Low — Content Depth for a Dedicated FAQ Page

The /faq route has only 4 questions. For a dedicated standalone page (vs. an inline section), this feels thin and may not justify the navigation entry. This is a product/content decision — the implementation is technically sound but the page will benefit from more entries as the platform grows.


✅ Everything Else Checks Out

Area Verdict
Architecture / file layout ✅ Clean — data in /data, page in /pages, component in /components/explore
Route registration ✅ Public /faq route, correctly ordered before * wildcard
Data layer reuse ✅ Single faqs.js source, consumed by both FAQPage and FAQSection — no duplication
Accordion state logic ✅ Correct toggle, collapsed by default, functional setState update pattern
Stable React keys item.id used everywhere, no index keys
Accessibility (ARIA) aria-expanded, aria-controls, aria-labelledby, aria-hidden, role="region" — all correct and consistent
aria-controls DOM integrity ✅ Panels always mounted, collapsed visually only
ID namespacing FAQSection uses landing-faq-* prefix to avoid collision with FAQPage's faq-* IDs
Animations ✅ CSS grid transition — smooth, no JS height measurement needed
Mobile responsiveness break-words on sidebar labels, stacked chips on mobile, sticky sidebar on desktop
<title> SEO ✅ Valid React 19 metadata element, hoisted to <head>
navigate(-1) ✅ Correct behavior — but needs fallback (see Medium issue above)
Import grouping ✅ Correct
No console.log ✅ Clean
border-3 ✅ Replaced with border-2
type="button" ✅ Present on all toggle buttons
Footer /faq link ✅ Added and routes correctly
React 19 + RR v7 compatibility ✅ No deprecated APIs used

Merge Verdict

This PR is mergeable. All high and medium issues from the original review have been cleanly resolved. The two remaining medium items (navigate(-1) fallback and the CTA copy mismatch) are UX polish items — the navigate(-1) fallback in particular is worth a quick fix before merge since a user arriving via a direct link will get a broken "Go Back" button. The low-priority items can be addressed in a follow-up.

Recommended before merge:

  1. 🟠 Add the navigate(-1) fallback (2-line fix)
  2. 🟠 Fix the CTA section heading to match the "Go Back" button label

Can be deferred to a follow-up PR:
3. 🟡 Replace width: 100vw with w-full
4. 🟡 Double-rAF scroll timing
5. 🟡 4th FAQ category / more entries

@saurabhhhcodes
Copy link
Copy Markdown
Author

Got it — I’m working on the proof bundle you asked for for the FAQ page flow, including the screenshot/browser-console check, and I’ll add that as a follow-up on this PR.

@saurabhhhcodes
Copy link
Copy Markdown
Author

Pushed one more polish commit on this PR just now. It addresses the latest review points by adding a safe fallback for the Go Back action, aligning the CTA copy with that behavior, switching the page container from 100vw to w-full, and delaying the sidebar scroll by an extra requestAnimationFrame so the expanded panel has committed before scrolling. I also re-ran ESLint on frontend/src/pages/FAQPage.jsx and git diff --check locally after the change.

@saurabhhhcodes
Copy link
Copy Markdown
Author

Quick follow-up here — I already pushed the FAQ polish pass requested in review. The main remaining ask on my side is visual proof once the local frontend runner cooperates again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create a Dedicated FAQ Page with Structured Layout and Modern UI

2 participants