Skip to content

feat: add Reviews testimonial carousel and How We Work scroll-pinned section#233

Merged
BillChirico merged 14 commits into
mainfrom
feat/reviews-how-we-work
Jul 17, 2026
Merged

feat: add Reviews testimonial carousel and How We Work scroll-pinned section#233
BillChirico merged 14 commits into
mainfrom
feat/reviews-how-we-work

Conversation

@rabden

@rabden rabden commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • New Reviews section (src/components/reviews.tsx): staggered testimonial card deck. content/review.json.
  • New How We Work section (src/components/how-we-work.tsx): 100vh pinned GSAP ScrollTrigger timeline above the About section — title velocity pull-in → headline → word-by-word subtext → 5-step card carousel (local UI cutout images: bubble, laptop, floating UI, calendar, handshake) → info bento cards with custom animated SVG graphics → editorial values stack → closing CTA. Phases are split so each step reads cleanly.
  • Button: swapped to the MD3-expressive variant and refactored all usages to semantic variants/sizes.
  • Team fix: Hossain Jahed (rabden) type corrected marketerbuilder and role set to Developer.
  • Added @gsap/react dependency.

Screencast.From.2026-07-17.09-41-32.mp4
Screencast.From.2026-07-16.22-31-44.mp4
Screenshot From 2026-07-16 22-32-20
Screencast.From.2026-07-17.09-42-54.mp4

…section

- New Reviews section: staggered testimonial card deck with the original
  OG shuffle logic (tempId key + wrap teleport), profile-pic support with
  initials fallback, removed gradient fades / bottom separator, bordered
  container to match testimonial card styling
- New How We Work section: 100vh pinned GSAP ScrollTrigger timeline
  (title float-in -> headline -> word-by-word subtext -> 5-step card
  carousel -> info bento cards with custom SVG animations -> values stack
  -> closing CTA), using local UI cutout images
- Swap Button to MD3-expressive variant, refactor usages to semantic
  variants/sizes across the site
- Fix Hossain Jahed team type (marketer -> builder) and role
- Add @gsap/react dependency
@vercel

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
volvox-website Ready Ready Preview, Comment Jul 17, 2026 4:26am

Request Review

@claude

claude Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Claude finished @rabden's task in 2m 32s —— View job


PR Review Complete

Reviewed PR #233: Reviews testimonial carousel and How We Work scroll-pinned section


Summary

This is a substantial feature PR that adds two new homepage sections (Reviews carousel and How We Work scroll-pinned experience), refactors the Button component to use MD3-expressive styling, and updates team member content. The implementation is well-structured with good attention to accessibility and reduced motion preferences.


Addressed Review Feedback ✅

The following previously raised issues have been successfully addressed:

Issue Status
Placeholder avatar URLs (i.pravatar.cc) ✅ Fixed - Now uses real Discord CDN URLs or no image
how-we-work missing from scroll spy ✅ Fixed - Added to NAV_ITEMS and sections array
reviews section tracking ✅ Fixed - Added to navigation constants
about-section test ID ✅ Present at about.tsx:79
how-we-work-section test ID ✅ Present at how-we-work.tsx:443
reviews-section test ID ✅ Present at reviews.tsx:389
Mobile layout for How We Work ✅ Fixed - Dedicated mobile layout with md:hidden
Reduced motion in How We Work ✅ Fixed - staticMode for mobile/reduced-motion users
Register useGSAP plugin ✅ Fixed at how-we-work.tsx:10
MagneticButton reduced motion ✅ Fixed - Uses useReducedMotion hook
Reviews empty array stability ✅ Fixed - EMPTY_REVIEWS constant at reviews.tsx:57
AudioContext cleanup ✅ Fixed - osc.onended closes context
URL validation for profilePicUrl ✅ Fixed - Uses z.string().url().optional()
Review ID uniqueness validation ✅ Fixed - Schema has .refine() for uniqueness
Volvox logo in CTA alt="" ✅ Fixed at how-we-work.tsx:1205

Remaining Minor Suggestions

1. Button Pointer Event Order (Low Priority)

src/components/ui/button.tsx:561-575

The pointer handlers call internal handlers before external callbacks:

onPointerDown: (e) => {
  events.onPointerDown(e);  // Internal first
  onPointerDown?.(e);       // External second
},

If a consumer wants to prevent ripple via e.preventDefault(), the internal handler runs first. Consider inverting and checking defaultPrevented:

onPointerDown: (e) => {
  onPointerDown?.(e);
  if (!e.defaultPrevented) events.onPointerDown(e);
},

2. Team Detail Page Click Handlers (Low Priority)

src/app/team/team-member-detail-client.tsx:34-44

The handleContact and handleHire functions use imperative window.location.href and window.open. These could be <a> tags for better accessibility (middle-click support, native context menu). However, since they're wrapped in MagneticButton, this may be intentional for the interaction design.


Architecture & Code Quality ✅

