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:
@@ -1,3 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "./Reveal";
|
||||
|
||||
export function About() {
|
||||
@@ -75,10 +76,12 @@ export function About() {
|
||||
style={{ minHeight: "14rem" }}
|
||||
delay={0.15}
|
||||
>
|
||||
<img
|
||||
<Image
|
||||
alt="Björn"
|
||||
src="/about-author.jpg"
|
||||
className="absolute inset-0 w-full h-full object-cover object-center pointer-events-none"
|
||||
fill
|
||||
sizes="(min-width: 768px) 58vw, 100vw"
|
||||
className="object-cover object-center pointer-events-none"
|
||||
/>
|
||||
{/* Left gradient: wide enough to cover the text-column overlap — md+ only */}
|
||||
<div className="hidden md:block absolute inset-y-0 left-0 w-72 bg-gradient-to-r from-bg-dark to-transparent pointer-events-none" />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { addToCart } from "../lib/cart";
|
||||
import { useCartFly } from "./CartFly";
|
||||
|
||||
@@ -61,7 +62,7 @@ export function AddToCartInlineButton({
|
||||
>
|
||||
{added ? "Hinzugefügt ✓" : label}
|
||||
</span>
|
||||
<img alt="" src="/icon-cart-outline.png" className="h-[1.875rem] w-8 object-contain" />
|
||||
<Image alt="" src="/icon-cart-outline.png" width={32} height={30} className="h-[1.875rem] w-8 object-contain" />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "./Reveal";
|
||||
|
||||
function Word({ children }: { children: string }) {
|
||||
@@ -16,7 +17,7 @@ function Arrow() {
|
||||
<div className="flex items-center justify-center shrink-0">
|
||||
<div className="-scale-y-100 rotate-180">
|
||||
<div className="relative" style={{ height: "var(--divider-arrow-h)", width: "var(--divider-arrow-w)" }}>
|
||||
<img alt="" src="/icon-separator.svg" className="absolute inset-0 w-full h-full" />
|
||||
<Image alt="" src="/icon-separator.svg" fill sizes="48px" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -60,7 +61,7 @@ export function Divider() {
|
||||
className="relative"
|
||||
style={{ height: "var(--divider-sparkle-inner-h)", width: "var(--divider-sparkle-inner-w)" }}
|
||||
>
|
||||
<img alt="" src="/icon-separator-right.svg" className="absolute inset-0 w-full h-full" />
|
||||
<Image alt="" src="/icon-separator-right.svg" fill sizes="48px" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -61,11 +61,7 @@ export function Hero() {
|
||||
Starte mit der 7-Tage-Challenge
|
||||
</span>
|
||||
<div className="relative h-[1.1875rem] w-[1.5625rem] shrink-0">
|
||||
<img
|
||||
alt=""
|
||||
src="/icon-check.svg"
|
||||
className="absolute inset-0 w-full h-full"
|
||||
/>
|
||||
<Image alt="" src="/icon-check.svg" fill sizes="26px" />
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { ReactNode } from "react";
|
||||
import Image from "next/image";
|
||||
import type { TOCSection } from "./SectionTOC";
|
||||
|
||||
// Minimal Lexical JSON → JSX renderer for Payload's richText fields.
|
||||
@@ -146,8 +147,8 @@ function renderNode(node: LexicalNode, key: string): ReactNode {
|
||||
return (
|
||||
<div key={key} className="relative flex items-start gap-6 w-full my-6">
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
<span className="flex h-7 w-6 items-center justify-center shrink-0">
|
||||
<img alt="" src="/icon-sparkle-merke-dir.png" className="w-full h-full object-contain" />
|
||||
<span className="relative flex h-7 w-6 items-center justify-center shrink-0">
|
||||
<Image alt="" src="/icon-sparkle-merke-dir.png" fill sizes="24px" className="object-contain" />
|
||||
</span>
|
||||
<span
|
||||
className="font-bold text-text-primary text-[1.625rem] whitespace-nowrap"
|
||||
@@ -158,9 +159,11 @@ function renderNode(node: LexicalNode, key: string): ReactNode {
|
||||
</div>
|
||||
{/* Hand-drawn underline image, not a plain bar — exported
|
||||
straight from the Figma node (label-underline). */}
|
||||
<img
|
||||
<Image
|
||||
alt=""
|
||||
src="/icon-merke-dir-underline.png"
|
||||
width={136}
|
||||
height={23}
|
||||
className="absolute left-8 top-[2.1875rem] w-[8.5rem] h-[1.4375rem] object-cover pointer-events-none"
|
||||
/>
|
||||
<div className="w-px self-stretch bg-brand shrink-0" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { Reveal, RevealGroup, RevealItem } from "./Reveal";
|
||||
import { getWerkzeugeCards } from "../lib/payload";
|
||||
|
||||
@@ -38,8 +39,8 @@ export async function Tools() {
|
||||
className="md:col-span-4 flex gap-8 items-start rounded-md transition-transform duration-300 hover:-translate-y-1"
|
||||
>
|
||||
{/* Icon — uniform box, pre-flipped/rotated source asset */}
|
||||
<div className="flex items-center justify-center shrink-0 size-14">
|
||||
<img alt="" src={tool.icon} className="max-w-full max-h-full object-contain" />
|
||||
<div className="relative flex items-center justify-center shrink-0 size-14">
|
||||
<Image alt="" src={tool.icon} fill sizes="56px" className="object-contain" />
|
||||
</div>
|
||||
|
||||
{/* Card content — self-stretch + h-full + justify-between so
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import { getTrustBadges } from "../lib/payload";
|
||||
|
||||
// Content now lives in Payload (TrustBadges collection) instead of being
|
||||
@@ -15,7 +16,9 @@ export async function TrustRow() {
|
||||
<div key={item.id} className="flex items-center gap-6 md:gap-12">
|
||||
{i > 0 && <div className="hidden md:block h-10 w-px bg-border" />}
|
||||
<div className="flex gap-4 items-center">
|
||||
<img alt="" src={item.icon} className="size-8 shrink-0 object-contain" />
|
||||
<div className="relative size-8 shrink-0">
|
||||
<Image alt="" src={item.icon} fill sizes="32px" className="object-contain" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-0.5 items-start">
|
||||
<p className="font-semibold text-body text-text-primary whitespace-nowrap">{item.title}</p>
|
||||
<p className="text-body-sm text-text-muted whitespace-nowrap">{item.description}</p>
|
||||
|
||||
Reference in New Issue
Block a user