Skip to content

Conversation

@aniket866
Copy link

@aniket866 aniket866 commented Nov 5, 2025

…close behavior

Closes # (optional — add issue number if there’s one)

📝 Description

This PR enhances the View Profile modal for a better user experience.
The modal now opens in a full-screen responsive layout, includes a backdrop blur for depth,
and closes automatically when users click outside the popup.

🔧 Changes Made

  • Refactored ViewProfileModal component for a wider, full-screen layout.
  • Added background overlay click-to-close functionality.
  • Improved visual hierarchy, spacing, and overall responsiveness.
  • Included a clearly visible close (X) button with pointer cursor.

📷 Screenshots or Visual Changes (if applicable)

Before:
before improvement.webm

After:

after.improvement.webm

🤝 Collaboration

Collaborated with: @aniket866 (optional)

✅ Checklist

  • I have read the contributing guidelines.
  • The feature works as intended in multiple screen sizes.
  • UI enhancements have been visually verified.
  • Code follows project style conventions.

Summary by CodeRabbit

  • UX Improvements

    • Modal now closes when clicking the overlay
    • Added dedicated close button to modal header
  • Style

    • Redesigned profile modal with improved layout and typography
    • Enhanced avatar display and profile information presentation
    • Added social media links section
    • Updated match reasons and stats grid appearance

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 5, 2025

Walkthrough

The ViewProfileModal component received a comprehensive visual redesign, transitioning from a basic modal layout to a polished, full-overlay modal with enhanced typography, spacing, and responsive design. The profile display now features larger avatars, expanded social links sections, reworked match reasons styling, and improved stats grid presentation, while maintaining the existing public API.

Changes

Cohort / File(s) Summary
ViewProfileModal UI Redesign
Frontend/src/components/collaboration-hub/ViewProfileModal.tsx
Replaced compact modal structure with full overlay backdrop, rounded scrollable container, and responsive max-width. Enhanced avatar sizing and styling (shadows, rings). Expanded typography for name/heading and added type/location subtitle. Replaced plain bio with formatted paragraph and added social links section with inline SVG icons (Instagram, YouTube, Twitter). Reworked "Why You Match" section with titled block, list styling, and bold point descriptions. Updated stats grid (Followers, Engagement, Content, Collabs) with improved layout and dark-mode colors. Replaced Connect button with centered, rounded colored button. Added overlay click handler for modal closure.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Modal as ViewProfileModal
    participant Overlay as Modal Overlay
    
    User->>Modal: Open modal / render
    Modal->>Overlay: Show with backdrop blur
    Overlay-->>Modal: Rendered
    
    alt User clicks Connect
        User->>Modal: Click Connect button
        Modal->>Modal: onConnect callback
    else User clicks overlay/close
        User->>Overlay: Click overlay area
        Overlay->>Modal: handleOverlayClick
        Modal->>Modal: Close modal
    end
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Responsive design verification: Ensure max-width and scrolling behavior work across breakpoints and screen sizes
  • Dark/light mode styling: Verify color and contrast consistency across both theme modes for all sections (stats, bio, social links)
  • Icon rendering: Validate inline SVG icons (Instagram, YouTube, Twitter) render correctly and match the design system
  • Layout spacing: Check alignment and spacing of avatar, name, subtitle, bio, social links, stats grid, and reasons section
  • Backward compatibility: Confirm prop interface unchanged and modal still closes/opens as expected

🐰 A modal once plain, now blooms so bright,
With rounded edges and backdrop's soft light!
Avatars gleam, social links dance and sway,
Why match reasons shine in every way,
This profile page hops into delight!

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main changes: a refined modal with wider layout and backdrop close functionality, matching the core objectives.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3be437 and d97492c.

📒 Files selected for processing (1)
  • Frontend/src/components/collaboration-hub/ViewProfileModal.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Frontend/src/components/collaboration-hub/ViewProfileModal.tsx (1)
Frontend/src/components/collaboration-hub/mockProfileData.ts (2)
  • mockWhyMatch (46-59)
  • mockProfileDetails (3-19)
🔇 Additional comments (7)
Frontend/src/components/collaboration-hub/ViewProfileModal.tsx (7)

6-6: LGTM!

Using the X icon from lucide-react maintains consistency with the project's icon library.


33-35: LGTM!

The overlay click handler correctly distinguishes between clicks on the backdrop versus clicks inside the modal content.


56-72: LGTM!

The header section provides clear visual hierarchy with the match percentage badge, avatar, name, and profile details appropriately styled for emphasis.


75-77: LGTM!

The bio and stats sections feature good responsive design with the grid adapting from 2 columns on mobile to 4 on larger screens, enhancing readability across devices.

Also applies to: 118-135


138-154: LGTM!

