Skip to content

Fix/UI accessibility and navigation - #79

Open
raj-aryan-official wants to merge 26 commits into
DjedAlliance:mainfrom
raj-aryan-official:fix/ui-accessibility-and-navigation
Open

Fix/UI accessibility and navigation#79
raj-aryan-official wants to merge 26 commits into
DjedAlliance:mainfrom
raj-aryan-official:fix/ui-accessibility-and-navigation

Conversation

@raj-aryan-official

@raj-aryan-official raj-aryan-official commented Mar 30, 2026

Copy link
Copy Markdown

Addressed Issues:
Fixes #78

Additional Notes:
This PR focuses on improving usability, accessibility, and overall navigation.

An About section has been added to the main page to give users a clear understanding of StablePay. The section is responsive and aligned with the existing design.

The navbar has been updated to include an About link for both desktop and mobile. Navigation links have been cleaned up and now scroll smoothly to the correct sections.

Basic accessibility improvements have been made to the mobile menu, including ARIA attributes and better interaction handling.

A small issue in the Button component was fixed where decorative elements could block clicks.

Some performance improvements were made by reducing unnecessary animations and limiting heavy event listeners where possible.

The codebase was also cleaned up by removing unused or confusing parts.

All changes were tested locally and the build completes without errors.

Checklist:
[x] This PR addresses a single improvement
[x] Code follows the project's style and conventions
[x] Changes tested locally
[x] No new warnings or errors

Happy to make further improvements if needed.

Summary by CodeRabbit

  • New Features

    • Theme toggle with persistent preference, system-detection, reduced-motion respect, and class-based dark mode
    • Mobile navigation drawer with accessible keyboard/focus handling
    • New About section describing use cases and workflow
    • Smooth in-page scrolling and social share actions (Twitter, LinkedIn, GitHub)
    • Added MIT license
  • Improvements

    • Expanded metadata for richer previews/SEO and theme color
    • Full site-wide dark/light theming and transition support
    • Real SVG logos in ticker and refined motion/reduced-motion behavior

@coderabbitai

coderabbitai Bot commented Mar 30, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds an About section, a client-side ThemeToggle with persistent dark-mode via a DOM class, smooth in-page navigation and an accessible mobile drawer, refactors Button props, moves animated backgrounds into dedicated motion layers with reduced-motion support, expands metadata/SEO, enables Tailwind class-based dark mode, and adds an MIT license file.

Changes

Cohort / File(s) Summary
License & Config
License.md, tailwind.config.ts
Added MIT license file; enabled Tailwind dark mode via darkMode: 'class'.
App layout & metadata
src/app/layout.tsx
Replaced Fraunces font, made body theme-aware (bg-white / dark:bg-black), expanded metadata (keywords, authors, openGraph, twitter, robots), exported viewport, and inlined a script to initialize dark class from localStorage/prefers-color-scheme.
Page composition
src/app/page.tsx
Imported and renders new About section in Home page composition; added JSDoc comment.
Components: Button
src/components/Button.tsx
Introduced ButtonProps (HTML button attributes), destructured props, merged styles (default boxShadow), forwarded rest props, and set decorative overlays to pointer-events-none.
Components: ThemeToggle
src/components/ThemeToggle.tsx
Added new client ThemeToggle component: mounts guard, reads/writes localStorage.theme, toggles document.documentElement dark class, uses framer-motion icons, and avoids hydration mismatch.
Header & Navigation
src/sections/Header.tsx
Converted to client component; added mobile drawer (focus trap, ESC, restore focus), smooth-scroll handler for nav links, integrated ThemeToggle, improved accessibility and ARIA attributes.
Footer & links
src/sections/Footer.tsx
Converted to client; updated logo import/path, dark-mode visuals, anchors now smooth-scroll to section IDs (preventDefault + scrollIntoView), made GitHub/Twitter/LinkedIn outbound links and added share links; adjusted responsive visibility.
New About & content sections
src/sections/About.tsx, src/sections/Hero.tsx, src/sections/Features.tsx, src/sections/CallToAction.tsx, src/sections/LogoTicker.tsx
Added About section; moved animated star/backgrounds into inner motion layers; added reduced-motion gating; refactored FeatureTab to button with aria-pressed; added useRelativeMousePosition hook; updated theming classes and transitions; LogoTicker now renders SVG logos and applies color transitions.