Positive observations:

  1. GSAP Integration - Proper use of useGSAP with revertOnUpdate: true and scoped containers
  2. Reduced Motion - Comprehensive support via staticMode state, CSS motion-reduce:, and useReducedMotion hook
  3. Content Validation - Zod schemas properly validate reviews with URL format and ID uniqueness
  4. Mobile-First - Dedicated mobile layouts avoid pinning/overflow issues
  5. Accessibility - Proper ARIA labels, live regions for carousel (<output aria-live="polite">), and keyboard navigation
  6. Import Organization - Framework imports before third-party before local (per guidelines)
  7. Type Safety - Explicit JSX.Element return types on exported components

Test Coverage

All required data-testid attributes per CLAUDE.md are present:

  • hero-section
  • products-section
  • blog-section
  • mentorship-section
  • about-section
  • reviews-section ✅ (new)
  • how-we-work-section ✅ (new)
  • footer
  • theme-toggle
  • cookie-consent-banner

Verdict

Ready to merge with the minor suggestions above being optional improvements for future iteration.

The PR demonstrates solid engineering practices with thorough attention to accessibility, performance (GSAP cleanup, reduced motion), and code organization. Previous review feedback has been systematically addressed.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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

The PR adds validated, content-driven homepage reviews, GSAP-powered About and How We Work sections, and an animated team-member detail page. It also updates the shared Button system, simplifies button styling across interfaces, removes the noise overlay, and updates team content.

Changes

Homepage reviews

Layer / File(s) Summary
Review content contract and source data
src/lib/schemas.ts, src/lib/types.ts, content/review.json, content/team.json
Adds validated review content, inferred types, review data, and team metadata updates.
Review loading and homepage wiring
src/lib/content.ts, src/app/page.tsx, src/components/homepage-client.tsx, CHANGELOG.md
Loads reviews with error handling and passes them into a new homepage section with scroll tracking.
Animated review deck
src/components/reviews.tsx
Adds responsive animated review cards, trust badges, navigation, ratings, reduced-motion handling, and live accessibility text.

Animated content sections

Layer / File(s) Summary
Pinned How We Work experience
src/components/how-we-work.tsx, package.json
Adds a GSAP/ScrollTrigger-pinned process section with steps, information cards, values, and a closing CTA.
About section animation and cards
src/components/about.tsx
Replaces viewport animations with GSAP reveals and updates BentoCard structure, styling, and content.
Animated team-member detail page
src/app/team/team-member-detail-client.tsx
Adds GSAP hero and scroll reveals while restructuring bio, projects, expertise, and connection sections.

Button system and site-wide styling

