feat: Système de paramètres d'affichage et accessibilité
- DisplaySettings.vue : Modal pour configurer l'affichage - Contrôles de zoom (80% à 150%) - Densité de l'interface (compacte, confortable, espacée) - Contraste (normal, élevé) - Persistance des paramètres via localStorage - Protection du modal contre les transformations de zoom
This commit is contained in:
203
app/components/DisplaySettings.vue
Normal file
203
app/components/DisplaySettings.vue
Normal file
@@ -0,0 +1,203 @@
|
||||
<template>
|
||||
<div class="modal" :class="{ 'modal-open': isOpen }">
|
||||
<div class="modal-box">
|
||||
<h3 class="font-bold text-lg mb-4">Paramètres d'affichage</h3>
|
||||
|
||||
<!-- Contrôle du zoom -->
|
||||
<div class="form-control mb-4">
|
||||
<label class="label">
|
||||
<span class="label-text">Taille du texte</span>
|
||||
<span class="label-text-alt">{{ zoomLevel }}%</span>
|
||||
</label>
|
||||
<input
|
||||
type="range"
|
||||
min="80"
|
||||
max="150"
|
||||
step="10"
|
||||
:value="zoomLevel"
|
||||
@input="updateZoom"
|
||||
class="range range-primary"
|
||||
/>
|
||||
<div class="w-full flex justify-between text-xs px-2 mt-1">
|
||||
<span>80%</span>
|
||||
<span>100%</span>
|
||||
<span>150%</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Contrôle de la densité -->
|
||||
<div class="form-control mb-4">
|
||||
<label class="label">
|
||||
<span class="label-text">Densité de l'interface</span>
|
||||
</label>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
@click="setDensity('compact')"
|
||||
class="btn btn-sm"
|
||||
:class="density === 'compact' ? 'btn-primary' : 'btn-outline'"
|
||||
>
|
||||
Compacte
|
||||
</button>
|
||||
<button
|
||||
@click="setDensity('comfortable')"
|
||||
class="btn btn-sm"
|
||||
:class="density === 'comfortable' ? 'btn-primary' : 'btn-outline'"
|
||||
>
|
||||
Confortable
|
||||
</button>
|
||||
<button
|
||||
@click="setDensity('spacious')"
|
||||
class="btn btn-sm"
|
||||
:class="density === 'spacious' ? 'btn-primary' : 'btn-outline'"
|
||||
>
|
||||
Espacée
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Contrôle du contraste -->
|
||||
<div class="form-control mb-4">
|
||||
<label class="label">
|
||||
<span class="label-text">Contraste</span>
|
||||
</label>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
@click="setContrast('normal')"
|
||||
class="btn btn-sm"
|
||||
:class="contrast === 'normal' ? 'btn-primary' : 'btn-outline'"
|
||||
>
|
||||
Normal
|
||||
</button>
|
||||
<button
|
||||
@click="setContrast('high')"
|
||||
class="btn btn-sm"
|
||||
:class="contrast === 'high' ? 'btn-primary' : 'btn-outline'"
|
||||
>
|
||||
Élevé
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Réinitialiser -->
|
||||
<div class="form-control">
|
||||
<button
|
||||
@click="resetSettings"
|
||||
class="btn btn-outline btn-sm"
|
||||
>
|
||||
Réinitialiser les paramètres
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="modal-action">
|
||||
<button @click="closeModal" class="btn btn-primary">Fermer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
isOpen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['close', 'update-settings'])
|
||||
|
||||
// Paramètres d'affichage
|
||||
const zoomLevel = ref(100)
|
||||
const density = ref('comfortable')
|
||||
const contrast = ref('normal')
|
||||
|
||||
// Charger les paramètres depuis le localStorage
|
||||
onMounted(() => {
|
||||
const savedZoom = localStorage.getItem('display-zoom')
|
||||
const savedDensity = localStorage.getItem('display-density')
|
||||
const savedContrast = localStorage.getItem('display-contrast')
|
||||
|
||||
if (savedZoom) zoomLevel.value = parseInt(savedZoom)
|
||||
if (savedDensity) density.value = savedDensity
|
||||
if (savedContrast) contrast.value = savedContrast
|
||||
|
||||
applySettings()
|
||||
})
|
||||
|
||||
const updateZoom = (event) => {
|
||||
zoomLevel.value = parseInt(event.target.value)
|
||||
applySettings()
|
||||
}
|
||||
|
||||
const setDensity = (newDensity) => {
|
||||
density.value = newDensity
|
||||
applySettings()
|
||||
}
|
||||
|
||||
const setContrast = (newContrast) => {
|
||||
contrast.value = newContrast
|
||||
applySettings()
|
||||
}
|
||||
|
||||
const applySettings = () => {
|
||||
// Sauvegarder dans localStorage
|
||||
localStorage.setItem('display-zoom', zoomLevel.value.toString())
|
||||
localStorage.setItem('display-density', density.value)
|
||||
localStorage.setItem('display-contrast', contrast.value)
|
||||
|
||||
// Appliquer les styles
|
||||
const root = document.documentElement
|
||||
|
||||
// Zoom - exclure complètement le modal des paramètres
|
||||
const modal = document.querySelector('.modal')
|
||||
if (modal) {
|
||||
// Forcer la taille normale pour le modal et tous ses enfants
|
||||
modal.style.fontSize = '100%'
|
||||
modal.style.transform = 'none'
|
||||
modal.style.scale = '1'
|
||||
|
||||
// Appliquer aux enfants du modal
|
||||
const modalElements = modal.querySelectorAll('*')
|
||||
modalElements.forEach(element => {
|
||||
element.style.fontSize = 'inherit'
|
||||
element.style.transform = 'none'
|
||||
element.style.scale = '1'
|
||||
})
|
||||
}
|
||||
|
||||
// Appliquer le zoom au reste de la page (sauf le modal)
|
||||
root.style.fontSize = `${zoomLevel.value}%`
|
||||
|
||||
// Densité - utiliser les classes DaisyUI
|
||||
root.classList.remove('density-compact', 'density-comfortable', 'density-spacious')
|
||||
root.classList.add(`density-${density.value}`)
|
||||
|
||||
// Contraste - utiliser les classes DaisyUI
|
||||
root.classList.remove('contrast-normal', 'contrast-high')
|
||||
root.classList.add(`contrast-${contrast.value}`)
|
||||
|
||||
// Émettre les changements
|
||||
emit('update-settings', {
|
||||
zoom: zoomLevel.value,
|
||||
density: density.value,
|
||||
contrast: contrast.value
|
||||
})
|
||||
}
|
||||
|
||||
const resetSettings = () => {
|
||||
zoomLevel.value = 100
|
||||
density.value = 'comfortable'
|
||||
contrast.value = 'normal'
|
||||
applySettings()
|
||||
}
|
||||
|
||||
const closeModal = () => {
|
||||
emit('close')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Les styles sont maintenant gérés par DaisyUI et le CSS global */
|
||||
</style>
|
||||
Reference in New Issue
Block a user