Sequence Diagrams

sequenceDiagram
    actor User
    participant ThemeToggle as ThemeToggle Component
    participant Local as localStorage
    participant DOM as document.documentElement
    participant Icon as Icon (Sun/Moon)

    User->>ThemeToggle: Click toggle
    ThemeToggle->>ThemeToggle: setState(newTheme)
    ThemeToggle->>Local: localStorage.setItem("theme", newTheme)
    ThemeToggle->>DOM: add/remove "dark" class
    ThemeToggle->>Icon: animate icon (framer-motion)
    DOM->>User: CSS dark: variants apply
Loading
sequenceDiagram
    actor User
    participant Header as Header NavLink/Button
    participant Handler as handleSmoothScroll
    participant DOM as targetSection (e.g., "#developers")
    participant View as Browser viewport

    User->>Header: Click nav link
    Header->>Handler: preventDefault() + compute id
    Handler->>DOM: document.getElementById(id)
    Handler->>View: scrollIntoView({ behavior: "smooth" })
    View->>User: animated scroll to section
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • Tanya-ruby

Poem

🐰 I hopped through lines of day and night,
I toggled themes to get the contrast right,
I placed an About where newcomers land,
I smoothed the scroll with a gentle hand,
StablePay shines in both the sun and night ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Several changes exceed the scope of issue #78: removed Fraunces font, added comprehensive metadata/SEO fields, added theme toggle with localStorage, added dark mode class support to Tailwind, and added social sharing links (Twitter/LinkedIn) to Footer. Remove out-of-scope changes: revert Fraunces removal, metadata expansions, theme toggle implementation, Tailwind dark mode configuration, and social sharing links. Keep only About section, navigation fixes, mobile menu accessibility, and Button component fixes.
✅ 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 'Fix/UI accessibility and navigation' directly aligns with the main objectives: improving UI accessibility and navigation through an About section, smooth scrolling, mobile menu enhancements, and button fixes.
Linked Issues check ✅ Passed The PR successfully addresses all coding requirements from issue #78: adds About section component with responsive design, implements smooth scrolling navigation, improves mobile menu with ARIA attributes, fixes Button component event handling, and adds theme toggle for accessibility.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 12

Caution

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

⚠️ Outside diff range comments (2)
src/sections/LogoTicker.tsx (1)

27-37: ⚠️ Potential issue | 🟡 Minor

Treat the looping ticker as decorative.

The ticker renders items twice for seamless looping (lines 38–56), so screen readers will announce duplicate partner names. The static heading already communicates this information, so the animated strip should be hidden from assistive tech.

Suggested change
           <motion.div
