Systeme de themes : Base (sombre) + SikaPics (rose elegant)

- themes.css : variables et overrides par theme via data-theme
- SikaPics : palette rose/violet, fond clair, typo Montserrat/Dancing Script
- Selecteur de theme dans admin > Evenement
- Preview live du theme dans l'admin

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-07 18:06:59 +02:00
parent 05e2c8318b
commit 626db8905a
4 changed files with 220 additions and 3 deletions

197
frontend/css/themes.css Normal file
View File

@@ -0,0 +1,197 @@
/* === Themes Photobooth === */
/* --- Theme Base (defaut, sombre moderne) --- */
[data-theme="base"] {
--primaire: #e91e63;
--secondaire: #ffffff;
--fond: #1a1a2e;
--fond-carte: #16213e;
--texte: #ffffff;
--texte-secondaire: #a0a0b0;
--danger: #f44336;
--succes: #4caf50;
--rayon: 16px;
--ombre: 0 8px 32px rgba(0,0,0,0.3);
--accent-gradient: linear-gradient(135deg, #e91e63, #ff5252);
--pellicule-fond: #141414;
--pellicule-perf: #3a3a3a;
}
/* --- Theme SikaPics (rose elegant, style photographe) --- */
[data-theme="sikapics"] {
--primaire: #c31f48;
--secondaire: #240439;
--fond: #fbe7e8;
--fond-carte: #ffffff;
--texte: #240439;
--texte-secondaire: #666666;
--danger: #c31f48;
--succes: #4caf50;
--rayon: 20px;
--ombre: 0 4px 24px rgba(195, 31, 72, 0.12);
--accent-gradient: linear-gradient(135deg, #c31f48, #f33362);
--pellicule-fond: #240439;
--pellicule-perf: #4a2060;
}
[data-theme="sikapics"] body,
[data-theme="sikapics"] {
font-family: 'Montserrat', 'Segoe UI', system-ui, sans-serif;
}
[data-theme="sikapics"] .ecran {
background: var(--fond);
}
[data-theme="sikapics"] #ecran-accueil {
background: linear-gradient(160deg, #fbe7e8 0%, #fff0f1 40%, #ffffff 100%);
}
[data-theme="sikapics"] #nom-evenement {
font-family: 'Dancing Script', 'Kalnia', cursive, serif;
font-size: 4.5rem;
color: var(--primaire);
font-weight: 600;
}
[data-theme="sikapics"] .accueil-instruction {
color: var(--texte-secondaire);
font-weight: 300;
letter-spacing: 2px;
text-transform: uppercase;
font-size: 1rem;
}
[data-theme="sikapics"] .cercle-pulse {
border-color: var(--primaire);
background: rgba(195, 31, 72, 0.1);
}
[data-theme="sikapics"] .btn-mode {
background: #ffffff;
border: 2px solid #eee;
color: var(--texte);
box-shadow: 0 2px 12px rgba(0,0,0,0.06);
}
[data-theme="sikapics"] .btn-mode:active {
border-color: var(--primaire);
box-shadow: 0 2px 16px rgba(195, 31, 72, 0.2);
}
[data-theme="sikapics"] .btn-action {
background: var(--accent-gradient);
border: none;
color: #fff;
font-weight: 600;
letter-spacing: 1px;
}
[data-theme="sikapics"] .btn-secondaire {
background: transparent;
border: 2px solid var(--primaire);
color: var(--primaire);
}
[data-theme="sikapics"] .btn-retour {
color: var(--texte-secondaire);
border-color: #ccc;
}
[data-theme="sikapics"] .btn-partage {
background: #ffffff;
border: 2px solid #eee;
color: var(--texte);
}
[data-theme="sikapics"] .btn-filtre,
[data-theme="sikapics"] .btn-overlay {
background: #ffffff;
border: 2px solid #eee;
color: var(--texte);
}
[data-theme="sikapics"] .btn-filtre.actif,
[data-theme="sikapics"] .btn-overlay.actif {
border-color: var(--primaire);
background: rgba(195, 31, 72, 0.08);
}
[data-theme="sikapics"] .popup-box {
background: #ffffff;
color: var(--texte);
}
[data-theme="sikapics"] .popup-box input {
background: #f8f0f1;
border-color: #e0c0c5;
color: var(--texte);
}
[data-theme="sikapics"] .pave-touche {
background: rgba(195, 31, 72, 0.08);
color: var(--texte);
}
[data-theme="sikapics"] .pave-touche:active {
background: rgba(195, 31, 72, 0.2);
}
[data-theme="sikapics"] .pave-effacer {
background: rgba(195, 31, 72, 0.15);
}
[data-theme="sikapics"] .pave-valider {
background: rgba(76, 175, 80, 0.15);
}
[data-theme="sikapics"] .admin-contenu {
background: #ffffff;
}
[data-theme="sikapics"] .admin-onglets {
background: #f8f0f1;
}
[data-theme="sikapics"] .onglet {
color: var(--texte-secondaire);
}
[data-theme="sikapics"] .onglet.actif {
color: var(--primaire);
background: #ffffff;
}
[data-theme="sikapics"] .compte-a-rebours {
color: var(--primaire);
text-shadow: 0 4px 20px rgba(195, 31, 72, 0.3);
}
[data-theme="sikapics"] .flash-blanc {
background: rgba(251, 231, 232, 0.9);
}
[data-theme="sikapics"] .booth-info {
background: rgba(36, 4, 57, 0.7);
color: #fff;
}
[data-theme="sikapics"] .booth-code {
color: #ffffff;
}
[data-theme="sikapics"] .compteur-accueil {
background: rgba(36, 4, 57, 0.5);
color: #ffffff;
}
[data-theme="sikapics"] .btn-admin {
color: rgba(36, 4, 57, 0.2);
}
[data-theme="sikapics"] .btn-admin:active {
color: rgba(36, 4, 57, 0.5);
}
/* Import Google Fonts pour SikaPics */
@import url('https://fonts.googleapis.com/css2?family=Dancing+Script:wght@400;600;700&family=Montserrat:wght@300;400;500;600;700&display=swap');

View File

@@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Photobooth</title>
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/themes.css">
</head>
<body>
<div id="app">
@@ -309,6 +310,13 @@
<!-- Panneau Evenement -->
<div class="admin-panneau" id="panneau-evenement">
<div class="champ">
<label>Theme visuel</label>
<select id="admin-theme" onchange="changerTheme(this.value)">
<option value="base">Base (Sombre moderne)</option>
<option value="sikapics">SikaPics (Rose elegant)</option>
</select>
</div>
<div class="champ">
<label>Nom de l'evenement</label>
<input type="text" id="admin-nom-event" placeholder="Mon Evenement">

View File

@@ -519,6 +519,7 @@ function setupToggleListeners() {
async function chargerEvenementAdmin() {
const event = config.evenement || {};
document.getElementById('admin-theme').value = event.theme || 'base';
setValue('admin-nom-event', event.nom);
setValue('admin-couleur-primaire', event.couleur_primaire || '#e91e63');
setValue('admin-couleur-secondaire', event.couleur_secondaire || '#ffffff');
@@ -527,6 +528,10 @@ async function chargerEvenementAdmin() {
if (event.media_accueil) select.value = event.media_accueil;
}
function changerTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
}
async function rafraichirMediaAccueil() {
const data = await apiGet('/api/animations/custom');
const select = document.getElementById('admin-media-accueil');
@@ -556,6 +561,7 @@ async function uploaderMediaAccueil() {
async function sauvegarderEvenement() {
await apiPost('/api/config', {
evenement: {
theme: document.getElementById('admin-theme').value,
nom: getValue('admin-nom-event'),
couleur_primaire: getValue('admin-couleur-primaire'),
couleur_secondaire: getValue('admin-couleur-secondaire'),

View File

@@ -21,9 +21,15 @@ function appliquerConfig() {
const event = config.evenement || {};
const fonc = config.fonctionnalites || {};
// Couleurs
// Theme
const theme = event.theme || 'base';
document.documentElement.setAttribute('data-theme', theme);
// Couleurs (seulement si theme base, sinon le theme CSS gere)
if (theme === 'base') {
document.documentElement.style.setProperty('--primaire', event.couleur_primaire || '#e91e63');
document.documentElement.style.setProperty('--secondaire', event.couleur_secondaire || '#ffffff');
}
// Nom evenement
const h1 = document.getElementById('nom-evenement');