diff --git a/.jules/palette.md b/.jules/palette.md index 2dcd639e..547db036 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -81,3 +81,6 @@ ## 2024-08-04 - 숫자 입력 필드 빈 문자열 상태 초기화 처리 **학습:** 숫자 입력 필드에서 빈 문자열('')을 입력할 때 브라우저는 이전의 유효하지 않은 상태를 암시적으로 유지하므로, 사용자 정의 검증을 명시적으로 초기화하지 않으면 네이티브 HTML5 유효성 검사가 정상 작동하지 않을 수 있음을 확인했습니다. **실행:** 인라인 검증 스크립트 작성 시 빈 문자열 상태를 별도로 확인하여 this.setCustomValidity('') 및 this.removeAttribute('aria-invalid')를 명시적으로 호출하는 로직을 추가해야 합니다. +## 2024-05-15 - Drag-and-drop Visual Feedback +**Learning:** Users lack confidence when dragging files into drop zones if the OS cursor doesn't indicate a valid drop target (e.g., showing a "copy" badge). +**Action:** Always explicitly set `e.dataTransfer.dropEffect = 'copy'` on `dragover` events to provide clear, immediate visual feedback. diff --git a/saas_web.py b/saas_web.py index 63265e94..126e8dba 100644 --- a/saas_web.py +++ b/saas_web.py @@ -372,14 +372,26 @@ async def add_security_headers(request: Request, call_next): zone.addEventListener(eventName, preventDefaults, false); }); ['dragenter', 'dragover'].forEach(eventName => { - zone.addEventListener(eventName, () => zone.classList.add('dragover'), false); + zone.addEventListener(eventName, (e) => { + zone.classList.add('dragover'); + if (e.dataTransfer) { + e.dataTransfer.dropEffect = 'copy'; + } + }, false); }); ['dragleave', 'drop'].forEach(eventName => { zone.addEventListener(eventName, () => zone.classList.remove('dragover'), false); }); }); ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { - document.body.addEventListener(eventName, preventDefaults, false); + document.body.addEventListener(eventName, (e) => { + preventDefaults(e); + if (eventName === 'dragenter' || eventName === 'dragover') { + if (e.dataTransfer) { + e.dataTransfer.dropEffect = 'none'; + } + } + }, false); }); function preventDefaults (e) { e.preventDefault();