1
0
mirror of https://github.com/avinal/avinal.github.io.git synced 2026-07-04 07:40:09 +05:30
Files
avinal.github.io/src/components/HeroCard.astro
T
avinal f5e739494a update home page hero and nav links
Assisted by Claude Code

Signed-off-by: Avinal Kumar <avinal.xlvii@gmail.com>
2026-05-02 18:18:33 +05:30

242 lines
8.9 KiB
Plaintext

---
/**
* Combined hero card: profile + about/skills + social links.
* Mirrors jay.fish's left hero section — everything about the person in one card.
*/
interface Skill {
icon: string;
title: string;
desc: string;
svgPath: string;
}
interface SocialLink {
label: string;
href: string;
icon: string;
}
interface Props {
name: string;
role: string;
bio: string;
avatarUrl?: string;
}
const { name, role, bio, avatarUrl } = Astro.props;
const about: Skill[] = [
{ icon: "cloud", title: "Cloud Native", desc: "Leading Builds for OpenShift at Red Hat", svgPath: '<path d="M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z"/>' },
{ icon: "cpu", title: "Kernel & Toolchain", desc: "Linux kernel, GCC & glibc contributor", svgPath: '<rect x="4" y="4" width="16" height="16" rx="2" ry="2"/><rect x="9" y="9" width="6" height="6"/><line x1="9" y1="1" x2="9" y2="4"/><line x1="15" y1="1" x2="15" y2="4"/><line x1="9" y1="20" x2="9" y2="23"/><line x1="15" y1="20" x2="15" y2="23"/><line x1="20" y1="9" x2="23" y2="9"/><line x1="20" y1="14" x2="23" y2="14"/><line x1="1" y1="9" x2="4" y2="9"/><line x1="1" y1="14" x2="4" y2="14"/>' },
{ icon: "code", title: "Open Source", desc: "GSoC alumnus & mentor, Campus Expert", svgPath: '<polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/>' },
{ icon: "server", title: "Self-hosting", desc: "Fedora daily driver, homelab everything", svgPath: '<rect x="2" y="2" width="20" height="8" rx="2" ry="2"/><rect x="2" y="14" width="20" height="8" rx="2" ry="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/>' },
];
const tools: Skill[] = [
{ icon: "terminal", title: "Languages", desc: "C/C++, Go, Bash", svgPath: '<polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/>' },
{ icon: "pen-tool", title: "Editor", desc: "Helix, Zellij, lazygit", svgPath: '<path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/><path d="M2 2l7.586 7.586"/><circle cx="11" cy="11" r="2"/>' },
{ icon: "settings", title: "Platforms", desc: "Fedora, Git, CMake, GitHub Actions", svgPath: '<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/>' },
];
const links: SocialLink[] = [
{ label: "GitHub", href: "https://github.com/avinal", icon: "github" },
{ label: "LinkedIn", href: "https://linkedin.com/in/avinal", icon: "linkedin" },
{ label: "Twitter", href: "https://twitter.com/Avinal_", icon: "twitter" },
{ label: "WakaTime", href: "https://wakatime.com/@avinal", icon: "wakatime" },
{ label: "RSS", href: "/rss.xml", icon: "rss" },
];
---
<div class="hero-card card">
<!-- Identity -->
<div class="hero-identity">
{avatarUrl ? (
<img src={avatarUrl} alt={name} class="hero-avatar" width="64" height="64" />
) : (
<div class="hero-avatar hero-avatar-fallback" aria-hidden="true">{name.charAt(0)}</div>
)}
<div>
<h1 class="hero-name">{name}</h1>
<p class="hero-role">{role}</p>
</div>
</div>
<p class="hero-bio">{bio}</p>
<!-- Skills columns -->
<div class="hero-skills">
<div class="skills-col">
<h3 class="col-heading">About</h3>
<ul class="skill-list">
{about.map(({ svgPath, title, desc }) => (
<li class="skill-item">
<svg class="skill-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><Fragment set:html={svgPath} /></svg>
<div>
<strong>{title}</strong>
<span class="skill-desc">{desc}</span>
</div>
</li>
))}
</ul>
</div>
<div class="skills-col">
<h3 class="col-heading">Tools & Stack</h3>
<ul class="skill-list">
{tools.map(({ svgPath, title, desc }) => (
<li class="skill-item">
<svg class="skill-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><Fragment set:html={svgPath} /></svg>
<div>
<strong>{title}</strong>
<span class="skill-desc">{desc}</span>
</div>
</li>
))}
</ul>
</div>
</div>
<!-- Social links -->
<div class="hero-links">
{links.map(({ label, href, icon }) => (
<a href={href} class="link-btn" target={href.startsWith("http") ? "_blank" : undefined} rel={href.startsWith("http") ? "noopener noreferrer" : undefined} aria-label={label}>
<svg class="link-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
{icon === "github" && <path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/>}
{icon === "linkedin" && <Fragment><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"/><rect x="2" y="9" width="4" height="12"/><circle cx="4" cy="4" r="2"/></Fragment>}
{icon === "twitter" && <path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z"/>}
{icon === "wakatime" && <Fragment><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" fill="none"/><path d="M7.5 14.5l2-4 2 3 2-5 2.5 6" stroke-linejoin="round"/></Fragment>}
{icon === "rss" && <Fragment><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="19" r="1"/></Fragment>}
</svg>
{label}
</a>
))}
</div>
</div>
<style>
.hero-card {
display: flex;
flex-direction: column;
gap: var(--space-5);
}
.hero-identity {
display: flex;
align-items: center;
gap: var(--space-4);
}
.hero-avatar {
width: 64px;
height: 64px;
border-radius: var(--radius-full);
object-fit: cover;
border: 2px solid var(--border);
flex-shrink: 0;
}
.hero-avatar-fallback {
display: flex;
align-items: center;
justify-content: center;
background-color: var(--accent);
color: white;
font-size: var(--text-2xl);
font-weight: 700;
}
.hero-name {
font-size: var(--text-xl);
margin-bottom: 2px;
}
.hero-role {
font-size: var(--text-sm);
color: var(--text-secondary);
}
.hero-bio {
color: var(--text-secondary);
font-size: var(--text-sm);
line-height: var(--leading-relaxed);
}
.hero-skills {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-6);
}
@media (max-width: 600px) {
.hero-skills { grid-template-columns: 1fr; }
}
.col-heading {
font-size: var(--text-xs);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--accent);
margin-bottom: var(--space-3);
}
.skill-list {
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.skill-item {
display: flex;
align-items: flex-start;
gap: var(--space-2);
font-size: var(--text-sm);
}
.skill-icon {
flex-shrink: 0;
margin-top: 2px;
color: var(--text-muted);
}
.skill-item strong {
font-weight: 600;
color: var(--text);
margin-right: var(--space-1);
}
.skill-desc {
color: var(--text-muted);
}
.hero-links {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
padding-top: var(--space-2);
border-top: 1px solid var(--border);
}
.link-btn {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-1) var(--space-3);
font-size: var(--text-xs);
font-weight: 500;
color: var(--text-secondary);
border: 1px solid var(--border);
border-radius: var(--radius-md);
text-decoration: none;
transition: all var(--duration-fast) var(--ease-out);
}
.link-btn:hover {
color: var(--text);
border-color: var(--border-strong);
background-color: var(--bg-surface-hover);
}
.link-icon { flex-shrink: 0; }
</style>