Fix accueil : hero fade doux, icônes safelist, blocs cliquables, menu, dark fort
- Hero : réécriture composable timeout pur (plus de Transition callbacks) Animation fade opacity 1s très douce, lisible - Icônes : safelist UnoCSS dans nuxt.config.ts (résout pastilles vides) - Menu : mis à jour site.yml (Numérique/Économique/Citoyenne/Événement) - Blocs : card entière cliquable, zone actions séparée (border-top) - Économie du don : lié à /modele-eco (page chapitres préservée) - Tarifs de l'eau : bouton SejeteralO (localhost:3009 / collectivites.librodrome.org) - Dark theme fort : bg 220 12% 15%, surface 19%, surface-light 24% - Config SejeteralO + Glibredecision dans app.config.ts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,76 +6,79 @@ export interface TypewriterSentence {
|
||||
}
|
||||
|
||||
interface SequenceOptions {
|
||||
fadeMs?: number
|
||||
holdMs?: number
|
||||
gapMs?: number
|
||||
}
|
||||
|
||||
export function useTypewriter(sentences: TypewriterSentence[], options: SequenceOptions = {}) {
|
||||
const {
|
||||
holdMs = 2400,
|
||||
fadeMs = 1000,
|
||||
holdMs = 2800,
|
||||
gapMs = 300,
|
||||
} = options
|
||||
|
||||
const currentIndex = ref(-1)
|
||||
const showActive = ref(false)
|
||||
const currentText = ref('')
|
||||
const currentStyle = ref<string>('title')
|
||||
const isVisible = ref(false)
|
||||
const lockedSentences = ref<TypewriterSentence[]>([])
|
||||
const isComplete = ref(false)
|
||||
|
||||
let holdTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const currentSentence = computed(() =>
|
||||
currentIndex.value >= 0 && currentIndex.value < sentences.length
|
||||
? sentences[currentIndex.value]
|
||||
: null,
|
||||
)
|
||||
let currentIdx = -1
|
||||
let timer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
function clearTimer() {
|
||||
if (holdTimer) {
|
||||
clearTimeout(holdTimer)
|
||||
holdTimer = null
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
timer = null
|
||||
}
|
||||
}
|
||||
|
||||
function showNext() {
|
||||
const nextIdx = currentIndex.value + 1
|
||||
if (nextIdx >= sentences.length) {
|
||||
function next() {
|
||||
currentIdx++
|
||||
if (currentIdx >= sentences.length) {
|
||||
currentText.value = ''
|
||||
isComplete.value = true
|
||||
return
|
||||
}
|
||||
|
||||
currentIndex.value = nextIdx
|
||||
const sentence = sentences[nextIdx]
|
||||
const sentence = sentences[currentIdx]
|
||||
|
||||
if (sentence.separator) {
|
||||
lockedSentences.value = [...lockedSentences.value, { text: '', separator: true }]
|
||||
}
|
||||
|
||||
showActive.value = true
|
||||
}
|
||||
// Set text while invisible
|
||||
currentText.value = sentence.text
|
||||
currentStyle.value = sentence.style || 'title'
|
||||
|
||||
/** Called by component via @after-enter on Transition */
|
||||
function onEntered() {
|
||||
holdTimer = setTimeout(() => {
|
||||
showActive.value = false
|
||||
}, holdMs)
|
||||
}
|
||||
// Fade in on next frame
|
||||
requestAnimationFrame(() => {
|
||||
isVisible.value = true
|
||||
})
|
||||
|
||||
/** Called by component via @after-leave on Transition */
|
||||
function onLeft() {
|
||||
const sentence = sentences[currentIndex.value]
|
||||
if (sentence?.stays) {
|
||||
lockedSentences.value = [...lockedSentences.value, { ...sentence }]
|
||||
}
|
||||
setTimeout(showNext, gapMs)
|
||||
// After fade-in + hold → fade out
|
||||
timer = setTimeout(() => {
|
||||
isVisible.value = false
|
||||
|
||||
// After fade-out completes → lock if stays, then next
|
||||
timer = setTimeout(() => {
|
||||
if (sentence.stays) {
|
||||
lockedSentences.value = [...lockedSentences.value, { ...sentence }]
|
||||
}
|
||||
timer = setTimeout(next, gapMs)
|
||||
}, fadeMs)
|
||||
}, fadeMs + holdMs)
|
||||
}
|
||||
|
||||
function start() {
|
||||
showNext()
|
||||
next()
|
||||
}
|
||||
|
||||
function skipToEnd() {
|
||||
clearTimer()
|
||||
showActive.value = false
|
||||
isVisible.value = false
|
||||
currentText.value = ''
|
||||
|
||||
const locked: TypewriterSentence[] = []
|
||||
for (const sentence of sentences) {
|
||||
@@ -88,20 +91,18 @@ export function useTypewriter(sentences: TypewriterSentence[], options: Sequence
|
||||
}
|
||||
|
||||
lockedSentences.value = locked
|
||||
currentIndex.value = sentences.length - 1
|
||||
currentIdx = sentences.length - 1
|
||||
isComplete.value = true
|
||||
}
|
||||
|
||||
onUnmounted(clearTimer)
|
||||
|
||||
return {
|
||||
currentIndex: readonly(currentIndex),
|
||||
currentSentence,
|
||||
showActive,
|
||||
currentText: readonly(currentText),
|
||||
currentStyle: readonly(currentStyle),
|
||||
isVisible,
|
||||
lockedSentences: readonly(lockedSentences),
|
||||
isComplete: readonly(isComplete),
|
||||
onEntered,
|
||||
onLeft,
|
||||
start,
|
||||
skipToEnd,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user