chore(ops): commit ThemeEditor.vue (extrait de l'ex-page /theme, consolidé dans Paramètres)
Composant autonome créé lors de la consolidation Thème→Paramètres (redirect routeur /theme→/settings déjà commité en
23f0f72). Fichier 100% mien, sans mélange → seul élément sûr à commiter de l'audit ; le point de montage (import dans
SettingsPage.vue) reste non commité car ce fichier est co-édité (voir rapport d'audit).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
4718d025f3
commit
60f6d71615
78
apps/ops/src/components/shared/ThemeEditor.vue
Normal file
78
apps/ops/src/components/shared/ThemeEditor.vue
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
<!--
|
||||||
|
ThemeEditor — éditeur de thème (palette --ops-*) EXTRAIT de l'ex-page /theme pour être monté DANS les Paramètres
|
||||||
|
(consolidation : une entrée de nav en moins). Logique dans composables/useTheme ; appliqué au boot par App.vue (indépendant).
|
||||||
|
Autonome : presets + groupes de couleurs + aperçu + Enregistrer/Réinitialiser (localStorage, ce navigateur).
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="row items-center q-mb-sm">
|
||||||
|
<div class="text-caption text-grey-7 col">
|
||||||
|
Couleurs principales regroupées — modif en direct (aperçu immédiat) puis « Enregistrer ». Les éléments qui utilisent
|
||||||
|
les variables <code>--ops-*</code> suivent automatiquement. Enregistré dans ce navigateur.
|
||||||
|
</div>
|
||||||
|
<q-btn flat dense no-caps icon="restart_alt" label="Réinitialiser" @click="reset" class="q-mr-sm" />
|
||||||
|
<q-btn unelevated dense no-caps color="primary" icon="save" label="Enregistrer" @click="save" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="q-mb-md">
|
||||||
|
<div class="text-subtitle2 q-mb-xs">Palettes de départ</div>
|
||||||
|
<q-btn outline no-caps color="green-7" icon="eco" label="Moderne (défaut)" @click="applyPreset('default')" class="q-mr-sm q-mb-xs"><q-tooltip>Vert accessible + neutres — palette par défaut de la marque</q-tooltip></q-btn>
|
||||||
|
<q-btn outline no-caps color="green-6" icon="bolt" label="Vif (lime)" @click="applyPreset('vif')" class="q-mr-sm q-mb-xs"><q-tooltip>Vert lime éclatant — plus vibrant</q-tooltip></q-btn>
|
||||||
|
<q-btn outline no-caps color="primary" icon="palette" label="Classique (indigo)" @click="applyPreset('indigo')" class="q-mb-xs" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row q-col-gutter-md">
|
||||||
|
<div v-for="g in groups" :key="g.title" class="col-12 col-md-6">
|
||||||
|
<q-card flat bordered>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-subtitle1 text-weight-bold">{{ g.title }}</div>
|
||||||
|
<div v-if="g.hint" class="text-caption text-grey-6 q-mb-sm">{{ g.hint }}</div>
|
||||||
|
<div v-for="t in g.tokens" :key="t.var" class="row items-center q-py-xs no-wrap" style="gap:10px">
|
||||||
|
<input type="color" :value="work[t.var]" @input="e => set(t, e.target.value)"
|
||||||
|
style="width:40px;height:34px;border:1px solid var(--ops-border);border-radius:8px;padding:2px;background:none;cursor:pointer;flex:0 0 auto" />
|
||||||
|
<div class="col"><div class="text-body2">{{ t.label }}</div><code class="text-caption text-grey-6">{{ t.var }}</code></div>
|
||||||
|
<q-input dense outlined v-model="work[t.var]" @update:model-value="v => set(t, v)" style="width:104px;flex:0 0 auto" />
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<q-card flat bordered class="q-mt-md">
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-subtitle1 text-weight-bold q-mb-sm">Aperçu</div>
|
||||||
|
<div class="row items-center q-gutter-sm">
|
||||||
|
<q-btn unelevated color="primary" no-caps label="Bouton accent" />
|
||||||
|
<q-btn outline color="primary" no-caps label="Contour" />
|
||||||
|
<span class="ops-badge active">Actif</span>
|
||||||
|
<span class="ops-badge open">Ouvert</span>
|
||||||
|
<span class="ops-badge inactive">Inactif</span>
|
||||||
|
<q-badge color="positive" label="Succès" />
|
||||||
|
<q-badge color="warning" label="Attention" />
|
||||||
|
<q-badge color="negative" label="Erreur" />
|
||||||
|
<a href="#" @click.prevent style="color:var(--ops-accent);font-weight:600">Lien accent</a>
|
||||||
|
</div>
|
||||||
|
<div class="q-mt-sm" style="background:var(--ops-bg);border:1px solid var(--ops-border);border-radius:8px;padding:10px">
|
||||||
|
<span style="color:var(--ops-text)">Texte principal sur fond de page.</span>
|
||||||
|
<span style="color:var(--ops-text-muted)"> · texte discret</span>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive, onMounted } from 'vue'
|
||||||
|
import { useQuasar } from 'quasar'
|
||||||
|
import { THEME_GROUPS, PRESETS, applyTheme, saveTheme, resetTheme, currentValues } from 'src/composables/useTheme'
|
||||||
|
|
||||||
|
const $q = useQuasar()
|
||||||
|
const groups = THEME_GROUPS
|
||||||
|
const work = reactive({})
|
||||||
|
onMounted(() => { Object.assign(work, currentValues()) })
|
||||||
|
|
||||||
|
function set (t, val) { if (!val) return; work[t.var] = val; applyTheme({ ...work }) }
|
||||||
|
function applyPreset (name) { Object.assign(work, PRESETS[name]); applyTheme({ ...work }) }
|
||||||
|
function save () { saveTheme({ ...work }); $q.notify({ type: 'positive', message: 'Thème enregistré (ce navigateur)' }) }
|
||||||
|
function reset () { resetTheme(); Object.assign(work, currentValues()); $q.notify({ type: 'info', message: 'Thème réinitialisé (défaut)' }) }
|
||||||
|
</script>
|
||||||
Loading…
Reference in New Issue
Block a user