Types
MFETheme
Gestione tema condiviso tra shell e microfrontend. Stato reattivo isDark, mode light/dark/system e API setTheme/toggleTheme.
Contratto
interface MFETheme {
/** Stato corrente: true se tema scuro attivo */
isDark: boolean
/** Modalità selezionata dall'utente */
mode: 'light' | 'dark' | 'system'
/** Imposta la modalità tema */
setTheme: (mode: 'light' | 'dark' | 'system') => void
/** Alterna tra light e dark */
toggleTheme: () => void
}
Campi
| Campo | Tipo | Descrizione |
|---|---|---|
isDark | boolean | true se il tema scuro è attivo. Risolve 'system' in base alla preferenza OS |
mode | 'light' | 'dark' | 'system' | Modalità scelta dall'utente (potrebbe differire da isDark quando è 'system') |
setTheme(mode) | function | Imposta la modalità. La shell aggiorna isDark di conseguenza |
toggleTheme() | function | Alterna tra 'light' e 'dark'. Se la modalità corrente è 'system', parte da isDark corrente |
Accesso dal MFE
import { useMfeContext } from '@pzeta/mfe-contracts/composables'
const ctx = useMfeContext()
if (ctx.theme?.isDark) {
// applica varianti scure
}
console.log('Modalità utente:', ctx.theme?.mode) // 'system'
Reattività
MFETheme non è un Ref: i campi isDark e mode sono valori sincroni al momento della lettura. La shell deve fornire un meccanismo per reagire ai cambi tema, tipicamente via eventBus:
const ctx = useMfeContext()
function applyTheme() {
document.documentElement.classList.toggle('dark', ctx.theme?.isDark ?? false)
}
onMounted(() => {
applyTheme()
ctx.eventBus?.on('theme-changed', applyTheme)
})
onBeforeUnmount(() => {
ctx.eventBus?.off('theme-changed', applyTheme)
})
In alternativa, la shell può fornire un Ref<MFETheme> esteso nel proprio MFEContext custom.
Pattern: theme switcher nel MFE
<script setup lang="ts">
import { useMfeContext } from '@pzeta/mfe-contracts/composables'
const ctx = useMfeContext()
function setMode(mode: 'light' | 'dark' | 'system') {
ctx.theme?.setTheme(mode)
}
</script>
<template>
<div class="theme-switcher">
<button @click="setMode('light')" :class="{ active: ctx.theme?.mode === 'light' }">
<i class="pi pi-sun" />
</button>
<button @click="setMode('dark')" :class="{ active: ctx.theme?.mode === 'dark' }">
<i class="pi pi-moon" />
</button>
<button @click="setMode('system')" :class="{ active: ctx.theme?.mode === 'system' }">
<i class="pi pi-desktop" />
</button>
</div>
</template>
Implementazione lato shell
Esempio basato su un ref reattivo Vue:
import { ref, computed, watch } from 'vue'
import type { MFETheme } from '@pzeta/mfe-contracts'
const mode = ref<'light' | 'dark' | 'system'>('system')
const systemPrefersDark = ref(matchMedia('(prefers-color-scheme: dark)').matches)
matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
systemPrefersDark.value = e.matches
})
const isDark = computed(() =>
mode.value === 'dark' || (mode.value === 'system' && systemPrefersDark.value),
)
const theme: MFETheme = {
get isDark() { return isDark.value },
get mode() { return mode.value },
setTheme(m) { mode.value = m },
toggleTheme() {
mode.value = isDark.value ? 'light' : 'dark'
},
}
// Emette evento ai MFE quando il tema cambia
watch(isDark, () => eventBus.emit('theme-changed'))
Tipi correlati
MFEContext.theme— accesso dal MFEMFETailwindStyles— estensione palette colori