diff --git a/frontend/src/components/drawers/expert/ExpertDrawer.vue b/frontend/src/components/drawers/expert/ExpertDrawer.vue
index 4c2878c6e1..b7ab60d7c4 100644
--- a/frontend/src/components/drawers/expert/ExpertDrawer.vue
+++ b/frontend/src/components/drawers/expert/ExpertDrawer.vue
@@ -35,7 +35,7 @@
-
+
@@ -90,9 +90,9 @@ export default {
}
},
mounted () {
- // Wait for drawer slide-in animation to complete (300ms) before focusing
+ // Wait for drawer slide-in animation to complete (300ms) before focusing the chat input
setTimeout(() => {
- this.$refs.drawer?.focus()
+ this.$refs.panel?.focusInput()
}, 350)
},
methods: {
diff --git a/frontend/src/components/expert/Expert.vue b/frontend/src/components/expert/Expert.vue
index e0298b2017..ae82a1b764 100644
--- a/frontend/src/components/expert/Expert.vue
+++ b/frontend/src/components/expert/Expert.vue
@@ -18,7 +18,7 @@
-
+
@@ -153,6 +153,9 @@ export default {
]),
...mapActions(useProductExpertInsightsAgentStore, ['getCapabilities']),
...mapActions(useProductAssistantStore, ['reset']),
+ focusInput () {
+ this.$refs.chatInput?.focusInput()
+ },
handleStopGeneration () {
if (this.abortController) {
this.abortController.abort()
diff --git a/frontend/src/components/expert/components/ExpertChatInput.vue b/frontend/src/components/expert/components/ExpertChatInput.vue
index 0b4bfc8807..a485e64d76 100644
--- a/frontend/src/components/expert/components/ExpertChatInput.vue
+++ b/frontend/src/components/expert/components/ExpertChatInput.vue
@@ -242,6 +242,11 @@ export default {
}
},
watch: {
+ isWaitingForResponse (waiting, wasWaiting) {
+ if (wasWaiting && !waiting) {
+ this.$nextTick(() => this.$refs.textarea?.focus())
+ }
+ },
pendingInput (text) {
if (text) {
this.inputText = text
@@ -282,6 +287,9 @@ export default {
methods: {
...mapActions(useProductAssistantStore, ['resetContextSelection']),
...mapActions(useProductExpertStore, ['startOver', 'handleQuery', 'setPendingInput', 'setComposerCommand', 'setQuestionCadence', 'setPlanMode', 'fetchToolCatalog']),
+ focusInput () {
+ this.$refs.textarea?.focus()
+ },
openSettings () {
this.$refs.settingsDialog.show()
},
@@ -295,15 +303,10 @@ export default {
this.togglePinWithWidth()
}
- // handleQuery renders the reply itself (see the store); the composer only needs
- // to refocus the input once the turn is on its way.
- this.handleQuery({ query: message })
- .then(() => {
- this.$nextTick(() => {
- this.$refs.textarea.focus()
- })
- })
- .catch(e => e)
+ // handleQuery renders the reply itself (see the store); the isWaitingForResponse
+ // watcher refocuses the input once the response completes (works for both HTTP
+ // and MQTT, where the promise resolves before the actual response arrives).
+ this.handleQuery({ query: message }).catch(e => e)
this.inputText = ''
this.requestingPlanChange = false