feat: complete team section UI redesign with tabs, animations, & centered layouts#7
feat: complete team section UI redesign with tabs, animations, & centered layouts#7BeeXD wants to merge 5 commits into
Conversation
BeeXD
commented
Apr 20, 2026
✅ Deploy Preview for devhack3 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR redesigns the Team section into a tabbed, animated layout with a modal bio viewer, and re-enables the Team section in the main app navigation.
Changes:
- Replaced the previous carousel-based Team UI with a new tabbed layout and modal bio popup in
Team.tsx. - Added coin divider animation styles to
index.css. - Re-enabled
<Team />rendering and added a “Team” navbar link inApp.tsx.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.
| File | Description |
|---|---|
| src/sections/Team.tsx | Full UI rebuild: tabs, animated team cards, coin dividers, and bio modal. |
| src/index.css | Adds spinY keyframes and .coin / .animate-spin-y styles used by the new divider. |
| src/components/TeamCarousel.tsx | Removes the old carousel component (now unused). |
| src/App.tsx | Imports/renders the Team section and adds “Team” to desktop + mobile nav links. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| { top: 4, left: 4 } as React.CSSProperties, | ||
| { top: 4, right: 4 } as React.CSSProperties, | ||
| { bottom: 4, left: 4 } as React.CSSProperties, | ||
| { bottom: 4, right: 4 } as React.CSSProperties, | ||
| ].map((pos, ri) => ( |
There was a problem hiding this comment.
React.CSSProperties is referenced here, but React isn’t imported in this module. In TS this will fail to type-check. Import React (or import CSSProperties as a type) and update these casts accordingly.
| <motion.div | ||
| initial={{ opacity: 0 }} | ||
| animate={{ opacity: 1 }} | ||
| exit={{ opacity: 0 }} | ||
| className="fixed inset-0 z-50 flex items-center justify-center bg-[rgba(26,26,26,0.8)] backdrop-blur-sm p-4" |
There was a problem hiding this comment.
For accessibility, the modal overlay/container should expose dialog semantics. Consider adding role="dialog" and aria-modal="true" (and ideally associating a label via aria-labelledby).
| /> | ||
| </motion.div> | ||
| </AnimatePresence> | ||
| {/* Header block condtionally rendered */} |
There was a problem hiding this comment.
Typo in comment: “condtionally” → “conditionally”.
| {/* Header block condtionally rendered */} | |
| {/* Header block conditionally rendered */} |
| { id: '1', name: 'Trisha', role: 'Student Co ordinator', image: 'https://api.dicebear.com/9.x/pixel-art/svg?seed=Trisha' }, | ||
| { id: '2', name: 'S Shreenidhi', role: 'Student Co ordinator', image: 'https://api.dicebear.com/9.x/pixel-art/svg?seed=Shreenidhi' }, |
There was a problem hiding this comment.
Spelling in user-visible role text: “Co ordinator” should be “Coordinator” (currently shown in the card and modal).
| { id: '1', name: 'Trisha', role: 'Student Co ordinator', image: 'https://api.dicebear.com/9.x/pixel-art/svg?seed=Trisha' }, | |
| { id: '2', name: 'S Shreenidhi', role: 'Student Co ordinator', image: 'https://api.dicebear.com/9.x/pixel-art/svg?seed=Shreenidhi' }, | |
| { id: '1', name: 'Trisha', role: 'Student Coordinator', image: 'https://api.dicebear.com/9.x/pixel-art/svg?seed=Trisha' }, | |
| { id: '2', name: 'S Shreenidhi', role: 'Student Coordinator', image: 'https://api.dicebear.com/9.x/pixel-art/svg?seed=Shreenidhi' }, |
| .animate-spin-y { | ||
| animation: spinY 3s linear infinite; | ||
| } | ||
|
|
There was a problem hiding this comment.
.animate-spin-y runs an infinite animation; consider a prefers-reduced-motion: reduce override to disable/simplify it for users who prefer reduced motion.
| @media (prefers-reduced-motion: reduce) { | |
| .animate-spin-y { | |
| animation: none; | |
| } | |
| } |
| if (selectedBio) { | ||
| if (typeof window !== 'undefined') document.body.style.overflow = 'hidden'; | ||
| } else { | ||
| if (typeof window !== 'undefined') document.body.style.overflow = 'auto'; | ||
| } |
There was a problem hiding this comment.
Directly mutating document.body.style.overflow during render introduces side effects on every render and can leave the page stuck (e.g., if the component unmounts while the modal is open). Move this into a useEffect that runs when selectedBio changes and add a cleanup to restore the previous overflow value.
| className="group relative bg-[#fff9f4] border-[3px] border-[#1a1a1a] shadow-[6px_6px_0px_#1a1a1a] hover:shadow-[8px_8px_0px_#f97028] transition-all cursor-pointer flex flex-col h-full overflow-hidden w-full max-w-[280px] sm:max-w-[300px] shrink-0" | ||
| onMouseEnter={() => setIsHovered(true)} | ||
| onMouseLeave={() => setIsHovered(false)} | ||
| onClick={() => onClickBio(member)} | ||
| > |
There was a problem hiding this comment.
The card container has an onClick handler and the nested “SHOW BIO” button also triggers onClickBio. Clicking the button will bubble and invoke the handler twice. Stop propagation in the button handler, or remove one of the click handlers.
| className="group relative bg-[#fff9f4] border-[3px] border-[#1a1a1a] shadow-[6px_6px_0px_#1a1a1a] hover:shadow-[8px_8px_0px_#f97028] transition-all cursor-pointer flex flex-col h-full overflow-hidden w-full max-w-[280px] sm:max-w-[300px] shrink-0" | ||
| onMouseEnter={() => setIsHovered(true)} | ||
| onMouseLeave={() => setIsHovered(false)} | ||
| onClick={() => onClickBio(member)} | ||
| > |
There was a problem hiding this comment.
This card is interactive (click opens the modal) but it’s not keyboard accessible because it’s a div. Use a semantic button/a, or add role="button", tabIndex={0}, and handle Enter/Space key presses.
| <button | ||
| className="absolute top-4 right-4 w-10 h-10 border-2 border-[#1a1a1a] flex items-center justify-center font-bold font-mono hover:bg-[#1a1a1a] hover:text-[#f3ecd2] transition-colors" | ||
| onClick={() => setSelectedBio(null)} | ||
| > | ||
| X |
There was a problem hiding this comment.
The close button content is just "X"; add an aria-label (e.g., "Close") so screen readers announce it properly.
| <a | ||
| href={selectedBio.twitter || '#'} | ||
| target="_blank" | ||
| rel="noreferrer" | ||
| className="flex-1 py-3 border-2 border-[#1a1a1a] text-center font-bold uppercase tracking-widest hover:bg-[#1a1a1a] hover:text-[#f3ecd2] transition-colors" | ||
| > | ||
| Twitter/X | ||
| </a> | ||
| <a | ||
| href={selectedBio.linkedin || '#'} | ||
| target="_blank" | ||
| rel="noreferrer" | ||
| className="flex-1 py-3 border-2 border-[#1a1a1a] text-center font-bold uppercase tracking-widest hover:bg-[#1a1a1a] hover:text-[#f3ecd2] transition-colors" | ||
| > | ||
| </a> |
There was a problem hiding this comment.
These social links fall back to href="#" when the profile URL is missing, which is a broken UX (and still opens a new tab). Conditionally render the links only when a real URL exists, or render a disabled state.
| <a | |
| href={selectedBio.twitter || '#'} | |
| target="_blank" | |
| rel="noreferrer" | |
| className="flex-1 py-3 border-2 border-[#1a1a1a] text-center font-bold uppercase tracking-widest hover:bg-[#1a1a1a] hover:text-[#f3ecd2] transition-colors" | |
| > | |
| Twitter/X | |
| </a> | |
| <a | |
| href={selectedBio.linkedin || '#'} | |
| target="_blank" | |
| rel="noreferrer" | |
| className="flex-1 py-3 border-2 border-[#1a1a1a] text-center font-bold uppercase tracking-widest hover:bg-[#1a1a1a] hover:text-[#f3ecd2] transition-colors" | |
| > | |
| </a> | |
| {selectedBio.twitter ? ( | |
| <a | |
| href={selectedBio.twitter} | |
| target="_blank" | |
| rel="noreferrer" | |
| className="flex-1 py-3 border-2 border-[#1a1a1a] text-center font-bold uppercase tracking-widest hover:bg-[#1a1a1a] hover:text-[#f3ecd2] transition-colors" | |
| > | |
| Twitter/X | |
| </a> | |
| ) : ( | |
| <span | |
| aria-disabled="true" | |
| className="flex-1 py-3 border-2 border-[#1a1a1a] text-center font-bold uppercase tracking-widest opacity-50 cursor-not-allowed" | |
| > | |
| Twitter/X | |
| </span> | |
| )} | |
| {selectedBio.linkedin ? ( | |
| <a | |
| href={selectedBio.linkedin} | |
| target="_blank" | |
| rel="noreferrer" | |
| className="flex-1 py-3 border-2 border-[#1a1a1a] text-center font-bold uppercase tracking-widest hover:bg-[#1a1a1a] hover:text-[#f3ecd2] transition-colors" | |
| > | |
| </a> | |
| ) : ( | |
| <span | |
| aria-disabled="true" | |
| className="flex-1 py-3 border-2 border-[#1a1a1a] text-center font-bold uppercase tracking-widest opacity-50 cursor-not-allowed" | |
| > | |
| </span> | |
| )} |