From 61fc55d3131a86e770a3e4eabe80fee975bce59d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Glasn=C3=A1k?= Date: Tue, 14 Oct 2025 01:42:41 +0200 Subject: [PATCH] fix(datepicker): improve focus handling and scroll position restoration in modal --- .../tm@modal/_mixins/vuetify-fix-focus.ts | 39 ++++++++++++--- .../master-task/z-master-task-modal.vue | 49 +++++++++++++------ .../tm@modal/task/_components/a-timeblock.vue | 11 ++++- 3 files changed, 77 insertions(+), 22 deletions(-) diff --git a/app/src/plugins/tm@modal/_mixins/vuetify-fix-focus.ts b/app/src/plugins/tm@modal/_mixins/vuetify-fix-focus.ts index ce566cc..a3b544d 100644 --- a/app/src/plugins/tm@modal/_mixins/vuetify-fix-focus.ts +++ b/app/src/plugins/tm@modal/_mixins/vuetify-fix-focus.ts @@ -3,6 +3,7 @@ export default { data() { return { preventInputFocus: false, + savedScrollPosition: null, }; }, @@ -20,18 +21,44 @@ export default { }, onDateOpen($event) { - if ($event == undefined) { + // $event should be the element reference (or any truthy value to trigger saving) + if ($event) { + // Find the scrollable modal container + const modalContent = document.querySelector('.v-dialog .modal-content'); + if (modalContent) { + this.savedScrollPosition = modalContent.scrollTop; + } + this.preventInputFocus = true; + + // Reset after datepicker is opened + setTimeout(() => { + this.preventInputFocus = false; + this.savedScrollPosition = null; + }, 500); } }, onInputFocus($event) { - setTimeout(() => { - if (this.preventInputFocus) { - $event.target.blur(); - this.preventInputFocus = false; + // If we have a saved scroll position and an unwanted focus happened + if (this.preventInputFocus && this.savedScrollPosition !== null) { + const target = $event.target; + + // Only intercept text input focus (autocomplete fields) + if (target.tagName === 'INPUT' && target.type === 'text') { + // Blur the focused element + setTimeout(() => { + target.blur(); + + const modalContent = document.querySelector( + '.v-dialog .modal-content', + ); + if (modalContent && this.savedScrollPosition !== null) { + modalContent.scrollTop = this.savedScrollPosition; + } + }, 0); } - }, 100); + } }, }, }; diff --git a/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue b/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue index 5b64aea..e0f4425 100644 --- a/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue +++ b/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue @@ -57,20 +57,26 @@
- +
+ +
diff --git a/app/src/plugins/tm@modal/task/_components/a-timeblock.vue b/app/src/plugins/tm@modal/task/_components/a-timeblock.vue index 6ad2e14..5fdf058 100644 --- a/app/src/plugins/tm@modal/task/_components/a-timeblock.vue +++ b/app/src/plugins/tm@modal/task/_components/a-timeblock.vue @@ -4,14 +4,13 @@