Layer / File(s) Summary
Button behavior and variants
src/components/ui/button.tsx
Reworks button variants, ripple behavior, tactile feedback, wrapper layout, and adds SplitButton.
Button consumers and navigation controls
src/components/**
Simplifies button styling and updates sizes, visibility, and variants across site interfaces.
Global presentation and page configuration
src/app/globals.css, src/app/layout.tsx, src/app/page.tsx
Removes the noise overlay and adds hourly homepage revalidation.

Suggested labels: feature, enhancement, dependencies, accessibility

Suggested reviewers: billchirico

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.63% 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
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main addition: a Reviews carousel and a How We Work scroll-pinned section.
Description check ✅ Passed The description matches the changeset and covers the new Reviews, How We Work, button updates, team fix, and dependency update.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/reviews-how-we-work

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.

@qltysh

qltysh Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

19 new issues

Tool Category Rule Count
qlty Duplication Found 20 lines of similar code in 2 locations (mass = 69) 13
qlty Structure Function with high complexity (count = 26): HowWeWork 3
qlty Structure Function with many returns (count = 8): Reviews 2
qlty Structure High total complexity (count = 81) 1

Comment thread src/components/how-we-work.tsx
Comment thread src/components/how-we-work.tsx
Comment thread content/review.json Outdated
The homepage should have a single h1 (in the Hero section). Section headings
should use h2 to maintain proper semantic HTML structure.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds new homepage sections and updates related UI. The main changes are:

  • New Reviews carousel backed by content/review.json.
  • New pinned How We Work section with GSAP animations.
  • Reviews content loading through the homepage server/client flow.
  • Expanded homepage navigation entries.
  • Updated button variants and related component usage.
  • Refreshed team member content and profile styling.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
src/components/reviews.tsx Adds the Reviews carousel with initial review ordering derived from the provided content.
src/components/homepage-client.tsx Adds How We Work and Reviews to the homepage and expands the scroll-spy section list.
src/components/how-we-work.tsx Adds the animated How We Work section with desktop pinning and a static path for mobile or reduced motion.
src/lib/constants.ts Adds How We Work and Reviews navigation items.

Reviews (11): Last reviewed commit: "fix: add dedicated mobile layout for how..." | Re-trigger Greptile

Comment thread src/components/reviews.tsx Outdated
Comment thread src/components/homepage-client.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 14

Caution

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

⚠️ Outside diff range comments (3)
src/components/blog/blog-post-header.tsx (1)

57-66: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add the required theme-toggle test ID.

Proposed fix
               <Button
                 variant="ghost"
                 size="icon"
+                data-testid="theme-toggle"
                 onClick={toggleTheme}

As per coding guidelines, “Add data-testid attributes to key elements: … theme-toggle …”.

🤖 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 `@src/components/blog/blog-post-header.tsx` around lines 57 - 66, Add the
required data-testid="theme-toggle" attribute to the theme-toggle Button in the
blog post header, identified by its toggleTheme onClick handler, while
preserving the existing variant, accessibility label, and behavior.

Source: Coding guidelines

src/components/navigation.tsx (1)

251-263: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prefer anchor tags for external navigation instead of window.open.

Using onClick with window.open for external links hinders accessibility, degrades SEO, and prevents users from natively middle-clicking to open in a new tab. Use the asChild prop on Button to render a standard <a> element instead.

  • src/components/navigation.tsx#L251-L263: Replace the onClick handler with an <a href={DISCORD_URL} target="_blank" rel="noopener noreferrer" onClick={handleDiscordClick}> inside the Discord button using asChild.
  • src/components/products.tsx#L229-L245: Replace the onClick handler with an <a href={product.links.demo} target="_blank" rel="noopener noreferrer"> inside the Launch button using asChild.
🤖 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 `@src/components/navigation.tsx` around lines 251 - 263, Replace the
window.open-based Discord navigation in the Button at
src/components/navigation.tsx:251-263 with an asChild anchor using
href={DISCORD_URL}, target="_blank", rel="noopener noreferrer", and
onClick={handleDiscordClick}; update the Launch Button at
src/components/products.tsx:229-245 similarly with an anchor using
product.links.demo, target="_blank", and rel="noopener noreferrer".
src/components/blog/blog-post-navbar.tsx (1)

24-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prefer <Link> components for internal navigation instead of router.push.

Several navigation buttons use onClick={() => router.push(...)} for internal routing. Using Next.js <Link> components (via the asChild prop) improves performance through route prefetching, enhances SEO, and allows users to middle-click to open links in a new tab.

  • src/components/blog/blog-post-navbar.tsx#L24-L32: Wrap the icon with <Link href="/#blog"> and add asChild to the button.
  • src/components/blog/blog-post-navbar.tsx#L80-L88: Wrap the content with <Link href="/#blog"> and add asChild to the button.
  • src/components/products/product-post-navbar.tsx#L24-L32: Wrap the icon with <Link href="/products"> and add asChild to the button.
  • src/components/products/product-post-navbar.tsx#L81-L89: Wrap the content with <Link href="/products"> and add asChild to the button.
  • src/components/team/member-navbar.tsx#L24-L32: Wrap the icon with <Link href="/team"> and add asChild to the button.
  • src/components/team/member-navbar.tsx#L80-L88: Wrap the content with <Link href="/team"> and add asChild to the button.
  • src/components/team/team-navbar.tsx#L38-L46: Wrap the icon with <Link href="/"> and add asChild to the button.
  • src/components/products/products-navbar.tsx#L79-L87: Wrap the icon with <Link href="/"> and add asChild to the button.
  • src/components/products.tsx#L400-L414: Wrap the content with <Link href="/products"> and add asChild to the button.
🤖 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 `@src/components/blog/blog-post-navbar.tsx` around lines 24 - 32, Replace the
internal router.push navigation with Next.js Link components using Button’s
asChild prop: in src/components/blog/blog-post-navbar.tsx lines 24-32 and 80-88
use /#blog; in src/components/products/product-post-navbar.tsx lines 24-32 and
81-89 use /products; in src/components/team/member-navbar.tsx lines 24-32 and
80-88 use /team; in src/components/team/team-navbar.tsx lines 38-46 and
src/components/products/products-navbar.tsx lines 79-87 use /; and in
src/components/products.tsx lines 400-414 use /products. Wrap each existing icon
or content child with the matching Link and remove the router-based click
handlers.
🤖 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 `@content/review.json`:
- Around line 20-69: Update the testimonial entries shown in
content/review.json, including Muhammad Yasir, Great game 202, KathyMcHugh,
TheBapes, and `@Chimemaram1`, to replace the i.pravatar.cc placeholder
profilePicUrl values with consented real reviewer avatars; if those are
unavailable, remove each profilePicUrl field entirely.

In `@src/components/homepage-client.tsx`:
- Line 112: Add "how-we-work" to the sections list used by the scroll spy in the
homepage client, and add the matching entry to NAV_ITEMS so the section is
tracked and its navigation item is highlighted while visible.

In `@src/components/how-we-work.tsx`:
- Line 370: Update the pinned layout around pinRef and the related step/card
content so screens below the md breakpoint are not clipped by the h-screen
overflow-hidden container. Disable pinning and allow natural vertical scrolling
on small screens, while preserving the existing pinned presentation for md and
larger viewports.
- Around line 382-406: Update the phase containers and the invisible mail link
identified in the diff, including the headline, subtext, steps wrapper, and
related ranges, to use visibility and/or inert state in addition to opacity and
pointer-events. Ensure inactive phases are removed from the accessibility tree
and cannot receive sequential focus, while the currently revealed phase becomes
accessible when activated.
- Around line 47-360: Update the useGSAP animation setup to detect
prefers-reduced-motion and provide a static rendering branch that skips the
pinned ScrollTrigger and scrubbed timeline, while keeping all phase
wrappers/content visible in their final non-animated state. Disable or prevent
the SVG animations in this branch, and ensure the normal GSAP timeline remains
unchanged for users without the preference.
- Around line 1-7: Reorder imports in the how-we-work component so the
React/framework import comes first, followed by GSAP third-party imports and
then the local Button import. Add an explicit public return type to the exported
component function, likely HowWeWork, without changing its existing behavior.
- Line 7: Update the GSAP plugin registration near the existing ScrollTrigger
registration to include useGSAP alongside ScrollTrigger, preserving the current
registration flow and ensuring the React integration is explicitly registered.

In `@src/components/reviews.tsx`:
- Around line 318-331: Stabilize the fallback used by the reviews value in the
component containing the orderedReviews synchronization: replace the per-render
[] created by content?.reviews ?? [] with a shared empty-array constant or
memoized fallback. Preserve the existing reviews data when content is present
and keep the useEffect dependency on the stabilized reviews value.

In `@src/components/ui/button.tsx`:
- Around line 634-638: Update the className composition in the button component
to replace the legacy Tailwind important utility `!h-auto` with the v4 trailing
syntax `h-auto!`, while preserving the existing `self-stretch` class and class
merging behavior.
- Around line 17-50: Update playTactilePopSound to close each newly created
AudioContext from osc.onended after the oscillator finishes, while retaining one
context per click only when audio is available. Replace the blanket silent catch
with handling that ignores only expected browser restrictions and forwards
unexpected exceptions to reportError().
- Around line 538-556: Update the component props assembly around componentProps
to destructure the four pointer callbacks from props, compose each with its
corresponding events handler, and spread only the remaining props before
assigning the composed handlers. Invoke the external callback and internal
handler while short-circuiting appropriately when event.defaultPrevented is set,
preserving the ripple hover/press state behavior.
- Around line 1-6: Add the "use client" directive at the top of the button
component before its imports so the component can use its React hooks and
browser-only APIs, including useState, useRef, and window.AudioContext.

In `@src/lib/schemas.ts`:
- Around line 236-241: Add a schema-level uniqueness validation to
reviewsContentSchema for reviews[].id, ensuring duplicate IDs produce a
validation error during parsing while preserving the existing review item
validation and other defaults.
- Around line 211-221: Update profilePicUrl in homepageReviewSchema to validate
URL values with Zod’s top-level z.url() schema while preserving its optional
behavior; leave the other review fields unchanged.

---

Outside diff comments:
In `@src/components/blog/blog-post-header.tsx`:
- Around line 57-66: Add the required data-testid="theme-toggle" attribute to
the theme-toggle Button in the blog post header, identified by its toggleTheme
onClick handler, while preserving the existing variant, accessibility label, and
behavior.

In `@src/components/blog/blog-post-navbar.tsx`:
- Around line 24-32: Replace the internal router.push navigation with Next.js
Link components using Button’s asChild prop: in
src/components/blog/blog-post-navbar.tsx lines 24-32 and 80-88 use /#blog; in
src/components/products/product-post-navbar.tsx lines 24-32 and 81-89 use
/products; in src/components/team/member-navbar.tsx lines 24-32 and 80-88 use
/team; in src/components/team/team-navbar.tsx lines 38-46 and
src/components/products/products-navbar.tsx lines 79-87 use /; and in
src/components/products.tsx lines 400-414 use /products. Wrap each existing icon
or content child with the matching Link and remove the router-based click
handlers.

In `@src/components/navigation.tsx`:
- Around line 251-263: Replace the window.open-based Discord navigation in the
Button at src/components/navigation.tsx:251-263 with an asChild anchor using
href={DISCORD_URL}, target="_blank", rel="noopener noreferrer", and
onClick={handleDiscordClick}; update the Launch Button at
src/components/products.tsx:229-245 similarly with an anchor using
product.links.demo, target="_blank", and rel="noopener noreferrer".
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 84c72e09-87ba-4f56-8f2d-d092ea31ca4a

📥 Commits

Reviewing files that changed from the base of the PR and between 5c37e09 and c32fc03.

⛔ Files ignored due to path filters (6)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • public/images/UI/calendar_cutout.png is excluded by !**/*.png
  • public/images/UI/floating_ui_elements_cutout.png is excluded by !**/*.png
  • public/images/UI/handshake_cutout.png is excluded by !**/*.png
  • public/images/UI/laptop_cutout.png is excluded by !**/*.png
  • public/images/UI/two_speech_bubble_cutout.png is excluded by !**/*.png
