Fix svg loading issues

This commit is contained in:
adilallo
2026-05-26 08:40:01 -06:00
parent edda28f95b
commit 2871df27b2
5 changed files with 61 additions and 22 deletions
+1
View File
@@ -49,6 +49,7 @@ export default function Page() {
description: t("pages.home.heroBanner.description"),
ctaText: t("pages.home.heroBanner.ctaText"),
ctaHref: t("pages.home.heroBanner.ctaHref"),
imageAlt: t("heroBanner.imageAlt"),
};
const cardStepsData = {
@@ -45,19 +45,22 @@ function CaseStudyView({
return (
<div
data-figma-node="21993-32352"
className={`relative flex h-[305px] w-[305px] shrink-0 overflow-hidden ${CASE_TILE_RADIUS_CLASS} ${SURFACE_CLASS[surface]} ${className}`.trim()}
className={`relative h-[305px] w-[305px] shrink-0 overflow-hidden ${CASE_TILE_RADIUS_CLASS} ${SURFACE_CLASS[surface]} ${className}`.trim()}
>
{visual ? (
<div className="flex size-full items-center justify-center p-2">{visual}</div>
) : (
<div className="absolute inset-0">
<Art
role="img"
aria-label={imageAlt}
data-case-study-art={SURFACE_ART_DATA_KEY[surface]}
width={305}
height={305}
className="pointer-events-none size-full select-none object-contain object-center"
width="100%"
height="100%"
className="pointer-events-none block select-none"
preserveAspectRatio="xMidYMid meet"
/>
</div>
)}
</div>
);
@@ -1,12 +1,9 @@
"use client";
/**
* Figma: "Sections / Hero" (see registry)
*/
import { memo } from "react";
import Image from "next/image";
import { useTranslation } from "../../../contexts/MessagesContext";
import ContentLockup from "../../type/ContentLockup";
import HeroDecor from "./HeroDecor";
import { ASSETS, getAssetPath } from "../../../../lib/assetUtils";
@@ -25,13 +22,18 @@ interface HeroBannerProps {
description?: string;
ctaText?: string;
ctaHref?: string;
imageAlt?: string;
}
const HeroBanner = memo<HeroBannerProps>(
({ title, subtitle, description, ctaText, ctaHref }) => {
const t = useTranslation();
const imageAlt = t("heroBanner.imageAlt");
({
title,
subtitle,
description,
ctaText,
ctaHref,
imageAlt = "Hero illustration",
}) => {
return (
<section className="bg-transparent px-[var(--spacing-scale-008)] sm:px-[var(--spacing-scale-010)] md:px-[var(--spacing-scale-016)] lg:px-[var(--spacing-scale-024)] xl:px-[var(--spacing-scale-048)]">
<div className="flex flex-col gap-[var(--spacing-scale-010)]">
@@ -58,7 +60,7 @@ const HeroBanner = memo<HeroBannerProps>(
</div>
{/* Hero Image Container */}
<div className="w-full h-full md:flex-1 rounded-[8px] overflow-hidden relative z-10 flex items-center justify-center">
<div className="relative z-10 flex w-full items-center justify-center overflow-hidden rounded-[8px] aspect-[16/10] md:flex-1">
<Image
src={getAssetPath(ASSETS.HERO_IMAGE)}
alt={imageAlt}
@@ -66,7 +68,7 @@ const HeroBanner = memo<HeroBannerProps>(
height={HERO_IMAGE_HEIGHT}
priority
sizes="(min-width: 768px) 50vw, 100vw"
className="w-full h-auto"
className="size-full object-contain"
/>
</div>
</div>
@@ -1,12 +1,23 @@
"use client";
import { memo } from "react";
import { memo, useEffect, useState } from "react";
interface HeroDecorProps {
className?: string;
}
const HeroDecor = memo<HeroDecorProps>(({ className = "" }) => {
const [grainEnabled, setGrainEnabled] = useState(false);
useEffect(() => {
// feTurbulence forces tiled rasterization that reads as top-down segments on
// first paint. Flat shapes render immediately; grain applies after paint.
const frame = requestAnimationFrame(() => {
setGrainEnabled(true);
});
return () => cancelAnimationFrame(frame);
}, []);
return (
<svg
className={`text-[var(--color-surface-default-brand-lighter-accent)] opacity-50 ${className}`}
@@ -59,7 +70,7 @@ const HeroDecor = memo<HeroDecorProps>(({ className = "" }) => {
</defs>
{/* apply filter only to the decoration paths */}
<g fill="currentColor" filter="url(#grain)">
<g fill="currentColor" filter={grainEnabled ? "url(#grain)" : undefined}>
<path d="M1441.54 226.758C1495.92 226.758 1540 320.385 1540 435.879C1540 551.373 1495.92 645 1441.54 645C1387.16 645 1343.08 551.373 1343.08 435.879C1343.08 320.385 1387.16 226.758 1441.54 226.758Z" />
<path d="M1441.54 226.758C1495.92 226.758 1540 320.385 1540 435.879C1540 551.373 1495.92 645 1441.54 645C1387.16 645 1343.08 551.373 1343.08 435.879C1343.08 320.385 1387.16 226.758 1441.54 226.758Z" />
<path d="M674.066 209.121C728.443 209.121 772.525 302.748 772.525 418.242C772.525 533.737 728.443 627.363 674.066 627.363C619.688 627.363 575.607 533.737 575.607 418.242C575.607 302.748 619.688 209.121 674.066 209.121Z" />
+24 -2
View File
@@ -1,6 +1,23 @@
import createMDX from "@next/mdx";
/* eslint-env node */
/** Keep viewBox so inline SVGR art can scale/center like `object-contain`. */
const svgrLoaderOptions = {
svgoConfig: {
plugins: [
{
name: "preset-default",
params: {
overrides: {
removeViewBox: false,
},
},
},
],
},
};
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "standalone",
@@ -22,7 +39,12 @@ const nextConfig = {
rules: {
"*.svg": {
condition: { not: "foreign" },
loaders: ["@svgr/webpack"],
loaders: [
{
loader: "@svgr/webpack",
options: svgrLoaderOptions,
},
],
as: "*.js",
},
},
@@ -104,7 +126,7 @@ const nextConfig = {
config.module.rules.push({
test: /\.svg$/,
issuer: /\.[jt]sx?$/,
use: ["@svgr/webpack"],
use: [{ loader: "@svgr/webpack", options: svgrLoaderOptions }],
});
// Bundle analysis - only in production builds