Add decorative artist pattern background to desktop advertisements

Integrates an `ArtistPatternBg` component to wrap ad containers (`ArticleCardAd`, home page wide-picked ad section) with a decorative artist name pattern, enhancing visual appeal on desktop while leaving mobile unchanged.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 517dfa7b-26ac-463d-a6e1-a58c6df97188
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 7e26d45f-76ee-4e0c-8b18-8bffeb9e004b
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/517dfa7b-26ac-463d-a6e1-a58c6df97188/jdAEdU5
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
sebastjanartic
2026-03-04 13:58:11 +00:00
parent 43bce5f4e9
commit f2eb995d7d
5 changed files with 613 additions and 535 deletions
+7 -3
View File
@@ -1,4 +1,5 @@
import { useEffect, useRef, useState } from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import ArtistPatternBg from "./artist-pattern-bg";
type AdFormat = "auto" | "fluid" | "rectangle" | "horizontal" | "vertical" | "autorelaxed";
@@ -77,16 +78,19 @@ export default function AdSense({
);
}
let adSeedCounter = 1;
export function ArticleCardAd() {
const seed = useMemo(() => adSeedCounter++, []);
return (
<div className="bg-card rounded-md border border-card-border overflow-hidden h-full">
<ArtistPatternBg className="rounded-md border border-card-border h-full bg-card" seed={seed}>
<AdSense
slot="3854634730"
format="fluid"
layoutKey="-6r+cy-10+8a-3"
style={{ display: "block" }}
/>
</div>
</ArtistPatternBg>
);
}
@@ -0,0 +1,73 @@
import { useMemo } from "react";
const ARTISTS = [
"Kastelruther Spatzen", "Melanie Payer", "Linda Feller", "Die Edlseer",
"Hansi Berger", "Sašo Avsenik", "Die Grubertaler", "Pagger Buam",
"John Prisco", "Igor und seine Oberkrainer", "Die Kaiser", "Marlena Martinelli",
"Spitzbua Markus", "Julia Raich", "Meissnitzer Band", "Tauern Echo",
"Brennholz", "Charly Kaiser", "Franz Nolf", "Franz Steiner",
"Die 3 Z'widern", "Mark Ed", "Natascha", "Meli Stein",
"SUSAL", "Pfundskerle", "Da Wadltreiber", "Sanny",
"Alex Reichinger", "Sigrid & Marina", "Folx Stadl", "Gipfelstammtisch",
];
function seededRandom(seed: number) {
let s = seed;
return () => {
s = (s * 16807 + 0) % 2147483647;
return s / 2147483647;
};
}
interface Props {
children: React.ReactNode;
className?: string;
seed?: number;
}
export default function ArtistPatternBg({ children, className = "", seed = 42 }: Props) {
const items = useMemo(() => {
const rng = seededRandom(seed);
const result: { name: string; x: number; y: number; size: number; opacity: number; rotation: number; italic: boolean }[] = [];
const count = 40;
for (let i = 0; i < count; i++) {
result.push({
name: ARTISTS[Math.floor(rng() * ARTISTS.length)],
x: rng() * 100,
y: (i / count) * 100 + (rng() - 0.5) * 8,
size: 9 + rng() * 9,
opacity: 0.03 + rng() * 0.05,
rotation: -12 + rng() * 24,
italic: rng() > 0.6,
});
}
return result;
}, [seed]);
return (
<div className={`relative overflow-hidden ${className}`}>
<div className="absolute inset-0 pointer-events-none select-none hidden lg:block" aria-hidden="true">
{items.map((item, i) => (
<span
key={i}
className="absolute whitespace-nowrap text-primary"
style={{
left: `${item.x}%`,
top: `${item.y}%`,
fontSize: `${item.size}px`,
opacity: item.opacity,
transform: `rotate(${item.rotation}deg)`,
fontStyle: item.italic ? "italic" : "normal",
fontWeight: item.italic ? 300 : 400,
}}
>
{item.name}
</span>
))}
</div>
<div className="relative z-[1]">
{children}
</div>
</div>
);
}