The "Why You Match" section provides clear visual separation and hierarchy with bold points followed by detailed descriptions, making the match reasoning easy to scan and understand.


157-164: LGTM!

The Connect button maintains consistent yellow accent theming and provides clear visual prominence as the primary call-to-action.


43-43: ****

The animation classes (animate-in, fade-in-0, zoom-in-95) are properly configured in this project. The codebase uses tw-animate-css (a drop-in replacement for tailwindcss-animate), which is already installed as a dependency and provides these exact utilities. These animation classes are actively used and working in multiple UI components throughout the codebase (dialog, popover, select, dropdown-menu), confirming the animations are properly configured. No action needed.

Likely an incorrect or invalid review comment.

Comment on lines +38 to +52
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm"
onClick={handleOverlayClick}
>
{/* Modal container */}
<div className="relative w-full max-w-3xl bg-white dark:bg-gray-900 rounded-3xl shadow-2xl overflow-y-auto max-h-[90vh] p-10 mx-4 animate-in fade-in-0 zoom-in-95 border border-gray-100 dark:border-gray-700">

{/* Close button */}
<button
onClick={onClose}
aria-label="Close"
className="absolute top-6 right-6 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-all"
>
<X className="h-6 w-6" />
</button>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Add essential accessibility features for the modal dialog.

The modal is missing critical accessibility features:

  1. ARIA attributes: The modal lacks role="dialog" and aria-modal="true" attributes required for screen readers
  2. Escape key support: No keyboard event handler to close the modal with the Escape key (standard UX pattern)
  3. Focus management: No focus trap to prevent keyboard navigation from leaving the modal, and no focus restoration when closed

Apply these changes to improve accessibility:

1. Add ARIA attributes to the modal container:

-      <div className="relative w-full max-w-3xl bg-white dark:bg-gray-900 rounded-3xl shadow-2xl overflow-y-auto max-h-[90vh] p-10 mx-4 animate-in fade-in-0 zoom-in-95 border border-gray-100 dark:border-gray-700">
+      <div 
+        role="dialog"
+        aria-modal="true"
+        aria-labelledby="profile-modal-title"
+        className="relative w-full max-w-3xl bg-white dark:bg-gray-900 rounded-3xl shadow-2xl overflow-y-auto max-h-[90vh] p-10 mx-4 animate-in fade-in-0 zoom-in-95 border border-gray-100 dark:border-gray-700"
+      >

2. Add Escape key handler (add after the component function opens, before the return):

   if (!open) return null;
   const profile = mockProfileDetails;

   const handleOverlayClick = (e: React.MouseEvent<HTMLDivElement>) => {
     if (e.target === e.currentTarget) onClose();
   };
+
+  React.useEffect(() => {
+    const handleEscape = (e: KeyboardEvent) => {
+      if (e.key === 'Escape') onClose();
+    };
+    document.addEventListener('keydown', handleEscape);
+    return () => document.removeEventListener('keydown', handleEscape);
+  }, [onClose]);

3. Add id to the heading for aria-labelledby:

-          <h2 className="text-3xl font-extrabold text-gray-900 dark:text-white">
+          <h2 id="profile-modal-title" className="text-3xl font-extrabold text-gray-900 dark:text-white">

Note: For focus trapping, consider using a library like focus-trap-react or implementing a custom focus trap to cycle focus within the modal.

📝 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
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm"
onClick={handleOverlayClick}
>
{/* Modal container */}
<div className="relative w-full max-w-3xl bg-white dark:bg-gray-900 rounded-3xl shadow-2xl overflow-y-auto max-h-[90vh] p-10 mx-4 animate-in fade-in-0 zoom-in-95 border border-gray-100 dark:border-gray-700">
{/* Close button */}
<button
onClick={onClose}
aria-label="Close"
className="absolute top-6 right-6 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-all"
>
<X className="h-6 w-6" />
</button>
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm"
onClick={handleOverlayClick}
>
{/* Modal container */}
<div
role="dialog"
aria-modal="true"
aria-labelledby="profile-modal-title"
className="relative w-full max-w-3xl bg-white dark:bg-gray-900 rounded-3xl shadow-2xl overflow-y-auto max-h-[90vh] p-10 mx-4 animate-in fade-in-0 zoom-in-95 border border-gray-100 dark:border-gray-700"
>
{/* Close button */}
<button
onClick={onClose}
aria-label="Close"
className="absolute top-6 right-6 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-all"
>
<X className="h-6 w-6" />
</button>
🤖 Prompt for AI Agents
Frontend/src/components/collaboration-hub/ViewProfileModal.tsx around lines 38
to 52: the modal lacks accessibility features; add role="dialog" and
aria-modal="true" to the modal container and set aria-labelledby pointing to the
modal heading (add an id to the heading), implement an Escape key handler by
adding a useEffect that listens for keydown and calls onClose when Escape is
pressed (with proper cleanup), and add focus management: either integrate
focus-trap-react around the modal content or implement a custom focus trap that
sets initial focus to the modal or first focusable element on open, cycles focus
within the modal, and restores focus to the previously focused element on close.
Ensure the Escape effect and focus management run only when the modal is open
and are cleaned up on unmount.