📒 Files selected for processing (31)
  • CHANGELOG.md
  • content/review.json
  • content/team.json
  • package.json
  • src/app/page.tsx
  • src/app/team/team-member-detail-client.tsx
  • src/components/ai/chat-header.tsx
  • src/components/blog.tsx
  • src/components/blog/back-to-posts-button.tsx
  • src/components/blog/blog-navbar.tsx
  • src/components/blog/blog-post-header.tsx
  • src/components/blog/blog-post-navbar.tsx
  • src/components/cookie-consent-banner.tsx
  • src/components/hero/hero-section.tsx
  • src/components/homepage-client.tsx
  • src/components/how-we-work.tsx
  • src/components/mentorship.tsx
  • src/components/navigation.tsx
  • src/components/products-list-client.tsx
  • src/components/products.tsx
  • src/components/products/product-hero.tsx
  • src/components/products/product-post-navbar.tsx
  • src/components/products/products-navbar.tsx
  • src/components/reviews.tsx
  • src/components/team/member-navbar.tsx
  • src/components/team/team-navbar.tsx
  • src/components/theme-toggle.tsx
  • src/components/ui/button.tsx
  • src/lib/content.ts
  • src/lib/schemas.ts
  • src/lib/types.ts
💤 Files with no reviewable changes (5)
  • src/components/blog/back-to-posts-button.tsx
  • src/components/mentorship.tsx
  • src/components/products/product-hero.tsx
  • src/components/theme-toggle.tsx
  • src/components/ai/chat-header.tsx

