feat: replace all emojis with SVG icons

This commit is contained in:
2025-10-14 10:17:38 +02:00
parent 55bc38577c
commit fa6d72ea62
10 changed files with 240 additions and 73 deletions

61
public/scripts/icons.js Normal file
View File

@@ -0,0 +1,61 @@
// Centralized SVG Icons for SPORE UI
// Usage: window.icon('cluster', {class: 'foo', width: 16, height: 16}) -> returns inline SVG string
(function(){
const toAttrs = (opts) => {
if (!opts) return '';
const attrs = [];
if (opts.class) attrs.push(`class="${opts.class}"`);
if (opts.width) attrs.push(`width="${opts.width}"`);
if (opts.height) attrs.push(`height="${opts.height}"`);
if (opts.strokeWidth) attrs.push(`stroke-width="${opts.strokeWidth}"`);
return attrs.join(' ');
};
const withSvg = (inner, opts) => {
const attr = toAttrs(opts);
return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" ${attr}>${inner}</svg>`;
};
const Icons = {
// Navigation / sections
cluster: (o) => withSvg(`<circle cx="12" cy="12" r="9"/><circle cx="8" cy="10" r="1.5"/><circle cx="16" cy="8" r="1.5"/><circle cx="14" cy="15" r="1.5"/><path d="M9 11l3 3M9 11l6-3"/>`, o),
topology: (o) => withSvg(`<path d="M6 3v6M6 15v6M18 3v6M18 15v6"/><rect x="3" y="9" width="6" height="6" rx="2"/><rect x="15" y="9" width="6" height="6" rx="2"/>`, o),
monitoring: (o) => withSvg(`<path d="M3 12h3l2 7 4-14 3 10 2-6h4"/>`, o),
firmware: (o) => withSvg(`<path d="M4 7l8-4 8 4v10l-8 4-8-4z"/><path d="M12 8v8"/>`, o),
// Status / feedback
success: (o) => withSvg(`<path d="M20 6L9 17l-5-5"/>`, o),
warning: (o) => withSvg(`<path d="M12 9v4"/><path d="M12 17h.01"/><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L14.71 3.86a2 2 0 0 0-3.42 0z"/>`, o),
error: (o) => withSvg(`<path d="M18 6L6 18M6 6l12 12"/>`, o),
offlineDot: (o) => withSvg(`<circle cx="12" cy="12" r="6" fill="currentColor"/>`, o),
dotGreen: (o) => withSvg(`<circle cx="12" cy="12" r="6" fill="#10b981"/>`, o),
dotYellow: (o) => withSvg(`<circle cx="12" cy="12" r="6" fill="#f59e0b"/>`, o),
dotRed: (o) => withSvg(`<circle cx="12" cy="12" r="6" fill="#ef4444"/>`, o),
// Actions
refresh: (o) => withSvg(`<path d="M3 3v6h6"/><path d="M21 21v-6h-6"/><path d="M20.49 9A9 9 0 0 0 5.64 5.64L3 9m18 6-2.64 2.36A9 9 0 0 1 3.51 15"/>`, o),
terminal: (o) => withSvg(`<path d="M4 17l6-6-6-6"></path><path d="M12 19h8"></path>`, o),
chevronDown: (o) => withSvg(`<path d="M6 9l6 6 6-6"/>`, o),
upload: (o) => withSvg(`<path d="M12 16V4"/><path d="M8 8l4-4 4 4"/><path d="M20 16v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-2"/>`, o),
file: (o) => withSvg(`<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/>`, o),
timer: (o) => withSvg(`<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 3"/>`, o),
cpu: (o) => withSvg(`<rect x="4" y="4" width="16" height="16" rx="2"/><rect x="9" y="9" width="6" height="6"/><path d="M9 1v3M15 1v3M9 20v3M15 20v3M1 9h3M1 15h3M20 9h3M20 15h3"/>`, o),
memory: (o) => withSvg(`<rect x="4" y="8" width="16" height="8" rx="2"/><path d="M7 8v8M12 8v8M17 8v8"/>`, o),
storage: (o) => withSvg(`<rect x="3" y="6" width="18" height="12" rx="2"/><path d="M7 10h10"/>`, o),
computer: (o) => withSvg(`<rect x="3" y="4" width="18" height="12" rx="2"/><path d="M8 20h8"/>`, o),
latency: (o) => withSvg(`<path d="M3 12h4l2 5 4-10 2 7 2-4h4"/>`, o)
};
function icon(name, opts){
const fn = Icons[name];
if (!fn) return '';
return fn(Object.assign({ width: 16, height: 16, strokeWidth: 2 }, opts || {}));
}
if (typeof window !== 'undefined') {
window.Icons = Icons;
window.icon = icon;
}
})();