Comment on lines +46 to +52
<button
onClick={onClose}
aria-label="Close"
className="absolute top-6 right-6 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-all"
>
<X className="h-6 w-6" />
</button>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add cursor pointer styling to the close button.

The close button lacks cursor-pointer styling, which may not clearly indicate it's interactive to users.

Apply this diff:

-  className="absolute top-6 right-6 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-all"
+  className="absolute top-6 right-6 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-all cursor-pointer"
📝 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
<button
onClick={onClose}
aria-label="Close"
className="absolute top-6 right-6 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-all"
>
<X className="h-6 w-6" />
</button>
<button
onClick={onClose}
aria-label="Close"
className="absolute top-6 right-6 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-all cursor-pointer"
>
<X className="h-6 w-6" />
</button>
🤖 Prompt for AI Agents
In Frontend/src/components/collaboration-hub/ViewProfileModal.tsx around lines
46 to 52, the close button is missing a cursor indicator; add the Tailwind class
cursor-pointer to the button's className so the pointer changes on hover, e.g.,
append " cursor-pointer" to the existing class string (preserve existing classes
and spacing).

Comment on lines +80 to 115
<div className="flex justify-center gap-5 mb-8">
{profile.socialLinks.map((link, idx) => (
<a key={idx} href={link.url} target="_blank" rel="noopener noreferrer" className="text-gray-500 hover:text-gray-900" title={link.platform}>
{/* icon rendering handled in parent */}
<a
key={idx}
href={link.url}
target="_blank"
rel="noopener noreferrer"
title={link.platform}
className="text-gray-500 hover:text-yellow-500 transition-transform hover:scale-110"
>
{link.icon === "instagram" && (
<svg className="w-5 h-5" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24"><rect width="20" height="20" x="2" y="2" rx="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" x2="17.51" y1="6.5" y2="6.5"/></svg>
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
strokeWidth="2"
viewBox="0 0 24 24"
>
<rect width="20" height="20" x="2" y="2" rx="5" />
<path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z" />
<line x1="17.5" x2="17.51" y1="6.5" y2="6.5" />
</svg>
)}
{link.icon === "youtube" && (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M21.8 8.001a2.752 2.752 0 0 0-1.938-1.948C18.003 6 12 6 12 6s-6.003 0-7.862.053A2.752 2.752 0 0 0 2.2 8.001 28.934 28.934 0 0 0 2 12a28.934 28.934 0 0 0 .2 3.999 2.752 2.752 0 0 0 1.938 1.948C5.997 18 12 18 12 18s6.003 0 7.862-.053a2.752 2.752 0 0 0 1.938-1.948A28.934 28.934 0 0 0 22 12a28.934 28.934 0 0 0-.2-3.999zM10 15V9l5 3-5 3z"/></svg>
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path d="M21.8 8.001a2.752 2.752 0 0 0-1.938-1.948C18.003 6 12 6 12 6s-6.003 0-7.862.053A2.752 2.752 0 0 0 2.2 8.001 28.934 28.934 0 0 0 2 12a28.934 28.934 0 0 0 .2 3.999 2.752 2.752 0 0 0 1.938 1.948C5.997 18 12 18 12 18s6.003 0 7.862-.053a2.752 2.752 0 0 0 1.938-1.948A28.934 28.934 0 0 0 22 12a28.934 28.934 0 0 0-.2-3.999zM10 15V9l5 3-5 3z" />
</svg>
)}
{link.icon === "twitter" && (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53A4.48 4.48 0 0 0 22.4.36a9.09 9.09 0 0 1-2.88 1.1A4.52 4.52 0 0 0 16.11 0c-2.5 0-4.52 2.02-4.52 4.52 0 .35.04.7.11 1.03C7.69 5.4 4.07 3.67 1.64.9c-.38.65-.6 1.4-.6 2.2 0 1.52.77 2.86 1.95 3.65A4.48 4.48 0 0 1 .96 6v.06c0 2.13 1.52 3.91 3.54 4.31-.37.1-.76.16-1.16.16-.28 0-.55-.03-.81-.08.55 1.7 2.16 2.94 4.07 2.97A9.06 9.06 0 0 1 0 20.29a12.8 12.8 0 0 0 6.95 2.04c8.34 0 12.9-6.91 12.9-12.9 0-.2 0-.39-.01-.58A9.22 9.22 0 0 0 23 3z"/></svg>
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path d="M23 3a10.9 10.9 0 0 1-3.14 1.53A4.48 4.48 0 0 0 22.4.36a9.09 9.09 0 0 1-2.88 1.1A4.52 4.52 0 0 0 16.11 0c-2.5 0-4.52 2.02-4.52 4.52 0 .35.04.7.11 1.03C7.69 5.4 4.07 3.67 1.64.9c-.38.65-.6 1.4-.6 2.2 0 1.52.77 2.86 1.95 3.65A4.48 4.48 0 0 1 .96 6v.06c0 2.13 1.52 3.91 3.54 4.31-.37.1-.76.16-1.16.16-.28 0-.55-.03-.81-.08.55 1.7 2.16 2.94 4.07 2.97A9.06 9.06 0 0 1 0 20.29a12.8 12.8 0 0 0 6.95 2.04c8.34 0 12.9-6.91 12.9-12.9 0-.2 0-.39-.01-.58A9.22 9.22 0 0 0 23 3z" />
</svg>
)}
</a>
))}
</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Replace inline SVGs with lucide-react icons for consistency.

