Replace all emoji icons with Lucide SVGs, add accent color picker
- Replace all emoji characters across WebUI with inline Lucide SVG icons for cross-platform consistency (icon paths in icon-paths.js) - Add accent color picker popover with 9 preset colors + custom picker, persisted to localStorage, updates all CSS custom properties - Remove subtab separator line for cleaner look - Color badge icons with accent color for visual pop - Remove processing badge from target cards - Fix hardcoded #4CAF50 in FPS labels and active badges to use CSS vars - Replace CSS content emoji (▶) with pure CSS triangle Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ import { startAutoRefresh, updateTabBadge } from './tabs.js';
|
||||
import {
|
||||
getTargetTypeIcon,
|
||||
ICON_TARGET, ICON_PROFILE, ICON_CLOCK, ICON_WARNING, ICON_OK,
|
||||
ICON_STOP, ICON_STOP_PLAIN, ICON_AUTOSTART,
|
||||
ICON_STOP, ICON_STOP_PLAIN, ICON_START, ICON_AUTOSTART, ICON_HELP,
|
||||
} from '../core/icons.js';
|
||||
|
||||
const DASHBOARD_COLLAPSED_KEY = 'dashboard_collapsed';
|
||||
@@ -64,7 +64,7 @@ function _startUptimeTimer() {
|
||||
if (!el) continue;
|
||||
const seconds = _getInterpolatedUptime(id);
|
||||
if (seconds != null) {
|
||||
el.textContent = `${ICON_CLOCK} ${formatUptime(seconds)}`;
|
||||
el.innerHTML = `${ICON_CLOCK} ${formatUptime(seconds)}`;
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
@@ -218,7 +218,7 @@ function _updateRunningMetrics(enrichedRunning) {
|
||||
}
|
||||
|
||||
const errorsEl = cached?.errors || document.querySelector(`[data-errors-text="${target.id}"]`);
|
||||
if (errorsEl) errorsEl.textContent = `${errors > 0 ? ICON_WARNING : ICON_OK} ${errors}`;
|
||||
if (errorsEl) errorsEl.innerHTML = `${errors > 0 ? ICON_WARNING : ICON_OK} ${errors}`;
|
||||
|
||||
// Update health dot — prefer streaming reachability when processing
|
||||
const isLed = target.target_type === 'led' || target.target_type === 'wled';
|
||||
@@ -267,7 +267,7 @@ function _updateProfilesInPlace(profiles) {
|
||||
if (btn) {
|
||||
btn.className = `btn btn-icon ${p.enabled ? 'btn-warning' : 'btn-success'}`;
|
||||
btn.setAttribute('onclick', `dashboardToggleProfile('${p.id}', ${!p.enabled})`);
|
||||
btn.textContent = p.enabled ? ICON_STOP_PLAIN : '▶';
|
||||
btn.innerHTML = p.enabled ? ICON_STOP_PLAIN : ICON_START;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -460,7 +460,7 @@ export async function loadDashboard(forceFullRender = false) {
|
||||
</div>
|
||||
<div class="dashboard-target-actions">
|
||||
<button class="btn btn-icon ${isRunning ? 'btn-warning' : 'btn-success'}" onclick="${isRunning ? `dashboardStopTarget('${target.id}')` : `dashboardStartTarget('${target.id}')`}" title="${isRunning ? t('device.stop') : t('device.start')}">
|
||||
${isRunning ? ICON_STOP_PLAIN : '▶'}
|
||||
${isRunning ? ICON_STOP_PLAIN : ICON_START}
|
||||
</button>
|
||||
</div>
|
||||
</div>`;
|
||||
@@ -518,7 +518,7 @@ export async function loadDashboard(forceFullRender = false) {
|
||||
// First load: build everything in one innerHTML to avoid flicker
|
||||
const isFirstLoad = !container.querySelector('.dashboard-perf-persistent');
|
||||
const pollSelect = _renderPollIntervalSelect();
|
||||
const toolbar = `<div class="stream-tab-bar"><span class="cs-expand-collapse-group">${pollSelect}<button class="tutorial-trigger-btn" onclick="startDashboardTutorial()" title="${t('tour.restart')}">?</button></span></div>`;
|
||||
const toolbar = `<div class="stream-tab-bar"><span class="cs-expand-collapse-group">${pollSelect}<button class="tutorial-trigger-btn" onclick="startDashboardTutorial()" title="${t('tour.restart')}">${ICON_HELP}</button></span></div>`;
|
||||
if (isFirstLoad) {
|
||||
container.innerHTML = `${toolbar}<div class="dashboard-perf-persistent dashboard-section">
|
||||
${_sectionHeader('perf', t('dashboard.section.performance'), '')}
|
||||
@@ -639,7 +639,7 @@ function renderDashboardTarget(target, isRunning, devicesMap = {}, cssSourceMap
|
||||
<div class="dashboard-target-metrics"></div>
|
||||
<div class="dashboard-target-actions">
|
||||
<button class="dashboard-autostart-btn${target.auto_start ? ' active' : ''}" onclick="dashboardToggleAutoStart('${target.id}', ${!target.auto_start})" title="${target.auto_start ? t('autostart.toggle.enabled') : t('autostart.toggle.disabled')}">★</button>
|
||||
<button class="btn btn-icon btn-success" onclick="dashboardStartTarget('${target.id}')" title="${t('device.button.start')}">▶</button>
|
||||
<button class="btn btn-icon btn-success" onclick="dashboardStartTarget('${target.id}')" title="${t('device.button.start')}">${ICON_START}</button>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
@@ -690,7 +690,7 @@ function renderDashboardProfile(profile) {
|
||||
</div>
|
||||
<div class="dashboard-target-actions">
|
||||
<button class="btn btn-icon ${profile.enabled ? 'btn-warning' : 'btn-success'}" onclick="dashboardToggleProfile('${profile.id}', ${!profile.enabled})" title="${profile.enabled ? t('profiles.action.disable') : t('profiles.status.active')}">
|
||||
${profile.enabled ? ICON_STOP_PLAIN : '▶'}
|
||||
${profile.enabled ? ICON_STOP_PLAIN : ICON_START}
|
||||
</button>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
Reference in New Issue
Block a user