Files
portfolio/src/components/ProjectCard.astro
Johan LEROY 155ab2977f
All checks were successful
Deploy production / build-deploy (push) Successful in 24s
feat(stack): grille complète (71 technos) en masonry centré + peaufinage UI
Stack & icônes
- grille unique enrichie (+24 technos) : React, TypeORM, Apache, Gitea,
  GitLab, GitHub Actions, Vite, pnpm, Socket.io, Chart.js, Discord.js,
  Prisma, Sequelize, IntelliJ IDEA, VS Code, Windows, HubSpot, HTML5/CSS3…
- nouvelles catégories « Bases de données & ORM » et « Tests & Qualité »
- 21 icônes simple-icons + tracés monochromes custom VS Code, Windows,
  Playwright ; support du fill-rule dans TechIcon
- mise en page masonry (CSS columns) + titres et puces centrés

Contenu & UI
- Hero : retrait du badge « ouvert aux opportunités »
- About / Contact : reformulation orientée projets
- ProjectCard : statut « en développement »
- typographie : tirets cadratins → virgules (titres, OG, aria-labels)
- ajout du visuel public/images/logo/couverture.png
2026-06-27 13:46:53 +02:00

51 lines
1.8 KiB
Plaintext

---
import Icon from "./Icon.astro";
import type { Project } from "../data/content";
const STATUS: Record<Project["status"], { label: string; color: string }> = {
live: { label: "en ligne", color: "var(--accent)" },
dev: { label: "en développement", color: "var(--warn)" },
archived: { label: "archivé", color: "var(--text-dim)" },
oss: { label: "open-source", color: "var(--info)" },
};
interface Props { project: Project; }
const { project: p } = Astro.props;
const st = STATUS[p.status];
const mono = p.title.replace(/[^A-Za-z0-9]/g, "").slice(0, 2);
// Toute la carte devient cliquable (nouvel onglet) dès qu'un lien est défini.
const Tag = p.link ? "a" : "article";
const linkAttrs = p.link
? { href: p.link, target: "_blank", rel: "noopener", "aria-label": `${p.title}, voir le projet (nouvel onglet)` }
: {};
---
<Tag class:list={["card", p.link && "card--link"]} {...linkAttrs}>
<div class:list={["card-media", p.imgDark && "card-media--themed"]}>
{p.img ? (
<>
<img class="logo-light" src={p.img} alt={p.title} loading="lazy" />
{p.imgDark && <img class="logo-dark" src={p.imgDark} alt={p.title} loading="lazy" />}
</>
) : (
<div class="card-mono"><span>{mono}</span></div>
)}
</div>
<div class="card-body">
<div class="card-head">
<span class="status"><span class="status-dot" style={`background:${st.color}`}></span>{st.label}</span>
{p.link && (
<span class="ext-link" aria-hidden="true">
<Icon name="external" size={16} />
</span>
)}
</div>
<h3 class="card-title">{p.title}</h3>
<p class="card-sub">{p.subtitle}</p>
<p class="card-desc">{p.desc}</p>
<div class="chips">
{p.stack.map((s) => <span class="chip">{s}</span>)}
</div>
</div>
</Tag>