diff --git a/.jules/palette.md b/.jules/palette.md index 0bbf5248..b01e606d 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -108,10 +108,14 @@ **Learning:** [When an element is removed from the DOM, focus naturally resets to the document body, breaking the keyboard navigation flow. It is critical to calculate the next logical focus target prior to deletion and programmatically restore focus post-render.] **Action:** [In future components involving item deletion within lists or tables, proactively incorporate index calculations before removing items to manage focus restoration correctly.] -## $(date +%Y-%m-%d) - Add Confirmation Dialog for CSV Import +## 2024-05-31 - Add Confirmation Dialog for CSV Import **Learning:** File import actions that completely overwrite existing application state can lead to severe data loss if triggered accidentally. In a WBS planner where users invest significant time building task hierarchies, destructive imports need explicit user confirmation. **Action:** Always add a confirmation dialog (`window.confirm` or custom modal) for any import or sync action that wipes out the current in-memory or persisted state, especially when there's no undo mechanism. -## $(date +%Y-%m-%d) - Prevent accidental data loss in inline editors +## 2024-05-31 - Prevent accidental data loss in inline editors **Learning:** Forms that take a long time to fill out (like a WBS editor) are prone to accidental closure by users pressing `Escape` or clicking cancel. This causes immediate data loss without any warning, resulting in frustration. **Action:** When working on editors that can be dismissed, track whether the user has modified any fields compared to their initial state. If there are changes, intercept the close action and present a confirmation dialog (`window.confirm`) to ensure they really want to discard their edits. Bypass this for intentional saves or explicit data overrides. + +## 2024-05-31 - Add Actionable Feedback for aria-disabled Form Submissions +**Learning:** Replacing native `disabled` with `aria-disabled` allows form inputs (like buttons) to remain focusable. However, if a user attempts to submit a form via an `aria-disabled` button without additional feedback, they may be confused as to why the form is not submitting, since the button intercepts the click/enter key but silently fails. +**Action:** When using `aria-disabled` on submit buttons, ensure that intercepting the submit action (e.g., in a `saveEditor` function) provides immediate, actionable feedback (like a toast notification) explaining why the submission was blocked. diff --git a/app.js b/app.js index a04aae71..b3d6e0a4 100644 --- a/app.js +++ b/app.js @@ -1068,7 +1068,12 @@ function renderEditorValidation() { const saveButton = form.querySelector('button[type="submit"]'); if (saveButton) { - saveButton.disabled = errors.length > 0; + saveButton.disabled = false; + if (errors.length > 0) { + saveButton.setAttribute('aria-disabled', 'true'); + } else { + saveButton.removeAttribute('aria-disabled'); + } saveButton.title = errors.length > 0 ? '입력값을 올바르게 수정해야 저장할 수 있습니다.' : '저장 (Enter)'; } @@ -1237,6 +1242,7 @@ function saveEditor() { if (errors.length > 0) { state.editor.errors = errors; renderEditorValidation(); + showToast('입력값을 올바르게 수정해야 저장할 수 있습니다.'); return; }