update frontend
This commit is contained in:
parent
a3bcb933b3
commit
60a51bdf8e
35
src/App.jsx
35
src/App.jsx
|
|
@ -1,11 +1,42 @@
|
||||||
import React from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import TopBar from "./components/Layout/TopBar";
|
import TopBar from "./components/Layout/TopBar";
|
||||||
import MapView from "./components/Map/MapView";
|
import MapView from "./components/Map/MapView";
|
||||||
|
|
||||||
|
const THEME_KEY = "sociowire:theme";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
|
const [theme, setTheme] = useState("dark");
|
||||||
|
|
||||||
|
// charge le thème depuis le localStorage au démarrage
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof window === "undefined") return;
|
||||||
|
try {
|
||||||
|
const saved = localStorage.getItem(THEME_KEY);
|
||||||
|
if (saved === "dark" || saved === "blue" || saved === "light") {
|
||||||
|
setTheme(saved);
|
||||||
|
document.body.setAttribute("data-theme", saved);
|
||||||
|
} else {
|
||||||
|
document.body.setAttribute("data-theme", "dark");
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
document.body.setAttribute("data-theme", "dark");
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// applique le thème + sauvegarde
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof window === "undefined") return;
|
||||||
|
try {
|
||||||
|
document.body.setAttribute("data-theme", theme);
|
||||||
|
localStorage.setItem(THEME_KEY, theme);
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}, [theme]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="app-root">
|
<div className="app-root">
|
||||||
<TopBar />
|
<TopBar theme={theme} onChangeTheme={setTheme} />
|
||||||
<div className="main-shell">
|
<div className="main-shell">
|
||||||
<div className="map-shell">
|
<div className="map-shell">
|
||||||
<MapView />
|
<MapView />
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,39 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default function TopBar() {
|
const THEME_LABELS = {
|
||||||
|
dark: "Dark",
|
||||||
|
blue: "Blue",
|
||||||
|
light: "Light",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function TopBar({ theme = "dark", onChangeTheme }) {
|
||||||
return (
|
return (
|
||||||
<header className="topbar">
|
<header className="topbar">
|
||||||
<div className="logo-circle">SW</div>
|
<div className="logo-circle">SW</div>
|
||||||
|
|
||||||
<div className="title-block">
|
<div className="title-block">
|
||||||
<div className="main-title">SOCIOWIRE.com</div>
|
<div className="main-title">SOCIOWIRE.com</div>
|
||||||
<div className="sub-title">Wired to life</div>
|
<div className="sub-title">Wired to life</div>
|
||||||
</div>
|
</div>
|
||||||
<button className="btn-primary">Login</button>
|
|
||||||
|
<div className="topbar-right">
|
||||||
|
<div className="theme-switch">
|
||||||
|
{["dark", "blue", "light"].map((t) => (
|
||||||
|
<button
|
||||||
|
key={t}
|
||||||
|
type="button"
|
||||||
|
className={
|
||||||
|
"theme-dot" + (theme === t ? " theme-dot-active" : "")
|
||||||
|
}
|
||||||
|
title={THEME_LABELS[t]}
|
||||||
|
onClick={() => onChangeTheme && onChangeTheme(t)}
|
||||||
|
>
|
||||||
|
{THEME_LABELS[t][0]}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<button className="btn-primary">Login</button>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ import "./styles/map.css";
|
||||||
import "./styles/markers.css";
|
import "./styles/markers.css";
|
||||||
import "./styles/popup.css";
|
import "./styles/popup.css";
|
||||||
import "./styles/overlays.css";
|
import "./styles/overlays.css";
|
||||||
import "./styles/posts.css"; // Sociowall + chat
|
import "./styles/posts.css";
|
||||||
|
import "./styles/theme.css";
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,19 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* plus aucun espace entre la topbar et la carte */
|
||||||
.main-shell {
|
.main-shell {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0.6rem;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Conteneur de la carte plein écran */
|
/* Conteneur de la carte plein écran collé aux bords */
|
||||||
.map-shell {
|
.map-shell {
|
||||||
position: relative;
|
position: relative;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
border-radius: 1rem;
|
border-radius: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 1px solid #1f2937;
|
border: none;
|
||||||
background: #020617;
|
background: #020617;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
/* ==========================================
|
||||||
|
THEME SYSTEM — body[data-theme="..."]
|
||||||
|
Trois thèmes : dark (par défaut), blue, light
|
||||||
|
========================================== */
|
||||||
|
|
||||||
|
/* Thème noir (par défaut) */
|
||||||
|
body[data-theme="dark"] {
|
||||||
|
background: #050816;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===================== BLUE ===================== */
|
||||||
|
|
||||||
|
body[data-theme="blue"] .sociowall-panel,
|
||||||
|
body[data-theme="blue"] .chat-panel,
|
||||||
|
body[data-theme="blue"] .post-card,
|
||||||
|
body[data-theme="blue"] .post-pin--expanded .post-card,
|
||||||
|
body[data-theme="blue"] .post-pin--compact .post-pin-bubble,
|
||||||
|
body[data-theme="blue"] .popup-post-card {
|
||||||
|
background: rgba(12, 20, 60, 0.96);
|
||||||
|
border-color: rgba(96, 165, 250, 0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-theme="blue"] .chip-round,
|
||||||
|
body[data-theme="blue"] .chip-pill,
|
||||||
|
body[data-theme="blue"] .chip-egg,
|
||||||
|
body[data-theme="blue"] .chip-hex {
|
||||||
|
background: rgba(10, 22, 60, 0.96);
|
||||||
|
border-color: rgba(96, 165, 250, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-theme="blue"] .chip-selected,
|
||||||
|
body[data-theme="blue"] .chip-egg-active {
|
||||||
|
background: linear-gradient(135deg, #1d4ed8, #38bdf8);
|
||||||
|
border-color: #bfdbfe;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===================== LIGHT ===================== */
|
||||||
|
|
||||||
|
body[data-theme="light"] {
|
||||||
|
background: #e5e7eb;
|
||||||
|
color: #111827;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* panneaux principaux clairs */
|
||||||
|
body[data-theme="light"] .sociowall-panel,
|
||||||
|
body[data-theme="light"] .chat-panel,
|
||||||
|
body[data-theme="light"] .post-card,
|
||||||
|
body[data-theme="light"] .post-pin--expanded .post-card,
|
||||||
|
body[data-theme="light"] .popup-post-card {
|
||||||
|
background: rgba(248, 250, 252, 0.97);
|
||||||
|
border-color: rgba(148, 163, 184, 0.9);
|
||||||
|
color: #111827;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* petits marqueurs compacts */
|
||||||
|
body[data-theme="light"] .post-pin--compact .post-pin-bubble {
|
||||||
|
background: rgba(255, 255, 255, 0.96);
|
||||||
|
border-color: rgba(148, 163, 184, 0.9);
|
||||||
|
color: #0f172a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* chips claires */
|
||||||
|
body[data-theme="light"] .chip-round,
|
||||||
|
body[data-theme="light"] .chip-pill,
|
||||||
|
body[data-theme="light"] .chip-egg,
|
||||||
|
body[data-theme="light"] .chip-hex {
|
||||||
|
background: rgba(255, 255, 255, 0.98);
|
||||||
|
border-color: rgba(148, 163, 184, 0.9);
|
||||||
|
color: #111827;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-theme="light"] .chip-selected,
|
||||||
|
body[data-theme="light"] .chip-egg-active {
|
||||||
|
background: linear-gradient(135deg, #38bdf8, #0ea5e9);
|
||||||
|
border-color: #0ea5e9;
|
||||||
|
color: #0f172a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* topbar clair */
|
||||||
|
body[data-theme="light"] .topbar {
|
||||||
|
background: #f9fafb;
|
||||||
|
border-bottom-color: #e5e7eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-theme="light"] .main-title,
|
||||||
|
body[data-theme="light"] .sub-title {
|
||||||
|
color: #0f172a;
|
||||||
|
}
|
||||||
|
|
@ -36,6 +36,40 @@
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* bloc de droite : thèmes + bouton login */
|
||||||
|
.topbar-right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* petits boutons de thème (D / B / L) */
|
||||||
|
.theme-switch {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dot {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid #4b5563;
|
||||||
|
background: #020617;
|
||||||
|
color: #e5e7eb;
|
||||||
|
font-size: 0.65rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dot-active {
|
||||||
|
border-color: #facc15;
|
||||||
|
box-shadow: 0 0 10px rgba(250, 204, 21, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bouton Login */
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
padding: 0.25rem 0.7rem;
|
padding: 0.25rem 0.7rem;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue