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 { createContext, useContext, useEffect, useState } from 'react';
import { api } from './api'; import { api } from './api';
// Legacy standaard-icoonkleuren (fallback als gebruiker ze niet zelf heeft ingesteld) // Legacy standaard-icoonkleuren (alle Lucide-iconen op de pagina een unieke kleur)
const DEFAULT_ICON_COLORS = { export const DEFAULT_ICON_COLORS = {
'layout-dashboard': '#58a6ff', 'users': '#3fb950', 'briefcase': '#d29922', // Navigation & Core Domains
'server': '#bc8cff', 'check-circle': '#3fb950', 'lightbulb': '#d29922', 'layout-dashboard': '#58a6ff',
'clock': '#79c0ff', 'eye': '#f778ba', 'phone': '#3fb950', 'file-text': '#f778ba', 'users': '#3fb950',
'edit-3': '#79c0ff', 'folder': '#d29922', 'clipboard-list': '#bc8cff', 'briefcase': '#d29922',
'mail': '#58a6ff', 'calendar': '#79c0ff', 'receipt': '#d29922', 'wallet': '#3fb950', 'check-circle': '#3fb950',
'bar-chart-3': '#bc8cff', 'share-2': '#58a6ff', 'network': '#00d4ff', 'radar': '#d29922', 'check-circle-2': '#3fb950',
'sparkles': '#bc8cff', 'settings': '#8b9bb8', 'shield-check': '#3fb950', 'check-square': '#3fb950',
'pen-tool': '#bc8cff', 'file-search': '#d29922', 'folder-kanban': '#d29922', 'cpu': '#58a6ff', 'check-check': '#3fb950',
'building-2': '#bc8cff', 'activity': '#58a6ff', 'search': '#8b9bb8', 'bell': '#d29922', 'calendar': '#79c0ff',
'plus': '#00d4ff', 'trash-2': '#f85149', 'pencil': '#79c0ff', 'star': '#d29922', 'mail': '#58a6ff',
'map-pin': '#58a6ff', 'globe': '#58a6ff', 'send': '#00d4ff', 'download': '#79c0ff', 'mail-plus': '#58a6ff',
'upload': '#79c0ff', 'save': '#3fb950', 'refresh-cw': '#58a6ff', 'filter': '#8b9bb8', 'inbox': '#58a6ff',
'more-vertical': '#8b9bb8', 'x': '#8b9bb8', 'menu': '#8b9bb8', 'external-link': '#8b9bb8', 'folder-kanban': '#d29922',
'log-out': '#8b9bb8', 'trending-up': '#3fb950', 'pie-chart': '#bc8cff', 'target': '#d29922', 'clock': '#79c0ff',
'shield': '#3fb950', 'zap': '#bc8cff', 'database': '#58a6ff', 'cloud': '#79c0ff', 'receipt': '#d29922',
'hard-drive': '#bc8cff', 'monitor': '#58a6ff', 'git-branch': '#f778ba', 'package': '#d29922', 'wallet': '#3fb950',
'terminal': '#79c0ff', 'code': '#58a6ff', 'layers': '#bc8cff', 'link': '#58a6ff', 'bar-chart-3': '#bc8cff',
'unlink': '#8b9bb8', 'copy': '#79c0ff', 'check': '#3fb950', 'alert-triangle': '#d29922', 'bar-chart': '#bc8cff',
'info': '#58a6ff', 'help-circle': '#8b9bb8', 'type': '#79c0ff', 'columns': '#bc8cff', 'server': '#bc8cff',
'table': '#58a6ff', 'list': '#79c0ff', 'grid': '#bc8cff', 'tag': '#d29922', 'share-2': '#58a6ff',
'calendar-days': '#79c0ff', 'mail-open': '#58a6ff', 'inbox': '#58a6ff', 'send-horizontal': '#00d4ff', 'network': '#00d4ff',
'paperclip': '#8b9bb8', 'users-round': '#3fb950', 'projector': '#bc8cff', 'kanban-square': '#d29922', 'radar': '#d29922',
'bar-chart': '#bc8cff', 'line-chart': '#58a6ff', 'activity-square': '#3fb950', 'sparkles': '#bc8cff',
'server': '#bc8cff', 'wifi': '#58a6ff', 'ethernet-port': '#58a6ff', 'router': '#bc8cff', 'settings': '#8b9bb8',
'switch': '#3fb950', 'firewall': '#f85149', 'storage': '#bc8cff', 'ups': '#d29922',
'pdu': '#79c0ff', 'cloud-upload': '#58a6ff', 'cloud-download': '#58a6ff', // Legacy & Platform
'brain-circuit': '#bc8cff', 'message-square': '#58a6ff', 'bot': '#bc8cff', 'shield-check': '#3fb950',
'key': '#f778ba', 'shield-check-big': '#3fb950', 'lock': '#79c0ff', 'unlock': '#8b9bb8' '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 }); const SettingsContext = createContext({ settings: null, loading: true });
export function SettingsProvider({ children }) { export function SettingsProvider({ children }) {
const [settings, setSettings] = useState(null); const [settings, setSettings] = useState(null);
useEffect(() => { 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 ( return (
<SettingsContext.Provider value={{ settings, loading: !settings }}> <SettingsContext.Provider value={{ settings, loading: !settings }}>
{children} {children}
@@ -51,7 +119,6 @@ export function useSettings() {
return useContext(SettingsContext); return useContext(SettingsContext);
} }
// Geef de kleur voor een icoon terug (user-instelling of legacy default)
export function iconColor(name, settings) { export function iconColor(name, settings) {
if (settings?.icon_colors && settings.icon_colors[name]) return settings.icon_colors[name]; if (settings?.icon_colors && settings.icon_colors[name]) return settings.icon_colors[name];
return DEFAULT_ICON_COLORS[name] || null; 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 charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mek-Tech — Consultancy Platform</title> <title>Mek-Tech — Consultancy Platform</title>
<script type="module" crossorigin src="/app/assets/index-BeV6U3Lw.js"></script> <script type="module" crossorigin src="/app/assets/index-zN5ia3Gj.js"></script>
<link rel="stylesheet" crossorigin href="/app/assets/index-Bc_GiMLN.css"> <link rel="stylesheet" crossorigin href="/app/assets/index-Cmof3-vz.css">
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>