The social links use inline SVG icons while the close button uses lucide-react. This creates inconsistency and increases code duplication.

Replace the inline SVGs with lucide-react icons. First, add the imports:

-import { X } from "lucide-react";
+import { X, Instagram, Youtube, Twitter } from "lucide-react";

Then simplify the social links rendering:

           {profile.socialLinks.map((link, idx) => (
             <a
               key={idx}
               href={link.url}
               target="_blank"
               rel="noopener noreferrer"
               title={link.platform}
               className="text-gray-500 hover:text-yellow-500 transition-transform hover:scale-110"
             >
-              {link.icon === "instagram" && (
-                <svg
-                  className="w-6 h-6"
-                  fill="none"
-                  stroke="currentColor"
-                  strokeWidth="2"
-                  viewBox="0 0 24 24"
-                >
-                  <rect width="20" height="20" x="2" y="2" rx="5" />
-                  <path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z" />
-                  <line x1="17.5" x2="17.51" y1="6.5" y2="6.5" />
-                </svg>
-              )}
-              {link.icon === "youtube" && (
-                <svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
-                  <path d="M21.8 8.001a2.752 2.752 0 0 0-1.938-1.948C18.003 6 12 6 12 6s-6.003 0-7.862.053A2.752 2.752 0 0 0 2.2 8.001 28.934 28.934 0 0 0 2 12a28.934 28.934 0 0 0 .2 3.999 2.752 2.752 0 0 0 1.938 1.948C5.997 18 12 18 12 18s6.003 0 7.862-.053a2.752 2.752 0 0 0 1.938-1.948A28.934 28.934 0 0 0 22 12a28.934 28.934 0 0 0-.2-3.999zM10 15V9l5 3-5 3z" />
-                </svg>
-              )}
-              {link.icon === "twitter" && (
-                <svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
-                  <path d="M23 3a10.9 10.9 0 0 1-3.14 1.53A4.48 4.48 0 0 0 22.4.36a9.09 9.09 0 0 1-2.88 1.1A4.52 4.52 0 0 0 16.11 0c-2.5 0-4.52 2.02-4.52 4.52 0 .35.04.7.11 1.03C7.69 5.4 4.07 3.67 1.64.9c-.38.65-.6 1.4-.6 2.2 0 1.52.77 2.86 1.95 3.65A4.48 4.48 0 0 1 .96 6v.06c0 2.13 1.52 3.91 3.54 4.31-.37.1-.76.16-1.16.16-.28 0-.55-.03-.81-.08.55 1.7 2.16 2.94 4.07 2.97A9.06 9.06 0 0 1 0 20.29a12.8 12.8 0 0 0 6.95 2.04c8.34 0 12.9-6.91 12.9-12.9 0-.2 0-.39-.01-.58A9.22 9.22 0 0 0 23 3z" />
-                </svg>
-              )}
+              {link.icon === "instagram" && <Instagram className="w-6 h-6" />}
+              {link.icon === "youtube" && <Youtube className="w-6 h-6" />}
+              {link.icon === "twitter" && <Twitter className="w-6 h-6" />}
             </a>
           ))}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
Frontend/src/components/collaboration-hub/ViewProfileModal.tsx lines 80-115: the
social links currently render inline SVGs for instagram/youtube/twitter; replace
them with lucide-react icons to match the rest of the component. Import the
corresponding icons from 'lucide-react' (e.g., Instagram, Youtube, Twitter) at
the top of the file, then in the map render use the matching icon component for
each platform (pass className="w-6 h-6" or equivalent) instead of the inline
<svg> blocks, keeping the surrounding <a> props unchanged.

@aniket866 aniket866 changed the base branch from main to dev November 6, 2025 06:30
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.

1 participant