forked from EHV/sejeteralo
feat: adoption layer yvv-nuxt-base — palettes déléguées à useMood
- extends '../../yvv-nuxt-base' (frontend en sous-dossier)
- app/composables/usePalette.ts : moods avec vars précalculées
(--color-primary-dark dérivé + variables SVG), délégation à useMood
(darkClass 'palette-dark', syncColorMode false, storageKey 'sej-palette')
et synchro de useState('theme-dark') lu par la page graphiques
- DisplaySettings.vue : palette inline (~90 lignes) remplacée par le composable ;
font-size/densité inchangés
- README : note layer partagé
Vérifié Playwright : 6 palettes × light/dark × mobile/desktop (bodyBg suit
--color-bg, .palette-dark ne bascule que sur nuit/ocean) ; build npm vert ;
prod :3099 → 200.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -61,8 +61,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Global shared dark mode state (accessible from any component via useState)
|
||||
const isDark = useState('theme-dark', () => false)
|
||||
// Palette : identité + application DOM/persistance/dark déléguées à useMood.
|
||||
const { paletteList, currentPalette, setPalette, initPalette } = usePalette()
|
||||
|
||||
const selectorRef = ref<HTMLElement>()
|
||||
const isOpen = ref(false)
|
||||
@@ -101,92 +101,6 @@ function setDensity(d: string) {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Palette definitions ──
|
||||
interface Palette {
|
||||
name: string; label: string; dark: boolean
|
||||
primary: string; accent: string
|
||||
bg: string; surface: string; text: string; textMuted: string; border: string
|
||||
// SVG-specific
|
||||
svgPlotBg: string; svgGrid: string; svgLegendBg: string; svgText: string; svgTextLight: string
|
||||
}
|
||||
|
||||
const paletteList: Palette[] = [
|
||||
// ── Light palettes ──
|
||||
{
|
||||
name: 'eau', label: 'Eau', dark: false,
|
||||
primary: '#2563eb', accent: '#059669',
|
||||
bg: '#f8fafc', surface: '#ffffff', text: '#1e293b', textMuted: '#64748b', border: '#e2e8f0',
|
||||
svgPlotBg: '#f8fafc', svgGrid: '#e2e8f0', svgLegendBg: 'white', svgText: '#334155', svgTextLight: '#64748b',
|
||||
},
|
||||
{
|
||||
name: 'terre', label: 'Terre', dark: false,
|
||||
primary: '#92400e', accent: '#d97706',
|
||||
bg: '#fefbf6', surface: '#ffffff', text: '#1c1917', textMuted: '#78716c', border: '#e7e5e4',
|
||||
svgPlotBg: '#faf8f5', svgGrid: '#e7e5e4', svgLegendBg: 'white', svgText: '#44403c', svgTextLight: '#78716c',
|
||||
},
|
||||
{
|
||||
name: 'foret', label: 'Foret', dark: false,
|
||||
primary: '#166534', accent: '#65a30d',
|
||||
bg: '#f7fdf9', surface: '#ffffff', text: '#14532d', textMuted: '#6b7c6e', border: '#d1e7d6',
|
||||
svgPlotBg: '#f5fbf7', svgGrid: '#d1e7d6', svgLegendBg: 'white', svgText: '#2d4a35', svgTextLight: '#6b7c6e',
|
||||
},
|
||||
{
|
||||
name: 'ardoise', label: 'Ardoise', dark: false,
|
||||
primary: '#475569', accent: '#64748b',
|
||||
bg: '#f8fafc', surface: '#ffffff', text: '#1e293b', textMuted: '#64748b', border: '#e2e8f0',
|
||||
svgPlotBg: '#f8fafc', svgGrid: '#e2e8f0', svgLegendBg: 'white', svgText: '#334155', svgTextLight: '#64748b',
|
||||
},
|
||||
// ── Dark palettes ──
|
||||
{
|
||||
name: 'nuit', label: 'Nuit', dark: true,
|
||||
primary: '#60a5fa', accent: '#34d399',
|
||||
bg: '#0f172a', surface: '#1e293b', text: '#f1f5f9', textMuted: '#94a3b8', border: '#334155',
|
||||
svgPlotBg: '#1e293b', svgGrid: '#334155', svgLegendBg: '#1e293b', svgText: '#cbd5e1', svgTextLight: '#94a3b8',
|
||||
},
|
||||
{
|
||||
name: 'ocean', label: 'Ocean', dark: true,
|
||||
primary: '#38bdf8', accent: '#2dd4bf',
|
||||
bg: '#0c1222', surface: '#162032', text: '#e2e8f0', textMuted: '#7dd3fc', border: '#1e3a5f',
|
||||
svgPlotBg: '#162032', svgGrid: '#1e3a5f', svgLegendBg: '#162032', svgText: '#bae6fd', svgTextLight: '#7dd3fc',
|
||||
},
|
||||
]
|
||||
const currentPalette = ref('eau')
|
||||
|
||||
function setPalette(name: string) {
|
||||
currentPalette.value = name
|
||||
const p = paletteList.find(x => x.name === name)
|
||||
if (!p || !import.meta.client) return
|
||||
localStorage.setItem('sej-palette', name)
|
||||
|
||||
const root = document.documentElement
|
||||
const s = root.style
|
||||
s.setProperty('--color-primary', p.primary)
|
||||
s.setProperty('--color-primary-dark', darken(p.primary))
|
||||
s.setProperty('--color-secondary', p.accent)
|
||||
s.setProperty('--color-bg', p.bg)
|
||||
s.setProperty('--color-surface', p.surface)
|
||||
s.setProperty('--color-text', p.text)
|
||||
s.setProperty('--color-text-muted', p.textMuted)
|
||||
s.setProperty('--color-border', p.border)
|
||||
// SVG theme vars
|
||||
s.setProperty('--svg-plot-bg', p.svgPlotBg)
|
||||
s.setProperty('--svg-grid', p.svgGrid)
|
||||
s.setProperty('--svg-legend-bg', p.svgLegendBg)
|
||||
s.setProperty('--svg-text', p.svgText)
|
||||
s.setProperty('--svg-text-light', p.svgTextLight)
|
||||
|
||||
root.classList.toggle('palette-dark', p.dark)
|
||||
isDark.value = p.dark
|
||||
}
|
||||
|
||||
function darken(hex: string): string {
|
||||
const r = parseInt(hex.slice(1, 3), 16)
|
||||
const g = parseInt(hex.slice(3, 5), 16)
|
||||
const b = parseInt(hex.slice(5, 7), 16)
|
||||
const f = 0.82
|
||||
return `#${Math.round(r * f).toString(16).padStart(2, '0')}${Math.round(g * f).toString(16).padStart(2, '0')}${Math.round(b * f).toString(16).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
// ── Init from localStorage ──
|
||||
onMounted(() => {
|
||||
if (!import.meta.client) return
|
||||
@@ -194,8 +108,8 @@ onMounted(() => {
|
||||
if (savedFont) setFontSize(savedFont)
|
||||
const savedDensity = localStorage.getItem('sej-density')
|
||||
if (savedDensity) setDensity(savedDensity)
|
||||
const savedPalette = localStorage.getItem('sej-palette')
|
||||
if (savedPalette) setPalette(savedPalette)
|
||||
// Palette : restauration + application déléguées au composable partagé.
|
||||
initPalette()
|
||||
})
|
||||
|
||||
// ── Click outside to close ──
|
||||
|
||||
Reference in New Issue
Block a user