Documentation Index
Fetch the complete documentation index at: https://mintlify.com/David-Andino/github-dashboard/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The UserCard component displays comprehensive GitHub user profile information including avatar, name, bio, social links, and key statistics (repositories, followers, following, gists).
Location in UI: Left sidebar, below the header when user data is loaded
Source: ~/workspace/source/src/components/UserCard.jsx
Props
GitHub user data object returned from the GitHub API. Contains profile information and statistics.user: {
login: string, // GitHub username
name: string | null, // Display name
avatar_url: string, // Avatar image URL
html_url: string, // GitHub profile URL
bio: string | null, // User bio
company: string | null, // Company name
location: string | null, // Location
blog: string | null, // Website URL
twitter_username: string | null, // Twitter handle
public_repos: number, // Public repository count
followers: number, // Follower count
following: number, // Following count
public_gists: number // Public gist count
}
Usage Example
From App.jsx:101:
The user data is fetched in App.jsx:45-46:
const [userData, reposData] = await Promise.all([
getUser(username),
getRepos(username, 1, PER_PAGE),
])
setUser(userData)
Key Features
Displays avatar, name, and GitHub link:
<div className={styles.top}>
<img src={user.avatar_url} alt={user.login} className={styles.avatar} />
<div className={styles.info}>
<div className={styles.nameRow}>
<h2 className={styles.name}>{user.name || user.login}</h2>
<a href={user.html_url} target="_blank" rel="noreferrer" className={styles.ghLink}>
@{user.login}
</a>
</div>
{user.bio && <p className={styles.bio}>{user.bio}</p>}
{/* ... */}
</div>
</div>
Name fallback: Uses user.login if user.name is not available.
Conditionally renders social information with icons:
<div className={styles.meta}>
{user.company && (
<span className={styles.metaItem}><Building2 size={13} />{user.company}</span>
)}
{user.location && (
<span className={styles.metaItem}><MapPin size={13} />{user.location}</span>
)}
{user.blog && (
<a href={user.blog.startsWith('http') ? user.blog : `https://${user.blog}`}
target="_blank" rel="noreferrer" className={styles.metaItem}>
<Link size={13} />{user.blog.replace(/^https?:\/\//, '')}
</a>
)}
{user.twitter_username && (
<a href={`https://twitter.com/${user.twitter_username}`}
target="_blank" rel="noreferrer" className={styles.metaItem}>
<Twitter size={13} />@{user.twitter_username}
</a>
)}
</div>
Blog URL handling: Automatically prepends https:// if protocol is missing, and strips protocol from display text.
Statistics Grid
Displays four key metrics using the Stat subcomponent:
<div className={styles.stats}>
<Stat label="Repositorios" value={user.public_repos} />
<Stat label="Seguidores" value={user.followers} />
<Stat label="Siguiendo" value={user.following} />
<Stat label="Gists" value={user.public_gists} />
</div>
Subcomponents
Stat Component
Helper component for displaying individual statistics:
function Stat({ label, value }) {
return (
<div className={styles.stat}>
<span className={styles.statVal}>{value?.toLocaleString() ?? '—'}</span>
<span className={styles.statLabel}>{label}</span>
</div>
)
}
Features:
- Formats numbers with locale-specific separators (e.g.,
1000 → 1,000)
- Shows em dash (
—) if value is null/undefined
Implementation Details
Icons Used
From Lucide React:
Building2 - Company
MapPin - Location
Link - Website/blog
Twitter - Twitter handle
External Links
All external links use:
target="_blank" - Opens in new tab
rel="noreferrer" - Security best practice
Animation
Applies fade-up animation on mount:
<div className={`${styles.card} fade-up`}>
Styling
Imports modular CSS from UserCard.module.css for component-scoped styles.
Conditional Rendering
Only renders fields that have values:
- Bio displayed only if
user.bio exists
- Each metadata item checks for existence before rendering
- Statistics use
?? operator for null/undefined handling