Replace sections with tabs, add device card to grid
Some checks failed
Validate / validate (push) Failing after 9s

- Switch Devices/Displays from collapsible sections to tab layout
- Remember active tab in localStorage
- Re-render display layout when switching to Displays tab
- Replace floating "+" button with dashed add-device card in grid
- Rename sections to "Devices" and "Displays"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-09 02:07:22 +03:00
parent c9929e3b7f
commit 01114e125e
3 changed files with 98 additions and 57 deletions

View File

@@ -164,8 +164,8 @@ document.addEventListener('DOMContentLoaded', async () => {
// Show content now that translations are loaded
document.body.style.visibility = 'visible';
// Restore collapsible section states
initCollapsibleSections();
// Restore active tab
initTabs();
// Load API key from localStorage
apiKey = localStorage.getItem('wled_api_key');
@@ -298,7 +298,8 @@ async function loadDisplays() {
return;
}
// Render visual layout
// Cache and render visual layout
_cachedDisplays = data.displays;
renderDisplayLayout(data.displays);
} catch (error) {
console.error('Failed to load displays:', error);
@@ -309,25 +310,22 @@ async function loadDisplays() {
}
}
function toggleSection(name) {
const header = document.querySelector(`.collapsible-header[data-section="${name}"]`);
const content = document.getElementById(`${name}-content`);
if (!header || !content) return;
const collapsed = !header.classList.contains('collapsed');
header.classList.toggle('collapsed', collapsed);
content.classList.toggle('collapsed', collapsed);
localStorage.setItem(`section_${name}_collapsed`, collapsed ? '1' : '0');
let _cachedDisplays = null;
function switchTab(name) {
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.toggle('active', btn.dataset.tab === name));
document.querySelectorAll('.tab-panel').forEach(panel => panel.classList.toggle('active', panel.id === `tab-${name}`));
localStorage.setItem('activeTab', name);
if (name === 'displays' && _cachedDisplays) {
requestAnimationFrame(() => renderDisplayLayout(_cachedDisplays));
}
}
function initCollapsibleSections() {
document.querySelectorAll('.collapsible-header[data-section]').forEach(header => {
const name = header.getAttribute('data-section');
const content = document.getElementById(`${name}-content`);
if (localStorage.getItem(`section_${name}_collapsed`) === '1' && content) {
header.classList.add('collapsed');
content.classList.add('collapsed');
}
});
function initTabs() {
const saved = localStorage.getItem('activeTab');
if (saved && document.getElementById(`tab-${saved}`)) {
switchTab(saved);
}
}
function renderDisplayLayout(displays) {
@@ -409,7 +407,10 @@ async function loadDevices() {
const container = document.getElementById('devices-list');
if (!devices || devices.length === 0) {
container.innerHTML = `<div class="loading">${t('devices.none')}</div>`;
container.innerHTML = `<div class="card add-device-card" onclick="showAddDevice()">
<div class="add-device-icon">+</div>
<div class="add-device-label">${t('devices.add')}</div>
</div>`;
return;
}
@@ -473,7 +474,11 @@ async function loadDevices() {
})
);
container.innerHTML = devicesWithState.map(device => createDeviceCard(device)).join('');
container.innerHTML = devicesWithState.map(device => createDeviceCard(device)).join('')
+ `<div class="card add-device-card" onclick="showAddDevice()">
<div class="add-device-icon">+</div>
<div class="add-device-label">${t('devices.add')}</div>
</div>`;
// Update footer WLED Web UI link with first device's URL
const webuiLink = document.querySelector('.wled-webui-link');