5
5
getPersonsMaintainerOf ,
6
6
} from '~/libraries/maintainers'
7
7
import { useState } from 'react'
8
+ // import { FaCode, FaGitAlt, FaComment, FaEye } from 'react-icons/fa'
8
9
9
10
function RoleBadge ( {
10
11
maintainer,
@@ -187,6 +188,69 @@ function MaintainerSocialLinks({ maintainer }: { maintainer: Maintainer }) {
187
188
)
188
189
}
189
190
191
+ // GitHub stats component - commented out due to performance/accuracy concerns
192
+ /*
193
+ function GitHubStats({
194
+ username,
195
+ stats,
196
+ }: {
197
+ username: string
198
+ stats?: {
199
+ totalCommits: number
200
+ totalPullRequests: number
201
+ totalIssues: number
202
+ totalReviews: number
203
+ }
204
+ }) {
205
+ if (!stats) return null
206
+
207
+ const totalContributions =
208
+ stats.totalCommits +
209
+ stats.totalPullRequests +
210
+ stats.totalIssues +
211
+ stats.totalReviews
212
+
213
+ return (
214
+ <div className="flex items-center gap-4 text-sm text-gray-600 dark:text-gray-400">
215
+ <div
216
+ className="flex items-center gap-1"
217
+ title="Total commits to TanStack repositories"
218
+ >
219
+ <FaCode className="w-3 h-3" />
220
+ <span>{stats.totalCommits.toLocaleString()}</span>
221
+ </div>
222
+ <div
223
+ className="flex items-center gap-1"
224
+ title="Total pull requests to TanStack repositories"
225
+ >
226
+ <FaGitAlt className="w-3 h-3" />
227
+ <span>{stats.totalPullRequests.toLocaleString()}</span>
228
+ </div>
229
+ <div
230
+ className="flex items-center gap-1"
231
+ title="Total issues opened in TanStack repositories"
232
+ >
233
+ <FaComment className="w-3 h-3" />
234
+ <span>{stats.totalIssues.toLocaleString()}</span>
235
+ </div>
236
+ <div
237
+ className="flex items-center gap-1"
238
+ title="Total pull request reviews in TanStack repositories"
239
+ >
240
+ <FaEye className="w-3 h-3" />
241
+ <span>{stats.totalReviews.toLocaleString()}</span>
242
+ </div>
243
+ <div
244
+ className="text-xs text-gray-500 dark:text-gray-500"
245
+ title="Total contributions to TanStack repositories"
246
+ >
247
+ {totalContributions.toLocaleString()} total
248
+ </div>
249
+ </div>
250
+ )
251
+ }
252
+ */
253
+
190
254
interface MaintainerCardProps {
191
255
maintainer : Maintainer
192
256
libraryId ?: Library [ 'id' ]
@@ -196,6 +260,17 @@ interface CompactMaintainerCardProps {
196
260
maintainer : Maintainer
197
261
}
198
262
263
+ interface MaintainerRowCardProps {
264
+ maintainer : Maintainer
265
+ libraryId ?: Library [ 'id' ]
266
+ stats ?: {
267
+ totalCommits : number
268
+ totalPullRequests : number
269
+ totalIssues : number
270
+ totalReviews : number
271
+ }
272
+ }
273
+
199
274
export function CompactMaintainerCard ( {
200
275
maintainer,
201
276
} : CompactMaintainerCardProps ) {
@@ -226,6 +301,119 @@ export function CompactMaintainerCard({
226
301
)
227
302
}
228
303
304
+ export function MaintainerRowCard ( {
305
+ maintainer,
306
+ libraryId,
307
+ stats,
308
+ } : MaintainerRowCardProps ) {
309
+ const libraries = getPersonsMaintainerOf ( maintainer )
310
+ const [ showAllLibraries , setShowAllLibraries ] = useState ( false )
311
+
312
+ return (
313
+ < div
314
+ className = "group bg-white dark:bg-gray-800 rounded-lg overflow-hidden shadow-lg w-full"
315
+ aria-label = { `Maintainer row card for ${ maintainer . name } ` }
316
+ >
317
+ < div className = "flex items-center gap-4 p-4" >
318
+ { /* Avatar Section */ }
319
+ < a
320
+ href = { `https://github.com/${ maintainer . github } ` }
321
+ target = "_blank"
322
+ rel = "noopener noreferrer"
323
+ aria-label = { `View ${ maintainer . name } 's GitHub profile` }
324
+ className = "relative flex-shrink-0"
325
+ tabIndex = { 0 }
326
+ >
327
+ < div className = "relative w-16 h-16 rounded-lg overflow-hidden" >
328
+ < img
329
+ alt = { `Avatar of ${ maintainer . name } ` }
330
+ className = "w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
331
+ src = { maintainer . avatar }
332
+ loading = "lazy"
333
+ decoding = "async"
334
+ />
335
+ < div className = "absolute inset-0 bg-gradient-to-t from-black/40 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
336
+ </ div >
337
+ </ a >
338
+
339
+ { /* Main Content */ }
340
+ < div className = "flex-1 min-w-0 overflow-hidden" >
341
+ < div className = "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2" >
342
+ < div className = "flex items-center gap-3" >
343
+ < span
344
+ className = "text-lg font-bold truncate"
345
+ id = { `maintainer-name-${ maintainer . github } ` }
346
+ >
347
+ { maintainer . name }
348
+ </ span >
349
+ { libraryId && (
350
+ < RoleBadge maintainer = { maintainer } libraryId = { libraryId } />
351
+ ) }
352
+ </ div >
353
+
354
+ < div className = "flex items-center gap-2" >
355
+ < MaintainerSocialLinks maintainer = { maintainer } />
356
+ </ div >
357
+ </ div >
358
+
359
+ { /* All Pills Inline */ }
360
+ { ( ( maintainer . frameworkExpertise &&
361
+ maintainer . frameworkExpertise . length > 0 ) ||
362
+ ( maintainer . specialties && maintainer . specialties . length > 0 ) ||
363
+ ( ! libraryId && libraries . length > 0 ) ) && (
364
+ < div className = "flex flex-wrap gap-2 mt-2 max-w-full" >
365
+ { /* Framework chips */ }
366
+ { maintainer . frameworkExpertise &&
367
+ maintainer . frameworkExpertise . length > 0 &&
368
+ maintainer . frameworkExpertise . map ( ( framework ) => (
369
+ < FrameworkChip key = { framework } framework = { framework } />
370
+ ) ) }
371
+
372
+ { /* Specialty chips */ }
373
+ { maintainer . specialties &&
374
+ maintainer . specialties . length > 0 &&
375
+ maintainer . specialties . map ( ( specialty ) => (
376
+ < SpecialtyChip key = { specialty } specialty = { specialty } />
377
+ ) ) }
378
+
379
+ { /* Library badges */ }
380
+ { ! libraryId &&
381
+ libraries . length > 0 &&
382
+ libraries
383
+ . slice ( 0 , showAllLibraries ? undefined : 2 )
384
+ . map ( ( library ) => (
385
+ < LibraryBadge key = { library . id } library = { library } />
386
+ ) ) }
387
+
388
+ { /* Show more button */ }
389
+ { ! libraryId && ! showAllLibraries && libraries . length > 2 && (
390
+ < button
391
+ onClick = { ( e ) => {
392
+ e . preventDefault ( )
393
+ e . stopPropagation ( )
394
+ setShowAllLibraries ( true )
395
+ } }
396
+ className = "inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-colors focus:outline-none focus:ring-2 focus:ring-blue-400"
397
+ aria-label = { `Show ${ libraries . length - 2 } more libraries` }
398
+ tabIndex = { 0 }
399
+ type = "button"
400
+ >
401
+ +{ libraries . length - 2 } more
402
+ </ button >
403
+ ) }
404
+ </ div >
405
+ ) }
406
+
407
+ { /* GitHub Stats - commented out due to performance/accuracy concerns */ }
408
+ { /* <div className="mt-4">
409
+ <GitHubStats username={maintainer.github} stats={stats} />
410
+ </div> */ }
411
+ </ div >
412
+ </ div >
413
+ </ div >
414
+ )
415
+ }
416
+
229
417
export function MaintainerCard ( { maintainer, libraryId } : MaintainerCardProps ) {
230
418
const libraries = getPersonsMaintainerOf ( maintainer )
231
419
const [ showAllLibraries , setShowAllLibraries ] = useState ( false )
@@ -240,7 +428,7 @@ export function MaintainerCard({ maintainer, libraryId }: MaintainerCardProps) {
240
428
target = "_blank"
241
429
rel = "noopener noreferrer"
242
430
aria-label = { `View ${ maintainer . name } 's GitHub profile` }
243
- className = "relative h-64 overflow block"
431
+ className = "relative h-64 overflow-hidden block"
244
432
tabIndex = { 0 }
245
433
>
246
434
< img
0 commit comments