From 2d663f6964c6defc077b86b8258f5bb9acbc1d64 Mon Sep 17 00:00:00 2001 From: nmemmert <67961292+nmemmert@users.noreply.github.com> Date: Mon, 27 Jul 2026 13:17:17 -0400 Subject: [PATCH] Replace details/summary expanders with toggle buttons for list/deck forms New list, Bulk import, New deck, and Bulk import decks are now proper buttons. Clicking one toggles the form open (highlighted blue) and clicking again or cancelling closes it. Only one form open at a time. Co-Authored-By: Claude Sonnet 4.6 --- public/admin.html | 36 ++++++++++++++++++++++-------------- public/admin.js | 39 +++++++++++++++++++++++++++++++++++++-- public/styles.css | 5 +++++ 3 files changed, 64 insertions(+), 16 deletions(-) diff --git a/public/admin.html b/public/admin.html index 7a0b5bf..df4db3b 100644 --- a/public/admin.html +++ b/public/admin.html @@ -305,8 +305,12 @@
-
- New list +
+ + +
+
-
- Bulk import lists +
+ - + @@ -346,8 +350,12 @@
-
- New deck +
+ + +
+
-
- Bulk import decks +
+ - + diff --git a/public/admin.js b/public/admin.js index 69fc223..5bde470 100644 --- a/public/admin.js +++ b/public/admin.js @@ -1368,7 +1368,7 @@ function renderLists(lists) { return w.word; }).join('\n'); $('#list-editor-title').textContent = list.builtin ? 'New list (from copy)' : `Editing: ${list.name}`; - $('#list-editor-details').open = true; + showSection('list', 'editor'); $('#list-name').scrollIntoView({ behavior: 'smooth' }); }) ); @@ -1398,6 +1398,7 @@ $('#list-form').addEventListener('submit', async (e) => { if (id) await api(`/api/lists/${id}`, { method: 'PUT', body: { name, words, groupName } }); else await api('/api/lists', { method: 'POST', body: { name, words, groupName } }); clearListForm(); + hideSections('list'); msg('List saved.'); loadSpelling(); }); @@ -1408,8 +1409,31 @@ function clearListForm() { $('#list-group').value = ''; $('#list-words').value = ''; $('#list-editor-title').textContent = 'New list'; + hideSections('list'); } +function showSection(type, which) { + $(`#${type}-editor-section`).hidden = which !== 'editor'; + $(`#${type}-bulk-section`).hidden = which !== 'bulk'; + $(`#${type}-new-btn`).classList.toggle('active', which === 'editor'); + $(`#${type}-bulk-btn`).classList.toggle('active', which === 'bulk'); +} +function hideSections(type) { + $(`#${type}-editor-section`).hidden = true; + $(`#${type}-bulk-section`).hidden = true; + $(`#${type}-new-btn`).classList.remove('active'); + $(`#${type}-bulk-btn`).classList.remove('active'); +} + +$('#list-new-btn').addEventListener('click', () => { + if ($('#list-editor-section').hidden) showSection('list', 'editor'); + else hideSections('list'); +}); +$('#list-bulk-btn').addEventListener('click', () => { + if ($('#list-bulk-section').hidden) showSection('list', 'bulk'); + else hideSections('list'); +}); + function parseBulkSections(text) { const sections = []; let current = null; @@ -1560,7 +1584,7 @@ async function loadDecks() { $('#deck-group').value = deck.group_name || ''; $('#deck-cards').value = deck.cards.map((c) => `${c.front} | ${c.back}`).join('\n'); $('#deck-editor-title').textContent = deck.builtin ? 'New deck (from copy)' : `Editing: ${deck.name}`; - $('#deck-editor-details').open = true; + showSection('deck', 'editor'); $('#deck-name').scrollIntoView({ behavior: 'smooth' }); }) ); @@ -1590,6 +1614,7 @@ $('#deck-form').addEventListener('submit', async (e) => { if (id) await api(`/api/decks/${id}`, { method: 'PUT', body: { name, cards, groupName } }); else await api('/api/decks', { method: 'POST', body: { name, cards, groupName } }); clearDeckForm(); + hideSections('deck'); msg('Deck saved.'); loadDecks(); }); @@ -1600,8 +1625,18 @@ function clearDeckForm() { $('#deck-group').value = ''; $('#deck-cards').value = ''; $('#deck-editor-title').textContent = 'New deck'; + hideSections('deck'); } +$('#deck-new-btn').addEventListener('click', () => { + if ($('#deck-editor-section').hidden) showSection('deck', 'editor'); + else hideSections('deck'); +}); +$('#deck-bulk-btn').addEventListener('click', () => { + if ($('#deck-bulk-section').hidden) showSection('deck', 'bulk'); + else hideSections('deck'); +}); + $('#deck-bulk-save').addEventListener('click', async () => { const groupName = $('#deck-bulk-group').value.trim(); const sections = parseBulkSections($('#deck-bulk-text').value); diff --git a/public/styles.css b/public/styles.css index 4e190af..72d5599 100644 --- a/public/styles.css +++ b/public/styles.css @@ -338,6 +338,11 @@ table.results tr:nth-child(even) td { background: #faf7ee; } .admin-main h2 { margin: 1.5rem 0 0.5rem; font-size: 1.15rem; } .panel { text-align: left; } +/* ---------- toggle button rows (new/bulk import) ---------- */ +.toggle-btns { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.75rem; } +.toggle-btns button.active { background: var(--accent); color: #fff; } +.section-form-title { font-size: 1rem; font-weight: 700; margin: 0 0 0; color: var(--ink); } + /* 2-column layout for wide screens */ .panel-cols { display: flex; flex-direction: column; gap: 1.5rem; } .panel-col { min-width: 0; }