From ad2e44b1baf3ab7850fbabe1fb54d77fe02ec598 Mon Sep 17 00:00:00 2001 From: Akshay Date: Thu, 6 Nov 2025 12:25:55 +0530 Subject: [PATCH] feat(connections): Enhance connections page with improved accessibility and UX - Add screen reader announcements for tab changes - Implement responsive tab design with mobile-friendly layouts - Add keyboard navigation support for connection stats cards - Introduce new CSS animations for smoother interactions - Enhance focus and hover states for better user engagement - Improve tab content transitions with fade-in animation - Add count animation for connection statistics - Implement touch-friendly button sizing for mobile devices Improves overall user experience and accessibility for the connections page, making navigation more intuitive and interactive across different devices. --- app/globals.css | 63 ++++++++++++++++++++++ app/protected/connections/page.tsx | 39 +++++++++----- components/connections/ConnectionStats.tsx | 30 ++++++++--- components/connections/UserCard.tsx | 21 ++++---- 4 files changed, 126 insertions(+), 27 deletions(-) diff --git a/app/globals.css b/app/globals.css index e55202fb..78dd07a7 100644 --- a/app/globals.css +++ b/app/globals.css @@ -473,3 +473,66 @@ Accessibility: Enhanced focus indicators for keyboard navigation */ .animate-shimmer { animation: shimmer 2s infinite; } + +/* Tab content animations */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fadeIn { + animation: fadeIn 0.3s ease-out; +} + +/* Count animation */ +@keyframes countUp { + from { + transform: scale(1.2); + opacity: 0; + } + to { + transform: scale(1); + opacity: 1; + } +} + +.animate-countUp { + animation: countUp 0.5s cubic-bezier(0.34, 1.56, 0.64, 1); +} + +/* Button press animation */ +@keyframes buttonPress { + 0% { + transform: scale(1); + } + 50% { + transform: scale(0.95); + } + 100% { + transform: scale(1); + } +} + +.animate-buttonPress { + animation: buttonPress 0.2s ease-in-out; +} + +/* Focus visible styles for keyboard navigation */ +.focus-visible:focus { + outline: 2px solid hsl(var(--ring)); + outline-offset: 2px; +} + +/* Touch-friendly button sizes */ +@media (max-width: 640px) { + button, a { + min-height: 44px; + min-width: 44px; + } +} diff --git a/app/protected/connections/page.tsx b/app/protected/connections/page.tsx index 873e4b26..540d82b0 100644 --- a/app/protected/connections/page.tsx +++ b/app/protected/connections/page.tsx @@ -12,9 +12,24 @@ import { ConnectionStats } from '@/components/connections/ConnectionStats' export default function ConnectionsPage() { const [searchQuery, setSearchQuery] = useState('') const [activeTab, setActiveTab] = useState('following') + const [announcement, setAnnouncement] = useState('') + + const handleTabChange = (tab: string) => { + setActiveTab(tab) + const tabNames: Record = { + following: 'Following', + followers: 'Followers', + search: 'Search' + } + setAnnouncement(`Switched to ${tabNames[tab]} tab`) + } return (
+ {/* Screen reader announcements */} +
+ {announcement} +
{/* Header */}
@@ -22,38 +37,38 @@ export default function ConnectionsPage() {

Connections

- +
{/* Main Content */}
- - - + + + - Following + Following - + - Followers + Followers - + - Search + Search - + - + - +
onTabChange?.('following')} + role="button" + tabIndex={0} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault() + onTabChange?.('following') + } + }} + aria-label={`View following list. You are following ${stats.following} users`} >
- +
-

{stats.following}

+

{stats.following}

onTabChange?.('followers')} + role="button" + tabIndex={0} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault() + onTabChange?.('followers') + } + }} + aria-label={`View followers list. You have ${stats.followers} followers`} >
- +
-

{stats.followers}

+

{stats.followers}

) diff --git a/components/connections/UserCard.tsx b/components/connections/UserCard.tsx index 38f6228f..db624cd6 100644 --- a/components/connections/UserCard.tsx +++ b/components/connections/UserCard.tsx @@ -155,10 +155,10 @@ export function UserCard({ user, connectionStatus, onConnectionChange, showMessa onClick={handleViewProfile} size="sm" variant="ghost" - className="gap-1" - title="View Profile" + className="gap-1 active:animate-buttonPress" + aria-label={`View ${name}'s profile`} > - +