+            aria-hidden="true"
             className="flex flex-none gap-8 sm:gap-14 pr-8 sm:pr-14"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/sections/LogoTicker.tsx` around lines 27 - 37, The animated ticker (the
motion.div that renders the looping partner strip with className "flex flex-none
gap-8..." and animate/transition props) is decorative and duplicates content, so
add accessibility attributes to hide it from assistive tech; update the
motion.div (or its immediate container) to include aria-hidden="true" and/or
role="presentation" so screen readers ignore the animated strip while the static
heading remains for users of assistive technologies.
src/app/layout.tsx (1)

74-80: ⚠️ Potential issue | 🟠 Major

Dark-mode users will still get a light-theme flash on first paint.

The initial HTML here is rendered without a dark class, and src/components/ThemeToggle.tsx:15-32 only applies that class in a client effect after mount. Seed the theme on <html> before hydration instead of relying on the toggle component.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/layout.tsx` around lines 74 - 80, The html element in
src/app/layout.tsx is rendered without a dark class so users see a light flash
before the client-side ThemeToggle applies the class; add a small inline script
in layout.tsx (placed before the hydrated body content) that runs immediately to
read the saved theme (e.g., from localStorage) or prefers-color-scheme and
synchronously add/remove the "dark" class on document.documentElement, mirroring
the logic used in ThemeToggle.tsx, so the initial HTML already has the correct
theme before hydration.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/ThemeToggle.tsx`:
- Around line 15-32: The initial theme is only applied inside ThemeToggle's
useEffect after mount causing a flash; fix by applying the theme synchronously
before hydration: extract the logic that reads localStorage.getItem('theme') and
window.matchMedia('(prefers-color-scheme: dark)') into a synchronous initializer
(or inline script in the document head) that computes initialTheme and
immediately mutates document.documentElement.classList (add/remove 'dark') and
sets localStorage if needed, then have ThemeToggle's useEffect (and state
setters setMounted/setTheme) only mirror that already-applied initial value
rather than being the first place that toggles the class. Ensure references to
setTheme, setMounted, the existing useEffect blocks, and
document.documentElement are preserved and consistent with the new pre-hydration
initializer.
- Around line 46-54: The ThemeToggle button in ThemeToggle.tsx currently omits
type and accessible state attributes; update the button element used by
toggleTheme to include type="button" to avoid implicit form submission, add
aria-pressed={isDark} to expose the current toggle state, and make the
aria-label dynamic (e.g., when isDark is true set label to "Switch to light
theme", otherwise "Switch to dark theme") so screen readers convey the action.

In `@src/sections/About.tsx`:
- Around line 8-9: The section with id "about" is missing the anchor offset
class used elsewhere; update the section element (the <section id="about"
className="..."> in About.tsx) to include the same offset utility (e.g., add
"scroll-mt-24" alongside existing classes) so the About heading aligns
consistently with the fixed header during smooth scrolling.

In `@src/sections/CallToAction.tsx`:
- Line 68: The developers section (element with id="developers" and
ref={sectionRef} in the CallToAction component) is missing the same scroll
offset used elsewhere; add the utility class "scroll-mt-24" to its className
(alongside the existing "py-12 sm:py-16 md:py-24") so in-page navigation and
scrollIntoView({ block: 'start' }) won't hide the heading under the sticky
header.
- Around line 35-41: The current throttled handler schedules a new
requestAnimationFrame for every mousemove, allowing multiple RAF callbacks and
no cancellation on unmount; change the implementation around the throttled
function and updateMousePosition usage to store a single pending RAF id and the
latest MouseEvent (e.g., keep let rafId: number | null = null and let
latestEvent: MouseEvent | null = null at component scope), have throttled assign
latestEvent and only call requestAnimationFrame when rafId is null, inside the
RAF callback call updateMousePosition(latestEvent!), clear rafId and
latestEvent, and in the cleanup (the return) both remove the 'mousemove'
listener and cancel any pending frame via cancelAnimationFrame(rafId) to avoid
stale updates after unmount.

In `@src/sections/Features.tsx`:
- Around line 69-70: The prefersReduced constant is computed but unused so
reduced-motion preferences are being ignored; update the motion props (e.g.,
whileHover, whileTap, rotate, and any opacity/scale animate/initial/transition
props) on the motion elements in Features.tsx to check prefersReduced and pass
empty objects or omit the prop when prefersReduced is true (e.g.,
whileHover={prefersReduced ? {} : { scale: 1.05 }} and similarly for whileTap,
rotate and the animated opacity/scale configs) so animations are disabled for
users who prefer reduced motion.
- Around line 72-78: Replace the non-semantic clickable element motion.div with
a semantic motion.button to restore keyboard accessibility and expose selection
state; update the element used at the location where motion.div is rendered (the
element using tabRef, onClick={props.onClick}, and className) to motion.button,
add type="button" and aria-pressed={props.selected}, ensure the existing ref
(tabRef) is forwarded to the button, and keep the same className and motion
props (whileHover/whileTap) so behavior and styling remain unchanged.

In `@src/sections/Footer.tsx`:
- Around line 50-58: In the Footer component update the YouTube anchor (the <a>
wrapping YTSocial) so its href matches the aria-label: either replace the
current "https://www.youtube.com" with the actual Djed Alliance channel URL (or
playlist) or remove the entire YouTube anchor and YTSocial element if no channel
exists; ensure the change is made in the Footer component where the YTSocial JSX
is rendered so aria-label and href remain consistent.

In `@src/sections/Header.tsx`:
- Line 45: Header mounts two ThemeToggle components which each maintain their
own local theme state, causing desynced toggles; fix by using a single shared
theme source or a single toggle instance. Either lift theme state up (create a
theme state + setter in the Header parent or a layout-level context) and pass it
into ThemeToggle (or refactor ThemeToggle to consume a ThemeContext), or render
only one ThemeToggle instance and move it into a common parent so both places
read the same state; update references to ThemeToggle in Header to use the
shared state or the single instance to keep both controls in sync.
- Around line 39-40: The "Integration Docs" anchor currently links to
'#features' incorrectly; update the anchor for the "Integration Docs" element
(the <a> using onClick={(e) => handleSmoothScroll(e, 'features')} and the
duplicate at the second occurrence) to point to the correct target (e.g., 'docs'
or the real section id) or remove the menu item until the section exists; modify
the second argument passed to handleSmoothScroll for the "Integration Docs"
anchors (and the href) to the actual section id (for example 'docs' or
'integration-docs') so both nav variants use the correct target.
- Around line 65-69: The drawer at id="mobile-drawer" is declared as a dialog
but lacks an accessible name, focus management, an Escape handler, and focus
trapping; update the component to (1) provide an accessible name via
aria-labelledby on the drawer pointing to a visible heading or aria-label on the
container (or give the Logo/heading an id and reference it), (2) move focus into
the drawer when opening (capture document.activeElement before open, use a ref
to focus the container or first focusable element in the drawer), (3) trap
keyboard focus inside the drawer while open (implement a simple focus trap by
handling Tab/Shift+Tab or use a small utility), (4) close the drawer on Escape
by adding a keydown handler that calls setOpen(false), and (5) restore focus to
the previously focused element when closing; reference id "mobile-drawer", the
setOpen setter, and the Close button/Logo/heading elements when adding refs/ids.

In `@src/sections/Hero.tsx`:
- Around line 17-18: The detected prefersReduced variable is unused so
animations (starfield and the three ring components rendered as motion.div)
ignore the user's reduced-motion preference; fix this by either using the
prefersReduced boolean to short-circuit or remove animation props when true, or
import and use Framer Motion's useReducedMotion() and conditionally apply/omit
animation props on the motion.div elements that render the starfield and the
three rings (look for the motion.div components that control the starfield and
each ring animation) so that when reduced motion is requested the
animate/transition/variants are disabled and only static markup is rendered.

---

Outside diff comments:
In `@src/app/layout.tsx`:
- Around line 74-80: The html element in src/app/layout.tsx is rendered without
a dark class so users see a light flash before the client-side ThemeToggle
applies the class; add a small inline script in layout.tsx (placed before the
hydrated body content) that runs immediately to read the saved theme (e.g., from
localStorage) or prefers-color-scheme and synchronously add/remove the "dark"
class on document.documentElement, mirroring the logic used in ThemeToggle.tsx,
so the initial HTML already has the correct theme before hydration.

In `@src/sections/LogoTicker.tsx`:
- Around line 27-37: The animated ticker (the motion.div that renders the
looping partner strip with className "flex flex-none gap-8..." and
animate/transition props) is decorative and duplicates content, so add
accessibility attributes to hide it from assistive tech; update the motion.div
(or its immediate container) to include aria-hidden="true" and/or
role="presentation" so screen readers ignore the animated strip while the static
heading remains for users of assistive technologies.
🪄 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: 1a335982-5e7c-4eb0-bec1-f6063de29126

📥 Commits

Reviewing files that changed from the base of the PR and between 072747f and 787c11c.

⛔ Files ignored due to path filters (5)
  • src/app/apple-touch-icon.svg is excluded by !**/*.svg
  • src/app/favicon.svg is excluded by !**/*.svg
  • src/assets/djed-alliance.svg is excluded by !**/*.svg
  • src/assets/stability-nexus.svg is excluded by !**/*.svg
  • src/assets/svg/logo.svg is excluded by !**/*.svg
📒 Files selected for processing (13)
  • License.md
  • src/app/layout.tsx
  • src/app/page.tsx
  • src/components/Button.tsx
  • src/components/ThemeToggle.tsx
  • src/sections/About.tsx
  • src/sections/CallToAction.tsx
  • src/sections/Features.tsx
  • src/sections/Footer.tsx
  • src/sections/Header.tsx
  • src/sections/Hero.tsx
  • src/sections/LogoTicker.tsx
  • tailwind.config.ts

Comment thread src/components/ThemeToggle.tsx
Comment thread src/components/ThemeToggle.tsx
Comment thread src/sections/About.tsx Outdated
Comment thread src/sections/CallToAction.tsx Outdated
Comment thread src/sections/CallToAction.tsx Outdated
Comment thread src/sections/Footer.tsx
Comment thread src/sections/Header.tsx Outdated
Comment thread src/sections/Header.tsx
Comment thread src/sections/Header.tsx Outdated
Comment thread src/sections/Hero.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (2)
src/sections/CallToAction.tsx (1)

81-100: ⚠️ Potential issue | 🟡 Minor

The stars no longer receive the infinite background animation.

Lines 84-91 still animate backgroundPositionX on the outer wrapper, but the background image moved to Lines 94-99. That leaves the star layer static and keeps an unnecessary infinite animation running on a plain container.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/sections/CallToAction.tsx` around lines 81 - 100, The outer motion.div
currently animates backgroundPositionX while the background image was moved into
the inner motion.div, so the star layer is now static and the outer wrapper runs
an unnecessary infinite animation; remove the animate and transition props from
the outer motion.div (the element using borderedDivRef) and move that
animate/transition block to the inner motion.div that sets style.backgroundImage
(the element using startBg.src and backgroundPositionY), animating
backgroundPositionX with startBg.width and the same repeat/duration/ease so the
star/background layer receives the infinite animation.
src/sections/Features.tsx (1)