Comment thread content/review.json
Comment thread src/components/homepage-client.tsx Outdated
Comment thread src/components/how-we-work.tsx Outdated
Comment thread src/components/how-we-work.tsx Outdated
Comment thread src/components/how-we-work.tsx
Comment thread src/components/ui/button.tsx
Comment thread src/components/ui/button.tsx
Comment thread src/components/ui/button.tsx
Comment thread src/lib/schemas.ts
Comment thread src/lib/schemas.ts
- reviews: lazy-init ordered reviews so the section renders in SSR HTML
- button: add "use client", compose consumer pointer handlers, close
  AudioContext after tactile pop, fix h-auto! Tailwind v4 syntax
- how-we-work: static (non-pinned) layout for mobile and reduced-motion
  users, freeze SMIL SVGs for reduced motion, gate inactive phases from
  the a11y tree via autoAlpha, add "use client" and register useGSAP
- homepage: move How We Work directly below the Hero, update scroll spy
- schemas: validate profilePicUrl as URL, enforce unique review ids
- team: refresh Hossain Jahed's project list
- content: drop placeholder pravatar avatars from reviews
Comment thread src/components/homepage-client.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
src/components/homepage-client.tsx (1)

65-66: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use window.scrollY instead of window.pageYOffset.

window.pageYOffset is a legacy alias for window.scrollY. For consistency with the rest of the file (e.g., in handleScroll), prefer window.scrollY.

♻️ Proposed refactor
           const elementPosition = element.getBoundingClientRect().top;
-          const offsetPosition = elementPosition + window.pageYOffset - offset;
+          const offsetPosition = elementPosition + window.scrollY - offset;
🤖 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 `@src/components/homepage-client.tsx` around lines 65 - 66, Update the scroll
offset calculation using elementPosition to read the page scroll value from
window.scrollY instead of the legacy window.pageYOffset alias, matching the
existing handleScroll implementation.
♻️ Duplicate comments (2)
src/components/ui/button.tsx (2)

558-573: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Honor event.defaultPrevented in composed event handlers.

The pointer handlers are now being destructured and composed (addressing part of the previous feedback), but the internal events.* handlers are called before the consumer's callback, and event.defaultPrevented is not checked. To properly allow consumers to opt-out of the ripple effect (e.g., when calling e.preventDefault()), invoke the external callback first and short-circuit if the default was prevented.

🛠️ Proposed fix for pointer events composition
       onPointerDown: (e: React.PointerEvent<HTMLButtonElement>) => {
-        events.onPointerDown(e);
         onPointerDown?.(e);
+        if (!e.defaultPrevented) events.onPointerDown(e);
       },
       onPointerUp: (e: React.PointerEvent<HTMLButtonElement>) => {
-        events.onPointerUp(e);
         onPointerUp?.(e);
+        if (!e.defaultPrevented) events.onPointerUp(e);
       },
       onPointerEnter: (e: React.PointerEvent<HTMLButtonElement>) => {
-        events.onPointerEnter(e);
         onPointerEnter?.(e);
+        if (!e.defaultPrevented) events.onPointerEnter(e);
       },
       onPointerLeave: (e: React.PointerEvent<HTMLButtonElement>) => {
-        events.onPointerLeave(e);
         onPointerLeave?.(e);
+        if (!e.defaultPrevented) events.onPointerLeave(e);
       },

Note: You may want to apply the same pattern to onClick (lines 574-582) if the tactile pop sound and internal ripple logic should also respect e.defaultPrevented.

🤖 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 `@src/components/ui/button.tsx` around lines 558 - 573, Update the composed
pointer handlers around events.onPointerDown, events.onPointerUp,
events.onPointerEnter, and events.onPointerLeave to invoke each consumer
callback first, then return without calling the corresponding internal handler
when the event is defaultPrevented; otherwise preserve the internal event
behavior. Apply the same defaultPrevented-aware ordering to the nearby onClick
composition if it also triggers tactile or ripple effects.

55-57: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Surface unexpected errors using reportError.

