Files
supabase/apps/www/components/Contribute/GithubAvatar.tsx
0b8db9adc1 Feat(www)/contribute (#40966)
* Rough contribute ui

* Clean up filter area

* Tweak query with new threads schema

* Unify table and apply some ui nits

* Fix types issues

* Setup types

* FilterS

* Fix filters

* Make search global

* Add icons for table rows

* Add single thread view

* Loading state for threads

* Fix icon colors

* Add leaderboard

* Fix conversation text overflow and add op badge

* Rename leaderboard

* Turn of leaderboard

* Formatting

* Remove other from product areas

* And from stacks

* Prettier types

* Start contribute/about

* About cards

* Add avatar component

* Polish up about page

* Nudges

* Add application form

* Add squad form

* Change to last 30 days instead of 24hrs

* Responsive nudges

* Format components for conversation view

* Re use ui components on about page

* Fix prettier errors

* Filter nudges

* chore(www): improve contribute UI (#41481)

* hero tweaks

* better table

* wrap post time

* nip and tuck

* use table component

* use table component

* Add menu item

* Alan/polish contribute filtering UI (#41504)

* polishing tabs

* nits in tables

* nit in filtering

* nits

* ship it

* fix selection style

* nit search bar

* Add view for authors

* Format author page

* Add contribute menu item

* Tidy up about page

* More about page edits

* Update

* basics

* copy cleanup

* improvements to thread table

* threads improvements

* remove extraneous div

* thread improvements

* chore(www): improve contribute UI (#41605)

* basics

* improvements to thread table

* threads improvements

* remove extraneous div

* thread improvements

* Add feature flag for contribute page

* Add feature flag for contribute page

* Fix ts error

* Thread view nudges

* Undo env change

* Cleanup

* Cleanup

* Typos

---------

Co-authored-by: Tomas Pozo <tomaspozogarzon@gmail.com>
Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
Co-authored-by: Alan Daniel <stylesshjs@gmail.com>
2026-01-07 14:48:23 -03:30

56 lines
1.7 KiB
TypeScript

'use client'
import Image from 'next/image'
import Link from 'next/link'
import { useState } from 'react'
interface GithubAvatarProps {
username: string
size?: number
className?: string
}
// Basic username validation - GitHub usernames must be alphanumeric with hyphens/underscores
function isValidGithubUsername(username: string): boolean {
if (!username || username.trim().length === 0) return false
// GitHub username rules: alphanumeric, hyphens, underscores, no consecutive hyphens/underscores, max 39 chars
const githubUsernameRegex = /^[a-zA-Z0-9]([a-zA-Z0-9]|-(?!-)|_(?!_))*[a-zA-Z0-9]?$/
return username.length <= 39 && githubUsernameRegex.test(username)
}
export function GithubAvatar({ username, size = 80, className }: GithubAvatarProps) {
const [imageError, setImageError] = useState(false)
const [imageSrc, setImageSrc] = useState(`https://github.com/${username}.png`)
// Validate username and use fallback if invalid
const isValid = isValidGithubUsername(username)
const fallbackSrc = isValid
? `https://github.com/identicons/${username}.png`
: '/images/blog/blog-placeholder.png'
const handleImageError = () => {
if (!imageError) {
setImageError(true)
setImageSrc(fallbackSrc)
}
}
return (
<Link
href={`https://github.com/${username}`}
target="_blank"
rel="noreferrer"
className="group relative"
>
<Image
src={imageSrc}
alt={`${username}'s GitHub avatar`}
width={size}
height={size}
className={`${className} transition-all duration-200 group-hover:scale-110 group-hover:ring-2 group-hover:ring-brand-500 group-hover:ring-offset-2 group-hover:ring-offset-background`}
onError={handleImageError}
/>
</Link>
)
}