71-111: ⚠️ Potential issue | 🔴 Critical

FeatureTab has two blocking syntax errors.

Line 71 redeclares prefersReduced after it's already declared at line 45, and the <motion.button> opened at line 74 closes as </motion.div> at line 111. Remove the duplicate declaration and fix the closing tag.

Proposed fix
-  const prefersReduced = typeof window !== 'undefined' && window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches
-
   return (
     <motion.button
       type="button"
       whileHover={prefersReduced ? undefined : { scale: 1.05 }}
       whileTap={prefersReduced ? undefined : { scale: 0.95 }}
@@
-    </motion.div>
+    </motion.button>
   )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/sections/Features.tsx` around lines 71 - 111, The FeatureTab component
has two issues: a duplicate prefersReduced declaration and a mismatched JSX
closing tag; remove the second declaration of prefersReduced (the one at the
start of the shown diff) so only the initial prefersReduced (declared earlier)
remains, and replace the incorrect closing </motion.div> with </motion.button>
to properly close the <motion.button> opened in this fragment.
♻️ Duplicate comments (1)
src/sections/Header.tsx (1)

83-85: ⚠️ Potential issue | 🟠 Major

Integration Docs still looks like a dead target.

Both nav variants prevent the native anchor behavior and then look up integration-docs; if no section exposes that id, the click becomes a silent no-op. I couldn't find that target in the sections included here.

Run this to confirm whether any section actually defines id="integration-docs"; if the only matches are the header links, the target is still missing:

#!/bin/bash
rg -n 'id=["'"'"']integration-docs["'"'"']|href=["'"'"']#integration-docs["'"'"']|getElementById\(["'"'"']integration-docs["'"'"']\)' src

Also applies to: 129-129

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/sections/Header.tsx` around lines 83 - 85, The "Integration Docs" nav
link uses the onClick handler handleSmoothScroll and targets 'integration-docs'
but there is no element with id="integration-docs", making the click a no-op;
either add id="integration-docs" to the intended section/component (e.g., the
IntegrationDocs section component or its container) or update the anchor's
href/onClick target to the actual existing id, or remove the custom handler to
allow native anchor behavior; locate the anchor in Header.tsx and the candidate
target section component and ensure their ids/match strings (the
'integration-docs' literal and handleSmoothScroll) are consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/sections/Footer.tsx`:
- Around line 27-29: The "Blog" anchor currently points to '#features' both in
its href and in the onClick handler, so the label doesn't match the destination;
update the anchor so its href and the element lookup in the onClick handler
point to the blog target (for example change href="#blog" and
document.getElementById('blog') or an external path like '/blog'), or remove the
anchor entirely until a real blog target exists; locate the anchor element with
the "Blog" text in Footer.tsx and modify the href and the getElementById string
inside the onClick callback (or delete the <a> node).

In `@src/sections/Header.tsx`:
- Around line 17-22: The handleSmoothScroll function currently forces smooth
scrolling; modify it to respect the user's prefers-reduced-motion setting by
checking window.matchMedia('(prefers-reduced-motion: reduce)').matches and using
behavior: 'auto' (or omitting smooth) when reduced motion is requested,
otherwise use behavior: 'smooth'; update the logic inside handleSmoothScroll to
compute the behavior value before calling el.scrollIntoView and use that
variable so header navigation honors user motion preferences.
- Around line 64-65: The header's className uses "z-0" which places it beneath
later content (e.g., Features.tsx's relative z-10); update the header element in
src/sections/Header.tsx (the <header ... className="... z-0 ...">) to a higher
stacking index such as "z-10" (or remove "z-0" and add "z-10") so the sticky
header and its mobile menu sit above page content; leave the backdrop div's
"-z-10" as-is so the backdrop remains behind the header.

---

Outside diff comments:
In `@src/sections/CallToAction.tsx`:
- Around line 81-100: The outer motion.div currently animates
backgroundPositionX while the background image was moved into the inner
motion.div, so the star layer is now static and the outer wrapper runs an
unnecessary infinite animation; remove the animate and transition props from the
outer motion.div (the element using borderedDivRef) and move that
animate/transition block to the inner motion.div that sets style.backgroundImage
(the element using startBg.src and backgroundPositionY), animating
backgroundPositionX with startBg.width and the same repeat/duration/ease so the
star/background layer receives the infinite animation.

In `@src/sections/Features.tsx`:
- Around line 71-111: The FeatureTab component has two issues: a duplicate
prefersReduced declaration and a mismatched JSX closing tag; remove the second
declaration of prefersReduced (the one at the start of the shown diff) so only
the initial prefersReduced (declared earlier) remains, and replace the incorrect
closing </motion.div> with </motion.button> to properly close the
<motion.button> opened in this fragment.

---

Duplicate comments:
In `@src/sections/Header.tsx`:
- Around line 83-85: The "Integration Docs" nav link uses the onClick handler
handleSmoothScroll and targets 'integration-docs' but there is no element with
id="integration-docs", making the click a no-op; either add
id="integration-docs" to the intended section/component (e.g., the
IntegrationDocs section component or its container) or update the anchor's
href/onClick target to the actual existing id, or remove the custom handler to
allow native anchor behavior; locate the anchor in Header.tsx and the candidate
target section component and ensure their ids/match strings (the
'integration-docs' literal and handleSmoothScroll) are consistent.
🪄 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: 63429989-6611-442f-8271-ebc94e7ae996

📥 Commits

Reviewing files that changed from the base of the PR and between 787c11c and ed3b49d.

📒 Files selected for processing (9)
  • src/app/layout.tsx
  • src/components/ThemeToggle.tsx
  • src/sections/About.tsx
  • src/sections/CallToAction.tsx
  • src/sections/Features.tsx
  • src/sections/Footer.tsx
  • src/sections/Header.tsx
  • src/sections/Hero.tsx
  • src/sections/LogoTicker.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/sections/LogoTicker.tsx
  • src/components/ThemeToggle.tsx

Comment thread src/sections/Footer.tsx
Comment on lines +27 to 29
<a href="#features" onClick={(e) => { e.preventDefault(); const el = document.getElementById('features'); if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' }) }} className="text-black/70 hover:text-black dark:text-white/70 dark:hover:text-white text-xs sm:text-sm transition-colors duration-300">
Blog
</a>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

The Blog footer item still lands on #features.

Both the href and the click handler on Lines 27-29 send users to the Features section, so the label does not match the destination. Point it at a real blog target or remove the item until one exists.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/sections/Footer.tsx` around lines 27 - 29, The "Blog" anchor currently
points to '#features' both in its href and in the onClick handler, so the label
doesn't match the destination; update the anchor so its href and the element
lookup in the onClick handler point to the blog target (for example change
href="#blog" and document.getElementById('blog') or an external path like
'/blog'), or remove the anchor entirely until a real blog target exists; locate
the anchor element with the "Blog" text in Footer.tsx and modify the href and
the getElementById string inside the onClick callback (or delete the <a> node).