The previous review comment was only partially addressed: the AudioContext is properly closed, but the catch block still silently swallows all exceptions. As per coding guidelines, use the custom reportError() function from src/lib/logger.ts to forward unexpected errors, while silently ignoring expected browser restrictions like NotAllowedError.

🛠️ Proposed fix

Update the catch block to only ignore NotAllowedError (ensure you also import reportError from @/lib/logger at the top of the file):

-  } catch {
-    // Silently fail if audio context is restricted by the browser (e.g. before user interaction)
-  }
+  } catch (error) {
+    // Silently fail if audio context is restricted by the browser (e.g. before user interaction)
+    if (error instanceof Error && error.name === "NotAllowedError") return;
+    
+    reportError(error);
+  }
🤖 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 `@src/components/ui/button.tsx` around lines 55 - 57, Update the AudioContext
error handling in the button component to import and use reportError from the
logger, ignoring only expected NotAllowedError browser restrictions and
forwarding all other caught exceptions to reportError; preserve the existing
cleanup behavior.

Source: Coding guidelines

🤖 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 `@src/lib/schemas.ts`:
- Around line 243-246: Update the refine configuration in the reviews schema to
use Zod 4’s `error` property instead of `message`, preserving the existing
“Review ids must be unique” text and uniqueness validation.

---

Outside diff comments:
In `@src/components/homepage-client.tsx`:
- Around line 65-66: Update the scroll offset calculation using elementPosition
to read the page scroll value from window.scrollY instead of the legacy
window.pageYOffset alias, matching the existing handleScroll implementation.

---

Duplicate comments:
In `@src/components/ui/button.tsx`:
- Around line 558-573: Update the composed pointer handlers around
events.onPointerDown, events.onPointerUp, events.onPointerEnter, and
events.onPointerLeave to invoke each consumer callback first, then return
without calling the corresponding internal handler when the event is
defaultPrevented; otherwise preserve the internal event behavior. Apply the same
defaultPrevented-aware ordering to the nearby onClick composition if it also
triggers tactile or ripple effects.
- Around line 55-57: Update the AudioContext error handling in the button
component to import and use reportError from the logger, ignoring only expected
NotAllowedError browser restrictions and forwarding all other caught exceptions
to reportError; preserve the existing cleanup behavior.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 36d372c4-0f2c-4e10-8591-4effda43ed58

📥 Commits

Reviewing files that changed from the base of the PR and between 1f0f0bb and 4e213a3.

📒 Files selected for processing (7)
  • content/review.json
  • content/team.json
  • src/components/homepage-client.tsx
  • src/components/how-we-work.tsx
  • src/components/reviews.tsx
  • src/components/ui/button.tsx
  • src/lib/schemas.ts

Comment thread src/lib/schemas.ts
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 15, 2026
- Complete rewrite of about.tsx: double-bezel bento grid, GSAP scroll
  reveals, spotlight cursor tracking, asymmetric layout
- Complete rewrite of team-member-detail-client.tsx: editorial hero,
  double-bezel avatar, bento bio/expertise, clean project grid
- how-we-work: refined phase 7 typography, volvox pill with logo,
  removed noise overlay and step labels
- reviews: source-mark fallback icons (PH/X/AppStore) when no pfp;
  added yasir avatar
- products: solid badge bg (no blur), removed innovation pipeline pill,
  removed marketplace button gradient overlay
- Removed global noise overlay from layout.tsx and globals.css
- Rewrote Hossain Jahed bio in team.json
Comment thread src/components/ui/button.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (4)
src/components/how-we-work.tsx (3)

70-75: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Resume SVG animations when reduced motion is disabled.

After pauseAnimations() runs, switching the preference back leaves every SVG permanently paused because the false branch returns. Call unpauseAnimations() when reducedMotion becomes false.

🤖 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 `@src/components/how-we-work.tsx` around lines 70 - 75, Update the SVG
animation effect in the component’s useEffect so it handles both preference
states: pause each SVG when reducedMotion is true and call unpauseAnimations()
on each SVG when it is false. Keep the existing containerRef query and
reducedMotion dependency.

482-488: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use cn() for the static-mode class switch.

Replace the raw conditional class string with the shared class-merging utility.

As per coding guidelines, “Use cn() utility from lib/utils.ts for conditional Tailwind CSS classes.”

🤖 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 `@src/components/how-we-work.tsx` around lines 482 - 488, Update the className
expression on the div using pinRef to call the shared cn() utility, passing the
staticMode-dependent class values through it instead of using a raw conditional
string. Preserve the existing classes and behavior for both static and
non-static modes.

Source: Coding guidelines


463-479: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Pair each static step image with its description.

Static mode stacks the entire card column before the entire text column, so mobile and reduced-motion users see five images followed by five disconnected descriptions. Render each step as one paired static row/card.

Also applies to: 528-569

🤖 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 `@src/components/how-we-work.tsx` around lines 463 - 479, Update the
static-mode rendering in the steps component so each step outputs its image/card
and corresponding description together in a single row or paired wrapper, rather
than rendering all cards followed by all text. Use the existing step iteration
and static-mode branches around the hww-steps-wrapper markup, and preserve the
current styling while ensuring the five static steps remain in matching order.
src/components/about.tsx (1)

