perf(images): convert remaining <img> tags to next/image project-wide

Clears every remaining @next/next/no-img-element warning — automatic
responsive srcset, lazy-loading, and format optimization instead of
always loading the original file at full size. Fixed-size icons got
explicit width/height; dynamic-aspect photos got fill inside a
relative wrapper.
This commit is contained in:
Marco
2026-07-21 12:44:03 +00:00
parent af00fd091f
commit 9c9f0b02c0
18 changed files with 92 additions and 42 deletions
+1 -1
View File
@@ -34,7 +34,7 @@ export function Focus() {
<ul className="flex flex-col gap-3 items-start w-full">
{bullets.map((b) => (
<li key={b} className="flex gap-[0.625rem] items-center w-full">
<img alt="" src="/icon-check.svg" className="size-5 shrink-0" />
<Image alt="" src="/icon-check.svg" width={20} height={20} className="size-5 shrink-0" />
<span className="flex-1 font-semibold text-body text-text-primary">{b}</span>
</li>
))}
+26 -14
View File
@@ -1,19 +1,29 @@
import { Fragment } from "react";
import Image from "next/image";
import { Reveal, RevealGroup, RevealItem } from "../../components/Reveal";
// Each icon's own real pixel dimensions (not uniformly square, e.g.
// icon-step-2 is 180x168) — needed so the `h-16 w-auto` sizing below infers
// the correct aspect ratio instead of stretching/squashing to a guessed one.
const steps = [
{
icon: "/icon-step-1.png",
width: 165,
height: 177,
title: "1. Aufschreiben",
desc: "Notiere deine Aufgaben und alles, was dir im Kopf herumgeht.",
},
{
icon: "/icon-step-2.png",
width: 180,
height: 168,
title: "2. Priorisieren",
desc: "Wähle deine 3 wichtigsten Aufgaben für heute aus und schreibe sie auf.",
},
{
icon: "/icon-step-3.png",
width: 180,
height: 177,
title: "3. Umsetzen",
desc: "Konzentriere dich auf das Wesentliche und hake ab, was wirklich zählt.",
},
@@ -47,21 +57,21 @@ export function HowItWorks() {
{steps.map((step, i) => (
<Fragment key={step.title}>
<RevealItem className="group flex flex-col gap-4 items-center text-center flex-1 max-w-xs md:max-w-none">
{/* Plain <img>, not next/image — one of the three source PNGs
isn't square (icon-step-2 is 68.6x64), and next/image's
required width/height props fought with Tailwind's
`img { height: auto }` preflight reset (console warning:
"width or height modified, but not the other"). A fixed
h-16 + w-auto lets each icon keep its own real aspect
ratio without that conflict — matches how every other
small decorative icon in this codebase (Tools.tsx etc.)
is already a plain <img>, not next/image. group-hover
scale is a small "step acknowledges you" touch — the
whole text column is the hover target, not just the icon,
so it's easy to trigger without precise pointing. */}
<img
{/* Explicit per-icon width/height (real pixel dimensions, not
a guessed/uniform size) — matters since one of the three
source PNGs isn't square (icon-step-2 is 180x168); passing
the real intrinsic size is what avoids next/image's
"width or height modified, but not the other" warning that
a wrong/guessed size would trigger against the `h-16
w-auto` sizing below. group-hover scale is a small "step
acknowledges you" touch — the whole text column is the
hover target, not just the icon, so it's easy to trigger
without precise pointing. */}
<Image
src={step.icon}
alt=""
width={step.width}
height={step.height}
className="h-16 w-auto object-contain transition-transform duration-300 group-hover:scale-110"
/>
<p className="font-semibold text-body text-text-primary">{step.title}</p>
@@ -73,9 +83,11 @@ export function HowItWorks() {
// — same margin-based centering technique as Challenge's
// step connector, not just the same icon asset.
<div className="flex items-center justify-center shrink-0 md:mt-[1.625rem]">
<img
<Image
alt=""
src="/icon-arrow-connector.svg"
width={24}
height={24}
className="w-6 h-6 rotate-90 md:w-10 md:h-3 md:rotate-0"
/>
</div>