Repository Public
1/*2 platform-links.tsx3 spboucher.ai Web4 Author: Simon-Pierre Boucher5 Mail: contact@spboucher.ai6*/78import { Cpu, Library, PenLine, Sparkles, type LucideIcon } from "lucide-react";910import { cn } from "@/lib/utils";1112/** Sister sites, shown as icon links on the home page and in the footer. */13export const platformLinks: {14 href: string;15 label: string;16 hint: string;17 icon: LucideIcon;18}[] = [19 {20 href: "https://maclustr.spboucher.ai",21 label: "MacLustr",22 hint: "Apple Silicon compute cluster",23 icon: Cpu,24 },25 {26 href: "https://wp.spboucher.ai",27 label: "Papers",28 hint: "Research observatory and interactive reader",29 icon: Library,30 },31 {32 href: "https://htr.spboucher.ai",33 label: "HTR",34 hint: "Human Text Reconstruction",35 icon: PenLine,36 },37 {38 href: "https://skills.spboucher.ai",39 label: "Skills",40 hint: "Skills library",41 icon: Sparkles,42 },43];4445/** `tiles`: labelled icon tiles (home hero). `icons`: compact icon-only squares (footer). */46export function PlatformLinks({47 variant = "tiles",48 className,49}: {50 variant?: "tiles" | "icons";51 className?: string;52}) {53 if (variant === "icons") {54 return (55 <>56 {platformLinks.map(({ href, label, hint, icon: Icon }) => (57 <a58 key={href}59 href={href}60 target="_blank"61 rel="noopener noreferrer"62 aria-label={`${label} — ${hint}`}63 title={`${label} — ${hint}`}64 className="inline-flex h-8 w-8 items-center justify-center border border-foreground/15 bg-card text-muted-foreground transition-all hover:-translate-y-px hover:border-foreground/50 hover:text-foreground"65 >66 <Icon className="h-3.5 w-3.5" aria-hidden="true" />67 </a>68 ))}69 </>70 );71 }72 return (73 <nav74 aria-label="Platforms"75 className={cn("grid grid-cols-2 gap-2 sm:grid-cols-4", className)}76 >77 {platformLinks.map(({ href, label, hint, icon: Icon }) => (78 <a79 key={href}80 href={href}81 target="_blank"82 rel="noopener noreferrer"83 title={hint}84 className="group flex items-center gap-2.5 border border-foreground/15 bg-card px-3 py-2.5 transition-all hover:-translate-y-px hover:border-primary/60 hover:shadow-sm"85 >86 <span className="inline-flex h-8 w-8 shrink-0 items-center justify-center border border-primary/25 bg-primary/5 text-primary transition-colors group-hover:bg-primary group-hover:text-primary-foreground">87 <Icon className="h-4 w-4" aria-hidden="true" />88 </span>89 <span className="min-w-0">90 <span className="block truncate text-sm font-medium leading-tight">91 {label}92 </span>93 <span className="block truncate font-mono text-[0.6rem] uppercase tracking-[0.12em] text-muted-foreground">94 {href.replace("https://", "").replace(".spboucher.ai", "")}95 </span>96 </span>97 </a>98 ))}99 </nav>100 );101}102