| 1 |
import { watch, onMounted, onUnmounted } from 'vue' |
| 2 |
import { useSettingsStore } from '@/stores/useSettingsStore' |
| 3 |
|
| 4 |
/** |
| 5 |
* Composable for managing WCAG-compliant color switching |
| 6 |
* Dynamically updates CSS variables based on WCAG backend compliance setting |
| 7 |
*/ |
| 8 |
export const useWcagColors = () => { |
| 9 |
const settingsStore = useSettingsStore() |
| 10 |
|
| 11 |
// Map of regular CSS variables to their WCAG equivalents |
| 12 |
const colorMap = { |
| 13 |
// Brand fill colors |
| 14 |
'--map-base-brand-fill-4': '--map-base-brand-fill-wcag-4', |
| 15 |
'--map-base-brand-fill-3': '--map-base-brand-fill-wcag-3', |
| 16 |
'--map-base-brand-fill-2': '--map-base-brand-fill-wcag-2', |
| 17 |
'--map-base-brand-fill-1': '--map-base-brand-fill-wcag-1', |
| 18 |
'--map-base-brand-fill-0': '--map-base-brand-fill-wcag-0', |
| 19 |
'--map-base-brand-fill--1': '--map-base-brand-fill-wcag--1', |
| 20 |
'--map-base-brand-fill--2': '--map-base-brand-fill-wcag--2', |
| 21 |
'--map-base-brand-fill--3': '--map-base-brand-fill-wcag--3', |
| 22 |
'--map-base-brand-fill--4': '--map-base-brand-fill-wcag--4', |
| 23 |
|
| 24 |
// Brand symbol colors |
| 25 |
'--map-base-brand-symbol-2': '--map-base-brand-symbol-wcag-2', |
| 26 |
'--map-base-brand-symbol-1': '--map-base-brand-symbol-wcag-1', |
| 27 |
'--map-base-brand-symbol-0': '--map-base-brand-symbol-wcag-0', |
| 28 |
'--map-base-brand-symbol--1': '--map-base-brand-symbol-wcag--1', |
| 29 |
|
| 30 |
// Purple colors |
| 31 |
'--map-base-purple-o05': '--map-base-purple-wcag-o03', |
| 32 |
|
| 33 |
// Dusk colors |
| 34 |
'--map-base-dusk-o05': '--map-base-dusk-wcag-o03', |
| 35 |
|
| 36 |
// Alpha colors |
| 37 |
'--map-base-brand-o05': '--map-base-brand-wcag-o03', |
| 38 |
} |
| 39 |
|
| 40 |
// Regular CSS variable values (non-WCAG) |
| 41 |
const regularColorValues = { |
| 42 |
'--map-base-brand-fill-4': 'var(--theme-base-brand-4)', |
| 43 |
'--map-base-brand-fill-3': 'var(--theme-base-brand-3)', |
| 44 |
'--map-base-brand-fill-2': 'var(--theme-base-brand-2)', |
| 45 |
'--map-base-brand-fill-1': 'var(--theme-base-brand-1)', |
| 46 |
'--map-base-brand-fill-0': 'var(--theme-base-brand-0)', |
| 47 |
'--map-base-brand-fill--1': 'var(--theme-base-brand--1)', |
| 48 |
'--map-base-brand-fill--2': 'var(--theme-base-brand--2)', |
| 49 |
'--map-base-brand-fill--3': 'var(--theme-base-brand--3)', |
| 50 |
'--map-base-brand-fill--4': 'var(--theme-base-brand--4)', |
| 51 |
'--map-base-brand-o05': 'var(--theme-base-brand-o05)', |
| 52 |
|
| 53 |
// Brand symbol colors |
| 54 |
'--map-base-brand-symbol-2': 'var(--theme-base-brand-2)', |
| 55 |
'--map-base-brand-symbol-1': 'var(--theme-base-brand-1)', |
| 56 |
'--map-base-brand-symbol-0': 'var(--theme-base-brand-0)', |
| 57 |
'--map-base-brand-symbol--1': 'var(--theme-base-brand--1)', |
| 58 |
|
| 59 |
// Purple colors |
| 60 |
'--map-base-purple-o05': 'var(--theme-base-purple-o05)', |
| 61 |
|
| 62 |
// Dusk colors |
| 63 |
'--map-base-dusk-o05': 'var(--theme-base-dusk-o05)', |
| 64 |
} |
| 65 |
|
| 66 |
// WCAG CSS variable values |
| 67 |
const wcagColorValues = { |
| 68 |
'--map-base-brand-fill-4': 'var(--theme-base-brand-wcag-4)', |
| 69 |
'--map-base-brand-fill-3': 'var(--theme-base-brand-wcag-3)', |
| 70 |
'--map-base-brand-fill-2': 'var(--theme-base-brand-wcag-2)', |
| 71 |
'--map-base-brand-fill-1': 'var(--theme-base-brand-wcag-1)', |
| 72 |
'--map-base-brand-fill-0': 'var(--theme-base-brand-wcag-0)', |
| 73 |
'--map-base-brand-fill--1': 'var(--theme-base-brand-wcag--1)', |
| 74 |
'--map-base-brand-fill--2': 'var(--theme-base-brand-wcag--2)', |
| 75 |
'--map-base-brand-fill--3': 'var(--theme-base-brand-wcag--3)', |
| 76 |
'--map-base-brand-fill--4': 'var(--theme-base-brand-wcag--4)', |
| 77 |
'--map-base-brand-o05': 'var(--theme-base-brand-wcag-o03)', |
| 78 |
|
| 79 |
// Brand symbol WCAG colors |
| 80 |
'--map-base-brand-symbol-2': 'var(--theme-base-brand-wcag-2)', |
| 81 |
'--map-base-brand-symbol-1': 'var(--theme-base-brand-wcag-1)', |
| 82 |
'--map-base-brand-symbol-0': 'var(--theme-base-brand-wcag-0)', |
| 83 |
'--map-base-brand-symbol--1': 'var(--theme-base-brand-wcag--1)', |
| 84 |
|
| 85 |
// Purple WCAG colors |
| 86 |
'--map-base-purple-o05': 'var(--theme-base-purple-wcag-o03)', |
| 87 |
|
| 88 |
// Dusk WCAG colors |
| 89 |
'--map-base-dusk-o05': 'var(--theme-base-dusk-wcag-o03)', |
| 90 |
} |
| 91 |
|
| 92 |
/** |
| 93 |
* Update CSS variables on document root based on WCAG compliance setting |
| 94 |
*/ |
| 95 |
const updateCssVariables = (useWcagColors: boolean) => { |
| 96 |
const root = document.documentElement |
| 97 |
|
| 98 |
if (useWcagColors) { |
| 99 |
// Apply WCAG-compliant colors |
| 100 |
Object.entries(wcagColorValues).forEach(([variable, value]) => { |
| 101 |
root.style.setProperty(variable, value) |
| 102 |
}) |
| 103 |
|
| 104 |
// Add WCAG class to body for additional styling if needed |
| 105 |
document.body.classList.add('wcag-compliant') |
| 106 |
document.body.classList.remove('wcag-disabled') |
| 107 |
} else { |
| 108 |
// Apply regular colors |
| 109 |
Object.entries(regularColorValues).forEach(([variable, value]) => { |
| 110 |
root.style.setProperty(variable, value) |
| 111 |
}) |
| 112 |
|
| 113 |
// Remove WCAG class from body |
| 114 |
document.body.classList.remove('wcag-compliant') |
| 115 |
document.body.classList.add('wcag-disabled') |
| 116 |
} |
| 117 |
} |
| 118 |
|
| 119 |
/** |
| 120 |
* Initialize WCAG color system |
| 121 |
*/ |
| 122 |
const initializeWcagColors = () => { |
| 123 |
// Apply initial colors based on current setting |
| 124 |
updateCssVariables(settingsStore.wcagBackendCompliance) |
| 125 |
} |
| 126 |
|
| 127 |
/** |
| 128 |
* Watch for changes in WCAG compliance setting |
| 129 |
*/ |
| 130 |
let stopWatcher: (() => void) | null = null |
| 131 |
|
| 132 |
const startWatching = () => { |
| 133 |
stopWatcher = watch( |
| 134 |
() => settingsStore.wcagBackendCompliance, |
| 135 |
(newValue) => { |
| 136 |
updateCssVariables(newValue) |
| 137 |
}, |
| 138 |
{ immediate: true }, |
| 139 |
) |
| 140 |
} |
| 141 |
|
| 142 |
const stopWatching = () => { |
| 143 |
if (stopWatcher) { |
| 144 |
stopWatcher() |
| 145 |
stopWatcher = null |
| 146 |
} |
| 147 |
} |
| 148 |
|
| 149 |
// Lifecycle management |
| 150 |
onMounted(() => { |
| 151 |
initializeWcagColors() |
| 152 |
startWatching() |
| 153 |
}) |
| 154 |
|
| 155 |
onUnmounted(() => { |
| 156 |
stopWatching() |
| 157 |
}) |
| 158 |
|
| 159 |
return { |
| 160 |
updateCssVariables, |
| 161 |
initializeWcagColors, |
| 162 |
startWatching, |
| 163 |
stopWatching, |
| 164 |
colorMap, |
| 165 |
regularColorValues, |
| 166 |
wcagColorValues, |
| 167 |
} |
| 168 |
} |
| 169 |
|