feat(midsummer): theme state provider + data-midsummer attribute
This commit is contained in:
parent
e803c35af9
commit
568992d0f9
3 changed files with 54 additions and 8 deletions
|
|
@ -1,23 +1,22 @@
|
||||||
import { MapLayout } from './components/map/MapLayout';
|
import { MapLayout } from './components/map/MapLayout';
|
||||||
import { PlayerDashboardFullPage } from './components/PlayerDashboardFullPage';
|
import { PlayerDashboardFullPage } from './components/PlayerDashboardFullPage';
|
||||||
|
import { MidsummerProvider } from './hooks/useMidsummer';
|
||||||
import { useLiveData } from './hooks/useLiveData';
|
import { useLiveData } from './hooks/useLiveData';
|
||||||
import './styles/map-layout.css';
|
import './styles/map-layout.css';
|
||||||
|
import './styles/midsummer.css';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Single SPA entry. Branches on `?view=` query param:
|
* Single SPA entry. Branches on `?view=` query param:
|
||||||
* /?view=dashboard → fullscreen PlayerDashboardFullPage (new-tab target)
|
* /?view=dashboard → fullscreen PlayerDashboardFullPage (new-tab target)
|
||||||
* / → default map + sidebar layout
|
* / → default map + sidebar layout
|
||||||
*
|
|
||||||
* We don't pull in react-router for one extra view — when a third view
|
|
||||||
* appears, swap this for proper routing.
|
|
||||||
*/
|
*/
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const view = new URLSearchParams(window.location.search).get('view');
|
const view = new URLSearchParams(window.location.search).get('view');
|
||||||
if (view === 'dashboard') {
|
return (
|
||||||
return <PlayerDashboardFullPage />;
|
<MidsummerProvider>
|
||||||
}
|
{view === 'dashboard' ? <PlayerDashboardFullPage /> : <DefaultApp />}
|
||||||
// Default: full app with map + sidebar.
|
</MidsummerProvider>
|
||||||
return <DefaultApp />;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Default map-and-sidebar layout. Split out so the dashboard tab doesn't
|
/** Default map-and-sidebar layout. Split out so the dashboard tab doesn't
|
||||||
|
|
|
||||||
45
frontend/src/hooks/useMidsummer.tsx
Normal file
45
frontend/src/hooks/useMidsummer.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
|
||||||
|
|
||||||
|
const KEY = 'mo-midsummer';
|
||||||
|
const SOUND_KEY = 'mo-midsummer-sound';
|
||||||
|
|
||||||
|
interface MidsummerCtx {
|
||||||
|
enabled: boolean;
|
||||||
|
toggle: () => void;
|
||||||
|
soundOn: boolean;
|
||||||
|
toggleSound: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Ctx = createContext<MidsummerCtx | null>(null);
|
||||||
|
|
||||||
|
export const MidsummerProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||||
|
// Default ON: only the literal "off" disables it.
|
||||||
|
const [enabled, setEnabled] = useState<boolean>(() => localStorage.getItem(KEY) !== 'off');
|
||||||
|
const [soundOn, setSoundOn] = useState<boolean>(() => localStorage.getItem(SOUND_KEY) !== 'off');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const el = document.documentElement;
|
||||||
|
if (enabled) el.setAttribute('data-midsummer', '');
|
||||||
|
else el.removeAttribute('data-midsummer');
|
||||||
|
localStorage.setItem(KEY, enabled ? 'on' : 'off');
|
||||||
|
}, [enabled]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
localStorage.setItem(SOUND_KEY, soundOn ? 'on' : 'off');
|
||||||
|
}, [soundOn]);
|
||||||
|
|
||||||
|
const toggle = useCallback(() => setEnabled(e => !e), []);
|
||||||
|
const toggleSound = useCallback(() => setSoundOn(s => !s), []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Ctx.Provider value={{ enabled, toggle, soundOn, toggleSound }}>
|
||||||
|
{children}
|
||||||
|
</Ctx.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useMidsummer(): MidsummerCtx {
|
||||||
|
const c = useContext(Ctx);
|
||||||
|
if (!c) throw new Error('useMidsummer must be used within MidsummerProvider');
|
||||||
|
return c;
|
||||||
|
}
|
||||||
2
frontend/src/styles/midsummer.css
Normal file
2
frontend/src/styles/midsummer.css
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
/* Midsummer "Små grodorna" theme overlay. All rules scoped under
|
||||||
|
:root[data-midsummer] so they only apply when the theme is on. */
|
||||||
Loading…
Add table
Add a link
Reference in a new issue