3-20: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Restore the required module organization in both animation components.

  • src/components/about.tsx#L3-L20: move React before third-party imports.
  • src/components/about.tsx#L177-L197: move BentoCardProps before setup and component logic.
  • src/app/team/team-member-detail-client.tsx#L3-L31: move React/Next first and declare props before plugin registration.

As per coding guidelines, “Organize imports in order: framework → third-party → local” and “Organize file structure as: imports → types → constants → logic → exports.”

🤖 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 `@src/components/about.tsx` around lines 3 - 20, Restore the prescribed
organization across all sites: in src/components/about.tsx lines 3-20, place
React imports before third-party imports and local imports; in
src/components/about.tsx lines 177-197, move BentoCardProps before setup and
component logic; in src/app/team/team-member-detail-client.tsx lines 3-31, place
React and Next imports first and declare the props type before plugin
registration. Keep the resulting structure as imports, types, constants, logic,
then exports.

Source: Coding guidelines

🤖 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 `@src/components/about.tsx`:
- Around line 72-78: Add the required test identifier to the section element
returned by the About component: set data-testid to "about-section" alongside
the existing ref, id, aria-label, and className attributes.
- Around line 28-70: Gate all listed animation logic behind the reduced-motion
preference: in src/components/about.tsx lines 28-70, skip the GSAP
ScrollTriggers and keep the header and bento elements in their visible final
states; in src/app/team/team-member-detail-client.tsx lines 46-131, skip
entrance and reveal animations; in lines 196-223, disable ping and magnetic
action movement; and in lines 375-427, render static social-button wrappers
instead of animated ones. Use the existing animation setup symbols and
reduced-motion detection consistently across each site.

In `@src/components/how-we-work.tsx`:
- Around line 1229-1242: Update the Image element inside the heading’s Volvox
badge to use an empty alt attribute, keeping the visible “Volvox” text as the
sole accessible label.

---

Outside diff comments:
In `@src/components/about.tsx`:
- Around line 3-20: Restore the prescribed organization across all sites: in
src/components/about.tsx lines 3-20, place React imports before third-party
imports and local imports; in src/components/about.tsx lines 177-197, move
BentoCardProps before setup and component logic; in
src/app/team/team-member-detail-client.tsx lines 3-31, place React and Next
imports first and declare the props type before plugin registration. Keep the
resulting structure as imports, types, constants, logic, then exports.

In `@src/components/how-we-work.tsx`:
- Around line 70-75: Update the SVG animation effect in the component’s
useEffect so it handles both preference states: pause each SVG when
reducedMotion is true and call unpauseAnimations() on each SVG when it is false.
Keep the existing containerRef query and reducedMotion dependency.
- Around line 482-488: Update the className expression on the div using pinRef
to call the shared cn() utility, passing the staticMode-dependent class values
through it instead of using a raw conditional string. Preserve the existing
classes and behavior for both static and non-static modes.
- Around line 463-479: Update the static-mode rendering in the steps component
so each step outputs its image/card and corresponding description together in a
single row or paired wrapper, rather than rendering all cards followed by all
text. Use the existing step iteration and static-mode branches around the
hww-steps-wrapper markup, and preserve the current styling while ensuring the
five static steps remain in matching order.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5abb7d0e-100a-4d1c-9595-bd7e65515f55

📥 Commits

Reviewing files that changed from the base of the PR and between 4e213a3 and 6447b0c.

📒 Files selected for processing (8)
  • content/review.json
  • src/app/globals.css
  • src/app/layout.tsx
  • src/app/team/team-member-detail-client.tsx
  • src/components/about.tsx
  • src/components/how-we-work.tsx
  • src/components/products.tsx
  • src/components/reviews.tsx
💤 Files with no reviewable changes (2)
  • src/app/layout.tsx
  • src/app/globals.css

Comment thread src/components/about.tsx
Comment thread src/components/about.tsx
Comment thread src/components/how-we-work.tsx
rabden added 2 commits July 17, 2026 09:41
…logo alt

- Gate about.tsx and team-detail-client.tsx GSAP entrance animations
  behind prefers-reduced-motion (keep final states)
- Disable MagneticButton magnetic pull under reduced-motion
- Hide hireability ping dot under reduced-motion (motion-reduce:hidden)
- Add data-testid="about-section" per coding guidelines
- Make Volvox logo in how-we-work CTA decorative (alt="")
- Skip stale claude[bot] audio comment (code no longer present)
Comment thread src/components/homepage-client.tsx
Replace legacy window.pageYOffset with modern window.scrollY
for consistency with the rest of the codebase.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Comment thread src/components/ui/button.tsx
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Signed-off-by: Hossain Jahed <rabiulhossainjahed@gmail.com>
github-actions Bot and others added 2 commits July 17, 2026 03:49
The playTactilePopSound function had two consecutive catch blocks
which is invalid syntax. Consolidated into a single catch block that
handles NotAllowedError silently and logs unexpected errors.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Insert how-we-work and reviews into NAV_ITEMS in page-scroll order so
the navbar reflects homepage section flow. Both section ids already
exist (how-we-work.tsx, reviews.tsx), so onNavigate scroll + href
fallback both work.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (2)
src/app/team/team-member-detail-client.tsx (2)

153-154: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add missing data-testid attribute to the hero section.

As per coding guidelines, src/**/*.tsx files must add data-testid attributes to key elements such as hero-section. Please add data-testid="hero-section" to the hero segment container.

🐛 Proposed fix
         {/* Hero Segment */}
-        <div className="flex flex-col md:flex-row gap-12 md:gap-16 items-start mb-24">
+        <div className="flex flex-col md:flex-row gap-12 md:gap-16 items-start mb-24" data-testid="hero-section">
🤖 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 `@src/app/team/team-member-detail-client.tsx` around lines 153 - 154, Add
data-testid="hero-section" to the Hero Segment container div in the team member
detail component, preserving its existing classes and layout.

Source: Coding guidelines


214-217: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use semantic <a> tags for navigation instead of imperative onClick handlers.

Using onClick on a <button> element to navigate degrades accessibility and breaks native browser features like middle-click to open in a new tab or copy link actions. If your Button component supports the asChild pattern (common in this UI stack), you can seamlessly render a semantic link while keeping the exact visual styling. (Applying this refactor also allows you to safely remove the handleContact and handleHire functions entirely at lines 34-44).

  • src/app/team/team-member-detail-client.tsx#L214-L217: Replace <Button onClick={handleContact}> with <Button asChild><a href={\mailto:${member.email}`}>...`.
  • src/app/team/team-member-detail-client.tsx#L222-L225: Replace with <Button asChild variant="outline"><a href={member.linkedinUrl} target="_blank" rel="noopener noreferrer">...</a></Button>.
  • src/app/team/team-member-detail-client.tsx#L380-L394: Replace the GitHub onClick button with an <a> tag rendering the icon.
  • src/app/team/team-member-detail-client.tsx#L399-L413: Replace the LinkedIn onClick button with an <a> tag rendering the icon.
  • src/app/team/team-member-detail-client.tsx#L418-L428: Replace the Email onClick button with an <a> tag rendering the icon.
🤖 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 `@src/app/team/team-member-detail-client.tsx` around lines 214 - 217, Replace
imperative navigation handlers with semantic links across
src/app/team/team-member-detail-client.tsx: at lines 214-217 use Button asChild
with a mailto anchor, at lines 222-225 use the outline Button asChild with an
external LinkedIn anchor and appropriate target/rel attributes, and at lines
380-394, 399-413, and 418-428 replace the GitHub, LinkedIn, and email onClick
buttons with anchors preserving their icons and styling. Remove the now-unused
handleContact and handleHire functions.
🤖 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 `@src/components/ui/magnetic-button.tsx`:
- Around line 29-31: Replace the repeated window.matchMedia check in
handleMouseMove with framer-motion’s useReducedMotion hook. Import and invoke
the hook within the component, then return early based on its value while
preserving the existing ref guard and mouse-move behavior.

---

Outside diff comments:
In `@src/app/team/team-member-detail-client.tsx`:
- Around line 153-154: Add data-testid="hero-section" to the Hero Segment
container div in the team member detail component, preserving its existing
classes and layout.
- Around line 214-217: Replace imperative navigation handlers with semantic
links across src/app/team/team-member-detail-client.tsx: at lines 214-217 use
Button asChild with a mailto anchor, at lines 222-225 use the outline Button
asChild with an external LinkedIn anchor and appropriate target/rel attributes,
and at lines 380-394, 399-413, and 418-428 replace the GitHub, LinkedIn, and
email onClick buttons with anchors preserving their icons and styling. Remove
the now-unused handleContact and handleHire functions.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9d7db418-38a3-457a-a27a-fb30557cb763

📥 Commits

Reviewing files that changed from the base of the PR and between 6447b0c and 1285601.

📒 Files selected for processing (6)
  • .gitignore
  • src/app/team/team-member-detail-client.tsx
  • src/components/about.tsx
  • src/components/homepage-client.tsx
  • src/components/how-we-work.tsx
  • src/components/ui/magnetic-button.tsx

Comment thread src/components/ui/magnetic-button.tsx Outdated
- Add data-testid and aria-label for accessibility/testing
- Use cn() utility for conditional className composition
- Fix SVG animation unpause when reduced motion is disabled

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Comment thread src/components/ui/button.tsx
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 17, 2026
- Increased island max-width from 850px to 1000px to accommodate 7 items.
- Marked Community and About as optional nav items.
- Optional items hidden below xl breakpoint to prevent layout breakage.
- Full nav visible at xl+ (1280px+).
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 17, 2026
Replace window.matchMedia check on every mouse move with
framer-motion's useReducedMotion hook for better performance.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@BillChirico
BillChirico merged commit 776ea62 into main Jul 17, 2026
11 checks passed
@BillChirico
BillChirico deleted the feat/reviews-how-we-work branch July 17, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants