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:
parent
43bce5f4e9
commit
f2eb995d7d
@ -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";
|
type AdFormat = "auto" | "fluid" | "rectangle" | "horizontal" | "vertical" | "autorelaxed";
|
||||||
|
|
||||||
@ -77,16 +78,19 @@ export default function AdSense({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let adSeedCounter = 1;
|
||||||
|
|
||||||
export function ArticleCardAd() {
|
export function ArticleCardAd() {
|
||||||
|
const seed = useMemo(() => adSeedCounter++, []);
|
||||||
return (
|
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
|
<AdSense
|
||||||
slot="3854634730"
|
slot="3854634730"
|
||||||
format="fluid"
|
format="fluid"
|
||||||
layoutKey="-6r+cy-10+8a-3"
|
layoutKey="-6r+cy-10+8a-3"
|
||||||
style={{ display: "block" }}
|
style={{ display: "block" }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</ArtistPatternBg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
73
client/src/components/artist-pattern-bg.tsx
Normal file
73
client/src/components/artist-pattern-bg.tsx
Normal file
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -8,6 +8,7 @@ import { Skeleton } from "@/components/ui/skeleton";
|
|||||||
import Header from "@/components/header";
|
import Header from "@/components/header";
|
||||||
import Footer from "@/components/footer";
|
import Footer from "@/components/footer";
|
||||||
import AdSense, { ArticleCardAd, MultiplexAd, SidebarAd } from "@/components/adsense";
|
import AdSense, { ArticleCardAd, MultiplexAd, SidebarAd } from "@/components/adsense";
|
||||||
|
import ArtistPatternBg from "@/components/artist-pattern-bg";
|
||||||
import { PhotoGalleryWidget } from "@/components/photo-gallery";
|
import { PhotoGalleryWidget } from "@/components/photo-gallery";
|
||||||
import { HoroscopeWidget } from "@/components/horoscope-widget";
|
import { HoroscopeWidget } from "@/components/horoscope-widget";
|
||||||
import { RecipeWidget } from "@/components/recipe-widget";
|
import { RecipeWidget } from "@/components/recipe-widget";
|
||||||
@ -631,7 +632,7 @@ export default function Home() {
|
|||||||
|
|
||||||
{widePickedArticles.length > 0 && (
|
{widePickedArticles.length > 0 && (
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-4 gap-4">
|
<div className="grid grid-cols-1 lg:grid-cols-4 gap-4">
|
||||||
<div className="hidden lg:block rounded-lg overflow-hidden bg-card border border-card-border">
|
<ArtistPatternBg className="hidden lg:block rounded-lg overflow-hidden bg-card border border-card-border" seed={99}>
|
||||||
<AdSense
|
<AdSense
|
||||||
slot="3854634730"
|
slot="3854634730"
|
||||||
format="fluid"
|
format="fluid"
|
||||||
@ -639,7 +640,7 @@ export default function Home() {
|
|||||||
style={{ display: "block" }}
|
style={{ display: "block" }}
|
||||||
className="w-full h-full min-h-[250px]"
|
className="w-full h-full min-h-[250px]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</ArtistPatternBg>
|
||||||
<div className="lg:col-span-3">
|
<div className="lg:col-span-3">
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||||
{widePickedArticles.map((a) => (
|
{widePickedArticles.map((a) => (
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"access_token": "sl.u.AGVuqbSOwM_IaEQkqETN8XBMNt5yaozQHrwswboVTqkE2GeJpVRaGEjJYk_AEO1_PoylTdNl0pMwGO4_SS-REKTIm1Fls8sFKlJMN77GiJQJuGbB1qdrpwR22LpZDznp3rmkmoEhxiiDQiRUl5SBxBZTy19DWpx5nyV3Lc3eXvaOU9mKvXrOzvRqtDhFUxHlEKNCLO4s7buoYak9A9eqK27comnMEJMCKJ1Kqiho-ZKk9WNFkMSbdyQIAbM0Uwy0AUD4W69aSqmj41aVOT1Y_M_EepY1WnZjGX5t71iXFjTKqtbMIG_sCV9mkBITNXYfcYQwW6ZGuFW5mMBnQ1WJdjqPS_iVuL8tKfLTe2TBNq4-A3CPZwtOgIrara4-3pP6ifphxmkgeNLTD2Tw5q2Cl0KRF_ZBhoTO0PxgRaiBYhEnFWDdfp0Wsn0jk8BGk5OY4nsSDgJactpKmWT4itE1CE-R5QM1Dsd98BXkXoROf5CSc9d2UVcknM5fKp5RRNHhq_bdDl5-U2wt7SE_G_xf2pMVAZPO3m8YZWpeI21IyTJGrRe9NLSa7tkZpOTdEp3Bg_lHnh0IP2PP79-hlSsTtBQ4oclQ6iomGv-tRhcwt_hHdy71lhx2LUj4QwzyptYK_YSYCtgsMofpo7f5slJfWSP4-p0s_hU2hP2SC_Z9SLuPKn91bvaQLOu2PINxF0yNDo10Y1wUveZboN2S0KeK3tIyfNplQ2g6KEmBDGQgXlMabrkBZfSFqofhCYCX3sdqzQCJKK4IjXGmrFYozv4wjWHD0CwetaCBURmAqwdw6o7Be89HS2AbB5-iWxRDctSQALNS1VkE24lH9nelT31b_grTEZLkLZJqnbd4TjeY1b_AlPQ4p7d2dud0MekbzsDvFC7KAUdOTRDlsF_0YKYx2AohOu79Jz7jAWTaBFBQLsrr1IoemfAHDkLNhpxgQjWZZ4Wj3CMj-01IVSeRrX6BW_Gt7V_E5FgSnUTNZANYqMmNN7ggzmCwZltAI3uNLK_qi_XBN66uUDBMHoJD8MuHxXvWFa4r-rOEQh04YM6FpSltHq8I6fL0OYQe4zrrBOYMsu5Xg5NDg8e2n9iCq4s7CSYrbJrkvzJTPAjgy74hblV5mV6kryZ4YMtizfsMmY3PEH6thCby1tADA4gQSGouXwZVGm11Dc3SikM4wLPKnWwI2gU985QoB89vJmDLnv5FRvR_ryARI5_1TLuaWswfAYcZajGNvjS-7emRNTnVsuMl1E5uIcIKCXHrUIIkPGPTfe74NGrhMRi7fdGTtwMZgA0TEqiYFjEgabbqgazkz8F3tg",
|
"access_token": "sl.u.AGUQq1dMOSrEC_xUCcjdbFyPUzqtq04u2Ya543b_-ykVOkXeSHLtcM_d24Sslmr0M6mrqYCQ7oYeh9l4XQEZWTGYWR_rDE5R_qn48gdf5DXpKM2_pzyeQaVteA0d2It52ETJRbVN4kGsJZixcwfLXGw4LK0r6FQ7Q4FYtQaYvyZKK1hO1p3SC8jL9mC_8ZUk-M-yrNtYfKnYbm6ZrMXX1WJEtqfM3fe1xVl2r0wlpq4PkSwXn_oU_EbGy6ITeJHx5PNI7_XME_tYdNDCdm9ESI-kV15r7SDtfBQfUoVx1zGGa_wsQq_chjd-v0nCoRhIWvBtxEo_cf9FyHzyqQ9iLKid1hzPZnam5rdW87B4DQQocWk8JjcAwqU4MGQWrViT-LXb6lGiyIQo_LCJlexgdlHMl8iN05-Za5rexP_K2g7GiU7bC1wf8TMFoI8xYS0Kq7pHz-Kx2AEUzip39x0dmAbb4Y07NvGWI3Cfi0fwe_7GQeKJ9KxLBMZIbAXnIfIzqK8H49npJddDPWlXJSMH6i2f4nLH05nnlf9HmqsO05TOESzxMwTAOsEStFDW0eBXrUB-UeBT8S5sfeuvubNYUNqAVw4IXisjZ4nnpfaIytuuBgPZOzQdaQkdgpxZaJFQz6uXU0ZzPMz4OnDhStSGoj15NRJDJWbNynaNWxTWv0Gncg09AP6IEuH_KdQdckUMVdmCBrTd4vsVGd__MZfsqt_SWsgEPA-xnUXSIRvhbmXCDTJsI0VHFywVfqHXtupw6ljkauw_BMiJv0p8KZhj9NB3aWJPamsPLV4UYRn_Cy2wYY6leqiAiyUI4lmcFkGtrVzeeLDG3Ga3pfm_7WlMU6ZJNuwVprxZpjf9yKR6U6u4Bc5_WoRvr7PTTu5oNOjGD2KCdSOBPDVuSL0lyMPazz1WpJ4SNAcC47c61Bp9ywO2TtDMGkcmKr6ElWxiPn21B3Cu2nh6_sCgIDLocMGPslME1VJb-msrDu8PLGX_fEnsOJd_2pHhr_cp3E3Kt8CB4mQfEtaPDhYkEQ9FvhvmtZ2sj9gYFYs0-6wE0bBaLLQBLgkBMgV5VZycNZ_A0tiB-uymKuFHdDZXVoejIrxBuRB1EiB30ba68BcM_erBItG3riwX5PfSNqJNhx0SEMNCiKjBKUuGRz6UQj64aZXOh6yvImw0SxXw922ktqTkqOk_hpZtkeGx21JC_NXohbqZnFlAMHfLFbsZUW8iaSbIzeydUvB3Llz-92Vx0hQAj3mOnMCteHivD2ra2izz_UwzfOhQ_6nLVJeWlWp6LpwycPya32VDQCb118S3zkfyrJZHNg",
|
||||||
"refresh_token": "8-fiK0Io8Z8AAAAAAAAAAXn1QIGTwFTVWKF47COXY2bjqYlWyd4aRnFtQJ7usZ0y",
|
"refresh_token": "8-fiK0Io8Z8AAAAAAAAAAXn1QIGTwFTVWKF47COXY2bjqYlWyd4aRnFtQJ7usZ0y",
|
||||||
"expires_at": 1772628298578,
|
"expires_at": 1772647027085,
|
||||||
"app_key": "sjwprgka82p8tpv",
|
"app_key": "sjwprgka82p8tpv",
|
||||||
"app_secret": "g3vuczqo0rx3crz"
|
"app_secret": "g3vuczqo0rx3crz"
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user