From fd38481e17fa75ef8dc3709b3cdbdd4ad685cee3 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Mon, 9 Feb 2026 19:18:21 +0300 Subject: [PATCH] Add backdrop click to Add/Edit Template modal, document dialog UI standards - Add backdrop click handlers to showAddTemplateModal() and editTemplate() to close modal when clicking outside - Create new "Frontend UI Patterns" section in CLAUDE.md documenting modal dialog standards - Document backdrop click behavior with code example - Document close button requirements for dialogs with Cancel buttons Co-Authored-By: Claude Sonnet 4.5 --- server/CLAUDE.md | 52 ++++++++++++++++++++++++ server/src/wled_controller/static/app.js | 22 +++++++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/server/CLAUDE.md b/server/CLAUDE.md index ac863e3..b36a57e 100644 --- a/server/CLAUDE.md +++ b/server/CLAUDE.md @@ -6,6 +6,8 @@ **IMPORTANT**: When making changes to server code (Python files in `src/wled_controller/`), you MUST restart the server if it's currently running to ensure the changes take effect. +**NOTE**: Auto-reload is currently disabled (`reload=False` in `main.py`) due to watchfiles causing an infinite reload loop. Changes to server code will NOT be automatically picked up - manual server restart is required. + #### When to restart: - After modifying API routes (`api/routes.py`, `api/schemas.py`) - After updating core logic (`core/*.py`) @@ -102,6 +104,56 @@ After restarting the server with new code: 3. Use `t('key')` function in `static/app.js` for dynamic content 4. No server restart needed (frontend only) +## Frontend UI Patterns + +### Modal Dialogs + +**IMPORTANT**: All modal dialogs must follow these standards for consistent UX: + +#### Backdrop Click Behavior +All modals MUST close when the user clicks outside the dialog (on the backdrop). Implement this by adding a click handler that checks if the clicked element is the modal backdrop itself: + +```javascript +// Show modal +const modal = document.getElementById('my-modal'); +modal.style.display = 'flex'; + +// Add backdrop click handler to close modal +modal.onclick = function(event) { + if (event.target === modal) { + closeMyModal(); + } +}; +``` + +**Where to add**: In every function that shows a modal (e.g., `showAddTemplateModal()`, `editTemplate()`, `showTestTemplateModal()`). + +#### Close Button Requirement +Each modal dialog that has a "Cancel" button MUST also have a cross (×) close button at the top-right corner of the dialog. This provides users with multiple intuitive ways to dismiss the dialog: + +1. Click the backdrop (outside the dialog) +2. Click the × button (top-right corner) +3. Click the Cancel button (bottom of dialog) +4. Press Escape key (if implemented) + +**HTML Structure**: +```html + +``` + +**CSS Requirements**: +- Close button should be positioned absolutely at top-right +- Should be easily clickable (min 24px × 24px hit area) +- Should have clear hover state + ## Authentication Server uses API key authentication. Keys are configured in: diff --git a/server/src/wled_controller/static/app.js b/server/src/wled_controller/static/app.js index 1046691..0685283 100644 --- a/server/src/wled_controller/static/app.js +++ b/server/src/wled_controller/static/app.js @@ -2281,7 +2281,16 @@ async function showAddTemplateModal() { // Load available engines await loadAvailableEngines(); - document.getElementById('template-modal').style.display = 'flex'; + // Show modal + const modal = document.getElementById('template-modal'); + modal.style.display = 'flex'; + + // Add backdrop click handler to close modal + modal.onclick = function(event) { + if (event.target === modal) { + closeTemplateModal(); + } + }; } // Edit template @@ -2315,7 +2324,16 @@ async function editTemplate(templateId) { document.getElementById('template-test-results').style.display = 'none'; document.getElementById('template-error').style.display = 'none'; - document.getElementById('template-modal').style.display = 'flex'; + // Show modal + const modal = document.getElementById('template-modal'); + modal.style.display = 'flex'; + + // Add backdrop click handler to close modal + modal.onclick = function(event) { + if (event.target === modal) { + closeTemplateModal(); + } + }; } catch (error) { console.error('Error loading template:', error); showToast(t('templates.error.load') + ': ' + error.message, 'error');