From b6512b2d8c13d8c06862fcea5e19b2fbdd457912 Mon Sep 17 00:00:00 2001 From: Josako Date: Mon, 22 Sep 2025 16:54:39 +0200 Subject: [PATCH] - Aanpassing layout van de chat-input. Character counter is ook weg op desktop. Scrollbar enkel zichtbaar indien nodig. Meer beschikbare ruimte in mobiele client. kleinere radius in de hoeken. - Gewijzigde logica voor hoogtebepaling chat-input en message history, zodat ook de mobiele client correct functioneert. --- eveai_chat_client/static/assets/css/chat.css | 25 +++++++-- .../static/assets/vue-components/ChatApp.vue | 11 ++-- .../assets/vue-components/ChatInput.vue | 52 ++++++------------- .../assets/vue-components/MessageHistory.vue | 4 +- nginx/frontend_src/js/chat-client.js | 22 +++++++- 5 files changed, 64 insertions(+), 50 deletions(-) diff --git a/eveai_chat_client/static/assets/css/chat.css b/eveai_chat_client/static/assets/css/chat.css index 9449b6d..adf0bea 100644 --- a/eveai_chat_client/static/assets/css/chat.css +++ b/eveai_chat_client/static/assets/css/chat.css @@ -14,7 +14,8 @@ /* App container layout */ .app-container { display: flex; - height: 100vh; + height: 100vh; /* fallback */ + height: 100dvh; /* prefer dynamic viewport unit */ width: 100%; } @@ -80,9 +81,23 @@ .content-area { flex: 1; background: linear-gradient(135deg, var(--gradient-start-color), var(--gradient-end-color)); - overflow-y: auto; + overflow-y: hidden; display: flex; flex-direction: column; + min-height: 0; + height: 100vh; /* fallback for desktop */ + height: 100dvh; /* prefer dynamic viewport on desktop */ +} + +.chat-container { + display: flex; + flex-direction: column; + flex: 1; + min-height: 0; /* laat kinderen (ChatApp) krimpen */ +} + +html, body { + height: 100%; } body { @@ -273,10 +288,14 @@ body { width: 100%; } + :root { --mobile-header-height: 60px; } /* default/minimum */ + /* Content area takes remaining space */ .content-area { flex: 1; - height: calc(100vh - 60px); /* Subtract mobile header height */ + height: calc(100vh - var(--mobile-header-height)); /* fallback */ + height: calc(100dvh - var(--mobile-header-height)); /* prefer dynamic viewport */ + min-height: 0; } } diff --git a/eveai_chat_client/static/assets/vue-components/ChatApp.vue b/eveai_chat_client/static/assets/vue-components/ChatApp.vue index 7dc6619..8ab2ddf 100644 --- a/eveai_chat_client/static/assets/vue-components/ChatApp.vue +++ b/eveai_chat_client/static/assets/vue-components/ChatApp.vue @@ -553,7 +553,8 @@ export default { .chat-app-container { display: flex; flex-direction: column; - height: 100vh; + flex: 1; + /* height: 100%; avoided to let flex sizing control height */ width: 100%; min-height: 0; max-width: 1000px; @@ -561,10 +562,12 @@ export default { margin-right: auto; padding: 20px; box-sizing: border-box; + overflow: hidden; } .chat-messages-area { flex: 1; + min-height: 0; /* ensure child can scroll */ overflow: hidden; display: flex; flex-direction: column; @@ -585,10 +588,4 @@ export default { flex: 0 0 auto; } -/* Responsive adjustments */ -@media (max-width: 768px) { - .chat-app-container { - height: 100vh; - } -} \ No newline at end of file diff --git a/eveai_chat_client/static/assets/vue-components/ChatInput.vue b/eveai_chat_client/static/assets/vue-components/ChatInput.vue index 08c470e..cc55a8a 100644 --- a/eveai_chat_client/static/assets/vue-components/ChatInput.vue +++ b/eveai_chat_client/static/assets/vue-components/ChatInput.vue @@ -42,6 +42,7 @@ ref="messageInput" v-model="localMessage" @keydown="handleKeydown" + @focus="autoResize" :placeholder="translatedPlaceholder" rows="1" :disabled="isLoading" @@ -50,10 +51,6 @@ :class="{ 'over-limit': isOverLimit }" > - -
- {{ characterCount }}/{{ maxLength }} -
@@ -142,12 +139,8 @@ export default { }; }, computed: { - characterCount() { - return this.localMessage.length; - }, - isOverLimit() { - return this.characterCount > this.maxLength; + return this.localMessage.length > this.maxLength; }, hasFormData() { @@ -239,12 +232,15 @@ export default { if (this.formData) { console.log('FormData bij mount:', JSON.stringify(this.formData)); } + // Herbereken bij viewport-wijziging (bv. rotatie op mobiel) + window.addEventListener('resize', this.autoResize, { passive: true }); }, beforeUnmount() { // Verwijder event listener bij unmount met de benoemde handler if (this.languageChangeHandler) { document.removeEventListener('language-changed', this.languageChangeHandler); } + window.removeEventListener('resize', this.autoResize); }, methods: { handleLanguageChange(event) { @@ -285,6 +281,8 @@ export default { } finally { // Reset de vertaling vlag this.isTranslating = false; + // Herbereken hoogte na vertaling + this.$nextTick(this.autoResize); } }, @@ -465,9 +463,9 @@ export default { .message-input { width: 100%; min-height: 40px; - padding: 10px 60px 10px 15px; /* Meer rechter padding voor character counter */ + padding: 10px 15px 10px 15px; /* counter verwijderd -> rechter padding omlaag */ border: 1px solid #ddd; - border-radius: 20px; + border-radius: 10px; resize: none; outline: none; transition: border-color 0.2s; @@ -478,35 +476,17 @@ export default { color: var(--human-message-text-color); /* Box-sizing om padding correct te berekenen */ box-sizing: border-box; + /* Laat intern scrollen toe bij >120px, maar verberg scrollbar visueel */ + overflow: auto; + -webkit-overflow-scrolling: touch; /* soepel scrollen op iOS */ + scrollbar-width: none; /* Firefox: verberg scrollbar */ } -/* Character counter */ -.character-counter { - position: absolute; - right: 15px; - bottom: 12px; - font-size: 12px; - color: var(--human-message-text-color); - opacity: 0.7; - pointer-events: none; /* Voorkom dat deze de textarea verstoort */ +/* WebKit/Chromium: scrollbar verbergen */ +.message-input::-webkit-scrollbar { + display: none; } -/* Character counter wordt rood bij overschrijding */ -.character-counter.over-limit { - color: #ff4d4f; - font-weight: bold; -} - -/* Verberg character counter op mobile */ -@media (max-width: 768px) { - .character-counter { - display: none; - } - - .message-input { - padding-right: 15px; /* Verminder van 60px naar 15px omdat counter weg is */ - } -} /* Input actions */ .input-actions { diff --git a/eveai_chat_client/static/assets/vue-components/MessageHistory.vue b/eveai_chat_client/static/assets/vue-components/MessageHistory.vue index 1e3a19a..66b510a 100644 --- a/eveai_chat_client/static/assets/vue-components/MessageHistory.vue +++ b/eveai_chat_client/static/assets/vue-components/MessageHistory.vue @@ -331,9 +331,9 @@ export default { display: flex; flex-direction: column; flex: 1; - height: 100%; + /* height: 100%; avoid forcing parent height */ min-height: 0; /* Laat kinderen scrollen */ - padding: 20px; + padding: 16px; /* iets minder padding om ruimte te besparen */ box-sizing: border-box; width: 100%; max-width: 1000px; diff --git a/nginx/frontend_src/js/chat-client.js b/nginx/frontend_src/js/chat-client.js index 413305e..6917659 100644 --- a/nginx/frontend_src/js/chat-client.js +++ b/nginx/frontend_src/js/chat-client.js @@ -160,20 +160,38 @@ function initializeMobileHeader() { }; const mountedApp = app.mount(container); - + + // Dynamisch de headerhoogte doorgeven aan CSS + const updateHeaderHeightVar = () => { + const isMobile = window.matchMedia('(max-width: 768px)').matches; + if (!isMobile) { + document.documentElement.style.removeProperty('--mobile-header-height'); + return; + } + const h = container.offsetHeight || 60; // fallback + document.documentElement.style.setProperty('--mobile-header-height', `${h}px`); + }; + + // Initieel instellen en bij gebeurtenissen herberekenen + requestAnimationFrame(updateHeaderHeightVar); + window.addEventListener('resize', updateHeaderHeightVar); + // Listen to language change events and update the mobile header's language provider const languageChangeHandler = (event) => { if (event.detail && event.detail.language) { console.log('MobileHeader: Received language change event:', event.detail.language); languageProvider.setLanguage(event.detail.language); + // taalwissel kan headerhoogte veranderen + requestAnimationFrame(updateHeaderHeightVar); } }; document.addEventListener('language-changed', languageChangeHandler); // Store the handler for cleanup if needed mountedApp._languageChangeHandler = languageChangeHandler; + mountedApp._updateHeaderHeightVar = updateHeaderHeightVar; - console.log('✅ MobileHeader component successfully mounted with LanguageProvider'); + console.log('✅ MobileHeader component successfully mounted with LanguageProvider en dynamische headerhoogte'); return mountedApp; } catch (error) { console.error('🚨 [CRITICAL ERROR] Bij initialiseren mobile header:', error);