forked from LPK/librodrome
- typo : Bricolage Grotesque (titres) + Atkinson Hyperlegible (texte), Syne gardée pour le logo seul ; une seule source de polices (Bunny) - palettes : teinte propre à chaque axe dans les 4 ambiances ; pages d'axe en axis-scope, cartes sans bordure (canon design) - accueil : console des trois curseurs (tablist clavier), boîte à outils, bloc format éditorial + événement + reproduction ; ?v=a|b|c|0 - numérique : carte LPK ; bouquet rendu avec statut et légende - messages : sans bordure, deux colonnes en grand écran Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
146 lines
4.4 KiB
TypeScript
146 lines
4.4 KiB
TypeScript
export type PaletteName = 'automne' | 'hiver' | 'printemps' | 'ete'
|
|
|
|
interface PaletteColors {
|
|
primary: string
|
|
accent: string
|
|
surface: string
|
|
bg: string
|
|
surfaceLight: string
|
|
text: string
|
|
textMuted: string
|
|
// One hue per axis: numérique (cool) · économique (warm) · citoyenne (green)
|
|
axisNum: string
|
|
axisEco: string
|
|
axisCit: string
|
|
isLight: boolean
|
|
label: string
|
|
icon: string
|
|
}
|
|
|
|
const palettes: Record<PaletteName, PaletteColors> = {
|
|
// ══════ DARK THEMES ══════
|
|
|
|
// Automne : cuivre chaud, feuilles mortes, terre brûlée
|
|
automne: {
|
|
primary: '18 80% 45%', // cuivre profond
|
|
accent: '32 85% 50%', // ambre doré
|
|
surface: '20 10% 12%', // écorce
|
|
bg: '20 10% 7%', // terre sombre
|
|
surfaceLight: '20 8% 17%', // bois fumé
|
|
text: '0 0% 100%',
|
|
textMuted: '0 0% 65%',
|
|
axisNum: '195 55% 60%',
|
|
axisEco: '32 85% 55%',
|
|
axisCit: '95 35% 55%',
|
|
isLight: false,
|
|
label: 'Automne',
|
|
icon: 'i-lucide-leaf',
|
|
},
|
|
|
|
// Hiver : bleu nuit, givre, argent lunaire
|
|
hiver: {
|
|
primary: '215 55% 52%', // bleu nuit étoilé
|
|
accent: '195 40% 65%', // givre argenté
|
|
surface: '222 14% 13%', // ciel de minuit
|
|
bg: '225 16% 8%', // nuit polaire
|
|
surfaceLight: '220 12% 18%', // brume nocturne
|
|
text: '0 0% 100%',
|
|
textMuted: '210 10% 65%',
|
|
axisNum: '205 70% 66%',
|
|
axisEco: '36 80% 62%',
|
|
axisCit: '160 40% 58%',
|
|
isLight: false,
|
|
label: 'Hiver',
|
|
icon: 'i-lucide-snowflake',
|
|
},
|
|
|
|
// ══════ LIGHT THEMES ══════
|
|
|
|
// Printemps : vert soutenu, magenta chaud, lumière vivante
|
|
printemps: {
|
|
primary: '152 80% 24%', // vert émeraude sombre
|
|
accent: '338 88% 45%', // magenta profond
|
|
surface: '145 25% 85%', // prairie franche
|
|
bg: '140 28% 90%', // vert lumineux franc
|
|
surfaceLight: '148 22% 77%', // feuillage vif
|
|
text: '155 50% 6%', // encre noire-verte
|
|
textMuted: '150 22% 28%', // sous-bois dense
|
|
axisNum: '212 65% 34%',
|
|
axisEco: '338 80% 42%',
|
|
axisCit: '152 80% 22%',
|
|
isLight: true,
|
|
label: 'Printemps',
|
|
icon: 'i-lucide-flower-2',
|
|
},
|
|
|
|
// Été : orange brûlant, corail profond, chaleur méditerranéenne
|
|
ete: {
|
|
primary: '18 90% 44%', // terre cuite brûlante
|
|
accent: '355 78% 50%', // corail ardent
|
|
surface: '32 40% 85%', // ocre clair
|
|
bg: '35 42% 90%', // chaleur dorée
|
|
surfaceLight: '30 32% 78%', // argile chaude
|
|
text: '20 45% 8%', // brun profond
|
|
textMuted: '22 22% 30%', // ombre terracotta
|
|
axisNum: '198 70% 30%',
|
|
axisEco: '24 88% 42%',
|
|
axisCit: '150 45% 28%',
|
|
isLight: true,
|
|
label: 'Été',
|
|
icon: 'i-lucide-sun',
|
|
},
|
|
}
|
|
|
|
// Chaque palette devient un "mood" du layer @yvv/nuxt-base : les couleurs
|
|
// (identité du projet) sont injectées en variables CSS --color-*, et les classes
|
|
// .palette-light / .palette-dark + color-scheme sont gérées par le mécanisme partagé.
|
|
const paletteMoods = (Object.entries(palettes) as [PaletteName, PaletteColors][]).map(
|
|
([id, c]) => ({
|
|
id,
|
|
isDark: !c.isLight,
|
|
vars: {
|
|
'--color-primary': c.primary,
|
|
'--color-accent': c.accent,
|
|
'--color-surface': c.surface,
|
|
'--color-bg': c.bg,
|
|
'--color-surface-light': c.surfaceLight,
|
|
'--color-text': c.text,
|
|
'--color-text-muted': c.textMuted,
|
|
'--axis-num': c.axisNum,
|
|
'--axis-eco': c.axisEco,
|
|
'--axis-cit': c.axisCit,
|
|
},
|
|
}),
|
|
)
|
|
|
|
export const usePaletteStore = defineStore('palette', () => {
|
|
// Application DOM + persistance + light/dark déléguées au layer partagé.
|
|
// storageKey 'palette' conservé pour ne pas perdre les préférences existantes.
|
|
const { currentMood, setMood, initMood } = useMood(paletteMoods, {
|
|
storageKey: 'palette',
|
|
defaultId: 'ete',
|
|
syncColorMode: false, // librodrome n'utilise pas @nuxtjs/color-mode
|
|
lightDarkClasses: true,
|
|
})
|
|
|
|
const currentPalette = computed<PaletteName>(() => (currentMood.value as PaletteName) || 'ete')
|
|
const colors = computed(() => palettes[currentPalette.value])
|
|
const isLight = computed(() => colors.value.isLight)
|
|
|
|
// Init depuis localStorage (SSR-safe : no-op côté serveur).
|
|
const applyToDOM = () => initMood()
|
|
|
|
function setPalette(name: PaletteName) {
|
|
setMood(name)
|
|
}
|
|
|
|
return {
|
|
currentPalette,
|
|
colors,
|
|
palettes,
|
|
isLight,
|
|
setPalette,
|
|
applyToDOM,
|
|
}
|
|
})
|