Files
portfolio/app/components/Hero.tsx
T
denshooter 96ec2d867f feat: plakat redesign phase 1 (tokens, fonts, poster hero, header) (#74)
- New design tokens: signal red, ink and paper as RGB channels; ink and paper
  swap roles in dark mode so every component inverts cleanly
- Fonts via next/font: Bricolage Grotesque (with wdth/opsz axes), Geist,
  Geist Mono; drop Inter and Playfair
- Poster hero: kicker, giant DK0 wordmark that reacts to pointer distance
  (weight and width through a damped spring, desktop only, off for reduced
  motion), claim as h1, intro with thesis countdown, marquee strip
- Header in poster style: transparent over the red hero, paper strip with
  ink rule when scrolled or on subpages; drawer menu restyled
- Remove wavy SVG separators, CSS shader gradient, background blobs and
  unused providers that caused the pink/purple bands between sections
- Drop the global p/span/div color override so colors inherit properly
- New hero texts in de/en, tests and i18n key check updated

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 23:48:39 +02:00

68 lines
2.9 KiB
TypeScript

import { getTranslations } from "next-intl/server";
import KineticWordmark from "./KineticWordmark";
interface HeroProps {
locale: string;
}
// Abgabe der Masterarbeit, Grundlage für den Countdown im Intro
const THESIS_DEADLINE = new Date("2027-02-15T12:00:00+01:00");
const MARQUEE = ["Self-Hosting", "Next.js", "SwiftUI", "Flutter", "Docker", "Microsoft 365", "Godot", "Home Assistant"];
export default async function Hero({ locale }: HeroProps) {
const t = await getTranslations({ locale, namespace: "home.hero" });
const daysLeft = Math.max(0, Math.ceil((THESIS_DEADLINE.getTime() - Date.now()) / 86_400_000));
return (
<>
<section id="top" className="relative overflow-hidden bg-signal px-4 pt-24 text-ink sm:px-6 md:pt-28 lg:px-10">
<p className="font-mono text-[13px] leading-snug">{t("kicker")}</p>
<div className="mt-4 sm:mt-8">
<KineticWordmark />
</div>
<div className="mt-3 grid gap-6 border-t-2 border-ink pb-8 pt-6 md:grid-cols-[1.3fr_1fr] md:items-end md:pb-10">
<h1 className="text-balance font-display text-[clamp(2rem,4.4vw,4rem)] font-extrabold leading-[0.96] tracking-[-0.035em] [font-variation-settings:'wdth'_85]">
<span className="sr-only">Dennis Konkol: </span>
{t("claim")}
</h1>
<div>
<p className="max-w-[42ch] text-[17px] leading-relaxed">
{t("intro")} {daysLeft > 0 && t("countdown", { days: daysLeft })}
</p>
<div className="mt-5 flex flex-wrap gap-2.5">
<a
href="#projects"
className="inline-flex items-center gap-2 rounded-full bg-ink px-5 py-3.5 text-[15px] font-semibold text-paper transition-transform duration-150 ease-out active:scale-[0.97]"
>
{t("ctaWork")} <span aria-hidden="true">↓</span>
</a>
<a
href="#contact"
className="inline-flex items-center rounded-full px-5 py-3.5 text-[15px] font-semibold shadow-[inset_0_0_0_1.5px_rgb(var(--plakat-ink))] transition-[background-color,color,transform] duration-150 ease-out hover:bg-ink hover:text-signal active:scale-[0.97]"
>
{t("ctaContact")}
</a>
</div>
</div>
</div>
</section>
<div className="overflow-hidden bg-ink text-paper" aria-hidden="true">
<div className="flex w-max animate-marquee gap-9 py-[18px] font-display text-[clamp(1.1rem,2.4vw,1.7rem)] font-bold leading-none">
{[...MARQUEE, ...MARQUEE].map((item, i) => (
<span key={i} className="flex items-center gap-9 whitespace-nowrap">
{item}
<svg viewBox="0 0 24 24" className="h-[0.7em] w-[0.7em] fill-signal">
<path d="M12 1.5l2.6 7.9 7.9 2.6-7.9 2.6-2.6 7.9-2.6-7.9-7.9-2.6 7.9-2.6z" />
</svg>
</span>
))}
</div>
</div>
</>
);
}