Spaces:
Sleeping
Sleeping
File size: 4,598 Bytes
0a8fe79 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | import React from 'react';
function ServerIcon({ server, isActive, onClick }) {
const initials = server.name
.split(' ')
.map((w) => w[0])
.slice(0, 2)
.join('')
.toUpperCase();
return (
<div className="relative flex items-center justify-center mb-2 group">
{/* Active indicator bar */}
<div
className={`absolute left-0 w-1 rounded-r-full bg-[#FFD700] transition-all duration-200 ${
isActive ? 'h-10' : 'h-0 group-hover:h-5'
}`}
/>
<button
onClick={onClick}
title={server.name}
className={`w-12 h-12 flex items-center justify-center transition-all duration-200 overflow-hidden ${
isActive
? 'rounded-2xl bg-[#FFD700]'
: 'rounded-full hover:rounded-2xl bg-[#2f2f35] hover:bg-[#FFD700]'
}`}
>
{server.icon ? (
<img
src={server.icon}
alt={server.name}
className="w-full h-full object-cover"
/>
) : (
<span
className={`text-sm font-bold transition-colors duration-200 ${
isActive ? 'text-[#0e0e10]' : 'text-gray-300 group-hover:text-[#0e0e10]'
}`}
>
{initials}
</span>
)}
</button>
</div>
);
}
export default function ServerList({
servers,
activeServer,
onSelectServer,
onOpenDMs,
onCreateServer,
onOpenUserSettings,
user,
}) {
const dmActive = activeServer === null;
return (
<div className="w-[72px] bg-[#111114] flex flex-col items-center py-3 overflow-y-auto scrollbar-hide">
{/* DM Button */}
<div className="relative flex items-center justify-center mb-2 group">
<div
className={`absolute left-0 w-1 rounded-r-full bg-[#FFD700] transition-all duration-200 ${
dmActive ? 'h-10' : 'h-0 group-hover:h-5'
}`}
/>
<button
onClick={onOpenDMs}
title="Direct Messages"
className={`w-12 h-12 flex items-center justify-center transition-all duration-200 ${
dmActive
? 'rounded-2xl bg-[#FFD700]'
: 'rounded-full hover:rounded-2xl bg-[#2f2f35] hover:bg-[#FFD700]'
}`}
>
<svg
className={`w-6 h-6 transition-colors duration-200 ${
dmActive ? 'text-[#0e0e10]' : 'text-gray-300 group-hover:text-[#0e0e10]'
}`}
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H5.17L4 17.17V4h16v12z" />
<path d="M7 9h2v2H7zm4 0h2v2h-2zm4 0h2v2h-2z" />
</svg>
</button>
</div>
{/* Divider */}
<div className="w-8 h-0.5 bg-[#FFD700]/30 rounded-full mb-2" />
{/* Server Icons */}
<div className="flex-1 w-full flex flex-col items-center overflow-y-auto scrollbar-hide">
{servers.map((server) => (
<ServerIcon
key={server.id}
server={server}
isActive={activeServer?.id === server.id}
onClick={() => onSelectServer(server)}
/>
))}
</div>
{/* Divider */}
<div className="w-8 h-0.5 bg-[#2f2f35] rounded-full my-2" />
{/* Create Server Button */}
<button
onClick={onCreateServer}
title="Create a Server"
className="w-12 h-12 rounded-full bg-[#2f2f35] hover:bg-[#22c55e] hover:rounded-2xl flex items-center justify-center transition-all duration-200 group mb-2"
>
<svg
className="w-6 h-6 text-[#22c55e] group-hover:text-white transition-colors duration-200"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
strokeWidth={2}
>
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4v16m8-8H4" />
</svg>
</button>
{/* User Avatar */}
<button
onClick={onOpenUserSettings}
title={user?.username || 'Settings'}
className="w-12 h-12 rounded-full overflow-hidden bg-[#2f2f35] hover:rounded-2xl transition-all duration-200 flex items-center justify-center"
>
{user?.avatar ? (
<img
src={user.avatar}
alt={user.username}
className="w-full h-full object-cover"
/>
) : (
<span className="text-sm font-bold text-gray-300">
{user?.username?.charAt(0)?.toUpperCase() || '?'}
</span>
)}
</button>
</div>
);
}
|