Comment thread src/sections/Header.tsx
Comment on lines +17 to +22
// Smooth scroll helper for same-page navigation
const handleSmoothScroll = (e: React.MouseEvent, id: string) => {
e.preventDefault()
const el = document.getElementById(id)
if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' })
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Respect reduced-motion in the nav scroll helper.

handleSmoothScroll always uses behavior: 'smooth', so users who opt out of animation still get forced motion on every header navigation click.

🛠️ Proposed fix
   const handleSmoothScroll = (e: React.MouseEvent, id: string) => {
     e.preventDefault()
     const el = document.getElementById(id)
-    if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' })
+    if (!el) return
+    const behavior = window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth'
+    el.scrollIntoView({ behavior, block: 'start' })
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/sections/Header.tsx` around lines 17 - 22, The handleSmoothScroll
function currently forces smooth scrolling; modify it to respect the user's
prefers-reduced-motion setting by checking
window.matchMedia('(prefers-reduced-motion: reduce)').matches and using
behavior: 'auto' (or omitting smooth) when reduced motion is requested,
otherwise use behavior: 'smooth'; update the logic inside handleSmoothScroll to
compute the behavior value before calling el.scrollIntoView and use that
variable so header navigation honors user motion preferences.

Comment thread src/sections/Header.tsx
Comment on lines +64 to +65
<header className="py-3 sm:py-4 border-b border-black/10 dark:border-white/15 md:border-none sticky top-0 z-0 transition-colors duration-500 shadow-sm md:shadow-none dark:shadow-none">
<div className="absolute inset-0 backdrop-blur-md -z-10 md:hidden bg-white/80 dark:bg-transparent transition-colors duration-500"></div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Raise the header above page content.

z-0 on the sticky header creates the stacking context for the whole drawer/backdrop subtree, so later content can still paint over it. src/sections/Features.tsx, Line 159 already uses relative z-10, which is enough to sit above this header and its mobile menu.

🛠️ Proposed fix
-    <header className="py-3 sm:py-4 border-b border-black/10 dark:border-white/15 md:border-none sticky top-0 z-0 transition-colors duration-500 shadow-sm md:shadow-none dark:shadow-none">
+    <header className="py-3 sm:py-4 border-b border-black/10 dark:border-white/15 md:border-none sticky top-0 z-30 transition-colors duration-500 shadow-sm md:shadow-none dark:shadow-none">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<header className="py-3 sm:py-4 border-b border-black/10 dark:border-white/15 md:border-none sticky top-0 z-0 transition-colors duration-500 shadow-sm md:shadow-none dark:shadow-none">
<div className="absolute inset-0 backdrop-blur-md -z-10 md:hidden bg-white/80 dark:bg-transparent transition-colors duration-500"></div>
<header className="py-3 sm:py-4 border-b border-black/10 dark:border-white/15 md:border-none sticky top-0 z-30 transition-colors duration-500 shadow-sm md:shadow-none dark:shadow-none">
<div className="absolute inset-0 backdrop-blur-md -z-10 md:hidden bg-white/80 dark:bg-transparent transition-colors duration-500"></div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/sections/Header.tsx` around lines 64 - 65, The header's className uses
"z-0" which places it beneath later content (e.g., Features.tsx's relative
z-10); update the header element in src/sections/Header.tsx (the <header ...
className="... z-0 ...">) to a higher stacking index such as "z-10" (or remove
"z-0" and add "z-10") so the sticky header and its mobile menu sit above page
content; leave the backdrop div's "-z-10" as-is so the backdrop remains behind
the header.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
src/app/layout.tsx (1)

2-2: Orphaned font configuration in Tailwind.

The Fraunces font has been removed from imports, but tailwind.config.ts (lines 28-35) still defines a fraunces font family referencing var(--font-fraunces). This CSS variable is no longer provided, so any use of font-fraunces would silently fall back to the generic serif. Consider removing the orphaned fraunces entry from the Tailwind config to prevent future confusion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/layout.tsx` at line 2, Remove the orphaned Tailwind font entry for
"fraunces" that references var(--font-fraunces): delete the "fraunces" family
definition in your Tailwind config (the object that maps "fraunces" to
"var(--font-fraunces)") and any related CSS variable declaration; additionally
search the codebase for the utility/class "font-fraunces" and either replace it
with an existing font class (e.g., the imported Inter or Caudex) or remove it to
avoid silent fallbacks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/layout.tsx`:
- Around line 29-44: The OpenGraph/Twitter image fields in the metadata object
(the images array and twitter.images in layout.tsx) currently point to an SVG
('/favicon.svg'), which most social platforms won't render; replace those
references with a raster image (e.g., '/og.png' or '/og.jpg') at the recommended
1200x630 resolution or remove the images entries until a proper PNG/JPG/WebP
asset exists so social previews render correctly. Ensure you update both the
images entry inside the metadata OpenGraph section and the twitter.images value
to the new raster filename.

---

Nitpick comments:
In `@src/app/layout.tsx`:
- Line 2: Remove the orphaned Tailwind font entry for "fraunces" that references
var(--font-fraunces): delete the "fraunces" family definition in your Tailwind
config (the object that maps "fraunces" to "var(--font-fraunces)") and any
related CSS variable declaration; additionally search the codebase for the
utility/class "font-fraunces" and either replace it with an existing font class
(e.g., the imported Inter or Caudex) or remove it to avoid silent fallbacks.
🪄 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: f15ded24-d502-4717-b0e1-6c56949a9f61

📥 Commits

Reviewing files that changed from the base of the PR and between ed3b49d and 15386f2.

📒 Files selected for processing (2)
  • src/app/layout.tsx
  • src/sections/LogoTicker.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/sections/LogoTicker.tsx

Comment thread src/app/layout.tsx
Comment on lines +29 to +44
images: [
{
// public currently does not contain og.png; use repo logo as fallback
url: '/favicon.svg',
width: 1200,
height: 630,
alt: 'StablePay — Open-source SDK',
},
],
type: 'website',
},
twitter: {
card: 'summary_large_image',
title: 'StablePay — Open-source SDK for Djed stablecoins',
description: 'An open-source SDK enabling merchants to accept payments in Djed stablecoins.',
images: ['/favicon.svg'],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

SVG is not supported for OpenGraph/Twitter card images.

Most social platforms (Facebook, Twitter/X, LinkedIn, Slack, etc.) require raster formats (PNG, JPG, WebP) for OG images and will not render SVG. Using /favicon.svg will result in missing or broken preview images when the page is shared.

Consider creating a proper OG image at the standard dimensions (1200×630) in PNG/JPG format, or remove the images fields until a proper asset is available to avoid misleading metadata.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/layout.tsx` around lines 29 - 44, The OpenGraph/Twitter image fields
in the metadata object (the images array and twitter.images in layout.tsx)
currently point to an SVG ('/favicon.svg'), which most social platforms won't
render; replace those references with a raster image (e.g., '/og.png' or
'/og.jpg') at the recommended 1200x630 resolution or remove the images entries
until a proper PNG/JPG/WebP asset exists so social previews render correctly.
Ensure you update both the images entry inside the metadata OpenGraph section
and the twitter.images value to the new raster filename.

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.

[FEATURE]:Add About section and improve navigation & accessibility

1 participant