feat: globale icon-kleuring via .lucide-<name> CSS-injectie

This commit is contained in:
mo
2026-07-21 22:26:19 +02:00
parent 345bc84640
commit 2e0284f372
5 changed files with 213 additions and 144 deletions
+99 -32
View File
@@ -1,45 +1,113 @@
import { createContext, useContext, useEffect, useState } from 'react';
import { api } from './api';
// Legacy standaard-icoonkleuren (fallback als gebruiker ze niet zelf heeft ingesteld)
const DEFAULT_ICON_COLORS = {
'layout-dashboard': '#58a6ff', 'users': '#3fb950', 'briefcase': '#d29922',
'server': '#bc8cff', 'check-circle': '#3fb950', 'lightbulb': '#d29922',
'clock': '#79c0ff', 'eye': '#f778ba', 'phone': '#3fb950', 'file-text': '#f778ba',
'edit-3': '#79c0ff', 'folder': '#d29922', 'clipboard-list': '#bc8cff',
'mail': '#58a6ff', 'calendar': '#79c0ff', 'receipt': '#d29922', 'wallet': '#3fb950',
'bar-chart-3': '#bc8cff', 'share-2': '#58a6ff', 'network': '#00d4ff', 'radar': '#d29922',
'sparkles': '#bc8cff', 'settings': '#8b9bb8', 'shield-check': '#3fb950',
'pen-tool': '#bc8cff', 'file-search': '#d29922', 'folder-kanban': '#d29922', 'cpu': '#58a6ff',
'building-2': '#bc8cff', 'activity': '#58a6ff', 'search': '#8b9bb8', 'bell': '#d29922',
'plus': '#00d4ff', 'trash-2': '#f85149', 'pencil': '#79c0ff', 'star': '#d29922',
'map-pin': '#58a6ff', 'globe': '#58a6ff', 'send': '#00d4ff', 'download': '#79c0ff',
'upload': '#79c0ff', 'save': '#3fb950', 'refresh-cw': '#58a6ff', 'filter': '#8b9bb8',
'more-vertical': '#8b9bb8', 'x': '#8b9bb8', 'menu': '#8b9bb8', 'external-link': '#8b9bb8',
'log-out': '#8b9bb8', 'trending-up': '#3fb950', 'pie-chart': '#bc8cff', 'target': '#d29922',
'shield': '#3fb950', 'zap': '#bc8cff', 'database': '#58a6ff', 'cloud': '#79c0ff',
'hard-drive': '#bc8cff', 'monitor': '#58a6ff', 'git-branch': '#f778ba', 'package': '#d29922',
'terminal': '#79c0ff', 'code': '#58a6ff', 'layers': '#bc8cff', 'link': '#58a6ff',
'unlink': '#8b9bb8', 'copy': '#79c0ff', 'check': '#3fb950', 'alert-triangle': '#d29922',
'info': '#58a6ff', 'help-circle': '#8b9bb8', 'type': '#79c0ff', 'columns': '#bc8cff',
'table': '#58a6ff', 'list': '#79c0ff', 'grid': '#bc8cff', 'tag': '#d29922',
'calendar-days': '#79c0ff', 'mail-open': '#58a6ff', 'inbox': '#58a6ff', 'send-horizontal': '#00d4ff',
'paperclip': '#8b9bb8', 'users-round': '#3fb950', 'projector': '#bc8cff', 'kanban-square': '#d29922',
'bar-chart': '#bc8cff', 'line-chart': '#58a6ff', 'activity-square': '#3fb950',
'server': '#bc8cff', 'wifi': '#58a6ff', 'ethernet-port': '#58a6ff', 'router': '#bc8cff',
'switch': '#3fb950', 'firewall': '#f85149', 'storage': '#bc8cff', 'ups': '#d29922',
'pdu': '#79c0ff', 'cloud-upload': '#58a6ff', 'cloud-download': '#58a6ff',
'brain-circuit': '#bc8cff', 'message-square': '#58a6ff', 'bot': '#bc8cff',
'key': '#f778ba', 'shield-check-big': '#3fb950', 'lock': '#79c0ff', 'unlock': '#8b9bb8'
// Legacy standaard-icoonkleuren (alle Lucide-iconen op de pagina een unieke kleur)
export const DEFAULT_ICON_COLORS = {
// Navigation & Core Domains
'layout-dashboard': '#58a6ff',
'users': '#3fb950',
'briefcase': '#d29922',
'check-circle': '#3fb950',
'check-circle-2': '#3fb950',
'check-square': '#3fb950',
'check-check': '#3fb950',
'calendar': '#79c0ff',
'mail': '#58a6ff',
'mail-plus': '#58a6ff',
'inbox': '#58a6ff',
'folder-kanban': '#d29922',
'clock': '#79c0ff',
'receipt': '#d29922',
'wallet': '#3fb950',
'bar-chart-3': '#bc8cff',
'bar-chart': '#bc8cff',
'server': '#bc8cff',
'share-2': '#58a6ff',
'network': '#00d4ff',
'radar': '#d29922',
'sparkles': '#bc8cff',
'settings': '#8b9bb8',
// Legacy & Platform
'shield-check': '#3fb950',
'pen-tool': '#bc8cff',
'file-search': '#d29922',
// Actions & Tools
'plus': '#00d4ff',
'pencil': '#79c0ff',
'trash-2': '#f85149',
'trash': '#f85149',
'search': '#8b9bb8',
'search-x': '#f85149',
'refresh-cw': '#58a6ff',
'download': '#79c0ff',
'upload': '#79c0ff',
'database-backup': '#bc8cff',
'send': '#00d4ff',
'star': '#d29922',
'bot': '#bc8cff',
'filter': '#8b9bb8',
// Infra & Entities
'building-2': '#bc8cff',
'factory': '#bc8cff',
'map-pin': '#58a6ff',
'cable': '#58a6ff',
'workflow': '#bc8cff',
// Status & Info
'bell': '#d29922',
'file-text': '#f778ba',
'lightbulb': '#d29922',
'alert-triangle': '#f85149',
'activity': '#58a6ff',
'construction': '#d29922',
'flag': '#f85149',
'user': '#3fb950',
'euro': '#3fb950',
'external-link': '#8b9bb8',
'log-out': '#f85149',
'menu': '#8b9bb8',
'x': '#8b9bb8'
};
// Injecteert globale CSS-regels voor alle .lucide-<name> elementen op de pagina
export function injectIconStyles(customColors) {
let styleEl = document.getElementById('mek-icon-colors');
if (!styleEl) {
styleEl = document.createElement('style');
styleEl.id = 'mek-icon-colors';
document.head.appendChild(styleEl);
}
const merged = { ...DEFAULT_ICON_COLORS, ...(customColors || {}) };
let css = '/* Dynamic Icon Colors */\n';
for (const [name, color] of Object.entries(merged)) {
if (!color) continue;
css += `.lucide-${name}, [data-lucide="${name}"] { color: ${color}; }\n`;
}
styleEl.textContent = css;
}
const SettingsContext = createContext({ settings: null, loading: true });
export function SettingsProvider({ children }) {
const [settings, setSettings] = useState(null);
useEffect(() => {
api.get('/settings').then(setSettings).catch(() => setSettings(null));
// Injecteer meteen de standaardkleuren voor snelle weergave
injectIconStyles(null);
api.get('/settings')
.then(s => {
setSettings(s);
if (s?.icon_colors) {
injectIconStyles(s.icon_colors);
}
})
.catch(() => setSettings(null));
}, []);
return (
<SettingsContext.Provider value={{ settings, loading: !settings }}>
{children}
@@ -51,7 +119,6 @@ export function useSettings() {
return useContext(SettingsContext);
}
// Geef de kleur voor een icoon terug (user-instelling of legacy default)
export function iconColor(name, settings) {
if (settings?.icon_colors && settings.icon_colors[name]) return settings.icon_colors[name];
return DEFAULT_ICON_COLORS[name] || null;
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -4,8 +4,8 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mek-Tech — Consultancy Platform</title>
<script type="module" crossorigin src="/app/assets/index-BeV6U3Lw.js"></script>
<link rel="stylesheet" crossorigin href="/app/assets/index-Bc_GiMLN.css">
<script type="module" crossorigin src="/app/assets/index-zN5ia3Gj.js"></script>
<link rel="stylesheet" crossorigin href="/app/assets/index-Cmof3-vz.css">
</head>
<body>
<div id="root"></div>