Refonte du fond de la page de connexion : vrai diaporama génératif
Le système de crossfade existait déjà mais avec 3 dégradés plats placeholder (commentaire explicite : "à remplacer par de vraies images"). Remplacé par un fond génératif plus riche, à la demande de l'utilisateur (design jugé "moche", contraste douteux sur certains postes) : - 4 scènes (taches de couleur floutées, palette sourde) qui dérivent lentement (@keyframes tc-drift, respecte prefers-reduced-motion) et s'enchaînent en fondu toutes les 8s. - Grain léger (SVG feTurbulence, mix-blend-overlay) contre l'effet "dégradé plat". - Scrim en deux passes (voile uniforme + dégradé directionnel) : le texte reste lisible quelle que soit la scène ou la position, plutôt que de dépendre d'un seul dégradé ancré à gauche. Pas de photo tierce (droits, dépendance externe) - art génératif en CSS/SVG, cohérent avec le ton "coffre-fort minimaliste" du reste de l'interface. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
a639b705a6
commit
c5147f5cb0
4 changed files with 106 additions and 18 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { BACKGROUND_IMAGES } from '../../lib/backgrounds';
|
import { BACKGROUND_SCENES } from '../../lib/backgrounds';
|
||||||
import { useBackgroundCrossfade } from '../../hooks/useBackgroundCrossfade';
|
import { useBackgroundCrossfade } from '../../hooks/useBackgroundCrossfade';
|
||||||
|
|
||||||
export function AuthBackground() {
|
export function AuthBackground() {
|
||||||
|
|
@ -6,15 +6,43 @@ export function AuthBackground() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="absolute inset-0 overflow-hidden bg-[#07080c]">
|
<div className="absolute inset-0 overflow-hidden bg-[#07080c]">
|
||||||
{BACKGROUND_IMAGES.map((bg, i) => (
|
{BACKGROUND_SCENES.map((scene, i) => (
|
||||||
<div
|
<div
|
||||||
key={bg}
|
key={scene.id}
|
||||||
className="absolute inset-0 scale-105 bg-cover bg-center transition-opacity duration-[2000ms] ease-in-out"
|
className="absolute inset-0 transition-opacity duration-[2400ms] ease-in-out"
|
||||||
style={{ background: bg, opacity: i === activeIndex ? 1 : 0 }}
|
style={{ opacity: i === activeIndex ? 1 : 0 }}
|
||||||
|
>
|
||||||
|
{scene.blobs.map((blob, bi) => (
|
||||||
|
<div
|
||||||
|
key={bi}
|
||||||
|
className="tc-drift absolute rounded-full blur-[90px]"
|
||||||
|
style={{
|
||||||
|
top: blob.top,
|
||||||
|
left: blob.left,
|
||||||
|
width: blob.size,
|
||||||
|
height: blob.size,
|
||||||
|
background: blob.color,
|
||||||
|
animationDelay: `${bi * -7}s`,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<div className="absolute inset-0 bg-[linear-gradient(100deg,rgba(6,7,11,0.92)_0%,rgba(6,7,11,0.62)_46%,rgba(6,7,11,0.28)_100%)]" />
|
</div>
|
||||||
<div className="absolute -right-[8%] -top-[18%] h-[52vw] w-[52vw] rounded-full bg-[radial-gradient(circle,rgba(91,140,255,0.26)_0%,transparent_66%)] blur-[10px]" />
|
))}
|
||||||
|
|
||||||
|
{/* Grain léger : casse l'effet "dégradé plat", donne une texture
|
||||||
|
plus organique - technique courante sur les fonds génératifs. */}
|
||||||
|
<svg className="absolute inset-0 h-full w-full opacity-[0.05] mix-blend-overlay" aria-hidden="true">
|
||||||
|
<filter id="tc-grain">
|
||||||
|
<feTurbulence type="fractalNoise" baseFrequency="0.85" numOctaves="2" stitchTiles="stitch" />
|
||||||
|
</filter>
|
||||||
|
<rect width="100%" height="100%" filter="url(#tc-grain)" />
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{/* Scrim en deux passes : un voile uniforme (garantit le contraste du
|
||||||
|
texte quelle que soit la position des taches de couleur) plus un
|
||||||
|
dégradé directionnel plus marqué côté texte. */}
|
||||||
|
<div className="absolute inset-0 bg-[#07080c]/48" />
|
||||||
|
<div className="absolute inset-0 bg-[linear-gradient(100deg,rgba(6,7,11,0.74)_0%,rgba(6,7,11,0.44)_46%,rgba(6,7,11,0.22)_100%)]" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { BACKGROUND_IMAGES } from '../lib/backgrounds';
|
import { BACKGROUND_SCENES } from '../lib/backgrounds';
|
||||||
|
|
||||||
const INTERVAL_MS = 5400;
|
const INTERVAL_MS = 8000;
|
||||||
|
|
||||||
export function useBackgroundCrossfade(): number {
|
export function useBackgroundCrossfade(): number {
|
||||||
const [index, setIndex] = useState(0);
|
const [index, setIndex] = useState(0);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||||
const id = window.setInterval(() => {
|
const id = window.setInterval(() => {
|
||||||
setIndex((i) => (i + 1) % BACKGROUND_IMAGES.length);
|
setIndex((i) => (i + 1) % BACKGROUND_SCENES.length);
|
||||||
}, INTERVAL_MS);
|
}, INTERVAL_MS);
|
||||||
return () => window.clearInterval(id);
|
return () => window.clearInterval(id);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,26 @@ input::placeholder {
|
||||||
animation: tc-pulse 2.4s ease-in-out infinite;
|
animation: tc-pulse 2.4s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes tc-drift {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translate(0, 0) scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translate(3%, -4%) scale(1.06);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tc-drift {
|
||||||
|
animation: tc-drift 22s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.tc-drift {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.upload-progress-stripes {
|
.upload-progress-stripes {
|
||||||
background-image: linear-gradient(
|
background-image: linear-gradient(
|
||||||
115deg,
|
115deg,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,49 @@
|
||||||
/**
|
/**
|
||||||
* Auth-screen background layers. Replace each entry with
|
* Scènes du diaporama de fond de l'écran de connexion : de l'art génératif
|
||||||
* `url('/assets/bg-1.jpg') center/cover no-repeat` for real photography —
|
* (pas de photo tierce, pour rester libre de droits) - deux à trois taches
|
||||||
* the crossfade logic in useBackgroundCrossfade doesn't change.
|
* de couleur douces, floutées, qui dérivent lentement (voir `.tc-drift`
|
||||||
|
* dans index.css) et s'enchaînent en fondu. Palette "zen" volontairement
|
||||||
|
* sourde : jamais de couleur saturée à pleine opacité.
|
||||||
*/
|
*/
|
||||||
export const BACKGROUND_IMAGES: string[] = [
|
export interface BackgroundBlob {
|
||||||
'radial-gradient(120% 95% at 22% 12%, #2b3340 0%, #121620 55%, #070910 100%)',
|
color: string;
|
||||||
'radial-gradient(120% 95% at 78% 18%, #2f2b3f 0%, #16131f 55%, #08070d 100%)',
|
top: string;
|
||||||
'radial-gradient(130% 100% at 45% 85%, #1f3340 0%, #0f161c 55%, #070a0d 100%)',
|
left: string;
|
||||||
|
size: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BackgroundScene {
|
||||||
|
id: string;
|
||||||
|
blobs: BackgroundBlob[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BACKGROUND_SCENES: BackgroundScene[] = [
|
||||||
|
{
|
||||||
|
id: 'aube',
|
||||||
|
blobs: [
|
||||||
|
{ color: 'rgba(123,148,255,0.42)', top: '-12%', left: '58%', size: '56vw' },
|
||||||
|
{ color: 'rgba(255,168,140,0.24)', top: '52%', left: '2%', size: '44vw' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'nuit',
|
||||||
|
blobs: [
|
||||||
|
{ color: 'rgba(91,102,255,0.38)', top: '-16%', left: '72%', size: '60vw' },
|
||||||
|
{ color: 'rgba(124,92,255,0.3)', top: '58%', left: '12%', size: '50vw' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'foret',
|
||||||
|
blobs: [
|
||||||
|
{ color: 'rgba(94,214,170,0.22)', top: '8%', left: '76%', size: '48vw' },
|
||||||
|
{ color: 'rgba(53,124,132,0.38)', top: '62%', left: '6%', size: '54vw' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'braise',
|
||||||
|
blobs: [
|
||||||
|
{ color: 'rgba(255,186,128,0.26)', top: '-6%', left: '18%', size: '50vw' },
|
||||||
|
{ color: 'rgba(179,111,255,0.3)', top: '54%', left: '68%', size: '54vw' },
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue