Alessandro commited on
Commit
2ab4e50
·
unverified ·
1 Parent(s): 6e0a082

feature: fullscreen chat input (#269)

Browse files

* feature: fullscreen chat input

* css fixes

webui/css/modals.css CHANGED
@@ -75,7 +75,7 @@
75
 
76
  /* Modal Description */
77
  .modal-description {
78
- padding: 0.8rem 2rem 0 2rem;
79
  flex-grow: 1;
80
  transition: all 0.3s ease;
81
  }
@@ -114,6 +114,96 @@
114
  background-color: rgba(155, 155, 155, 0.7);
115
  }
116
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  /* Buttons Container */
118
  #buttons-container {
119
  display: flex;
@@ -273,7 +363,6 @@ h2 {
273
  .btn {
274
  text-wrap: wrap;
275
  font-size: var(--font-size-small);
276
- padding: 0.5rem 0.85rem;
277
  }
278
 
279
  .btn-upload {
@@ -285,4 +374,4 @@ h2 {
285
  .btn-upload > svg {
286
  width: 20px;
287
  }
288
- }
 
75
 
76
  /* Modal Description */
77
  .modal-description {
78
+ padding: 0.8rem 1rem 0 1rem;
79
  flex-grow: 1;
80
  transition: all 0.3s ease;
81
  }
 
114
  background-color: rgba(155, 155, 155, 0.7);
115
  }
116
 
117
+ /* Full Screen Input Modal Styles */
118
+ .full-screen-input-modal {
119
+ width: 90%;
120
+ max-width: 800px;
121
+ max-height: 80vh;
122
+ position: relative;
123
+ padding: 0;
124
+ background-color: rgb(20, 20, 20, 0.96);
125
+ border: 1.5px solid var(--color-border);
126
+ }
127
+
128
+ .full-screen-input-modal h2 {
129
+ margin: 0;
130
+ padding: 0;
131
+ font-size: 1.1rem;
132
+ color: var(--color-text);
133
+ opacity: 0.8;
134
+ }
135
+
136
+ .full-screen-input-modal .modal-close {
137
+ position: absolute;
138
+ top: 1rem;
139
+ right: 1rem;
140
+ font-size: 1.5rem;
141
+ padding: 0 0.5rem;
142
+ line-height: 0.8;
143
+ }
144
+
145
+ .full-screen-input-modal .btn-ok {
146
+ margin-right: 1rem;
147
+ }
148
+
149
+ .full-screen-input-modal .modal-content {
150
+ height: calc(80vh);
151
+ padding: 0;
152
+ margin: 0;
153
+ overflow: hidden;
154
+ }
155
+
156
+ .full-screen-input-modal .modal-footer {
157
+ background: transparent;
158
+ max-height: 50px;
159
+ }
160
+
161
+ #full-screen-input {
162
+ width: 100%;
163
+ height: 100%;
164
+ border: none;
165
+ background-color: transparent;
166
+ color: var(--color-text);
167
+ font-family: 'Roboto Mono', monospace;
168
+ font-optical-sizing: auto;
169
+ font-size: 0.955rem;
170
+ padding: 1.2rem 1rem;
171
+ resize: none;
172
+ outline: none;
173
+ }
174
+
175
+ #full-screen-input::-webkit-scrollbar {
176
+ width: 6px;
177
+ height: 6px;
178
+ }
179
+
180
+ #full-screen-input::-webkit-scrollbar-track {
181
+ background: transparent;
182
+ margin: 14px;
183
+ border-radius: 6px;
184
+ }
185
+
186
+ #full-screen-input::-webkit-scrollbar-thumb {
187
+ background-color: rgba(155, 155, 155, 0.5);
188
+ border-radius: 6px;
189
+ -webkit-transition: background-color 0.2s ease;
190
+ transition: background-color 0.2s ease;
191
+ }
192
+
193
+ #full-screen-input::-webkit-scrollbar-thumb:hover {
194
+ background-color: rgba(155, 155, 155, 0.7);
195
+ }
196
+
197
+ .light-mode .full-screen-input-modal {
198
+ background-color: rgb(220, 220, 220, 0.86);
199
+ }
200
+
201
+ .full-screen-input-modal .modal-footer {
202
+ padding: 1rem 0;
203
+ border-top: none;
204
+ background: transparent;
205
+ }
206
+
207
  /* Buttons Container */
208
  #buttons-container {
209
  display: flex;
 
363
  .btn {
364
  text-wrap: wrap;
365
  font-size: var(--font-size-small);
 
366
  }
367
 
368
  .btn-upload {
 
374
  .btn-upload > svg {
375
  width: 20px;
376
  }
377
+ }
webui/css/settings.css CHANGED
@@ -214,13 +214,13 @@ nav ul li a img {
214
  }
215
  }
216
 
217
- @media (max-width: 480px) {
218
  nav ul {
219
  grid-template-columns: repeat(2, 1.2fr);
220
  }
221
  }
222
 
223
- @media (max-width: 380px) {
224
  nav ul {
225
  grid-template-columns: 1fr;
226
  }
 
214
  }
215
  }
216
 
217
+ @media (max-width: 640px) {
218
  nav ul {
219
  grid-template-columns: repeat(2, 1.2fr);
220
  }
221
  }
222
 
223
+ @media (max-width: 480px) {
224
  nav ul {
225
  grid-template-columns: 1fr;
226
  }
webui/index.css CHANGED
@@ -7,30 +7,30 @@
7
 
8
  :root {
9
  /* Dark mode */
10
- --color-background-dark: #171717;
11
- --color-text-dark: #e0e0e0;
12
- --color-primary-dark: #86929d;
13
- --color-secondary-dark: #3f3f3f;
14
  --color-accent-dark: #cf6679;
15
  --color-message-bg-dark: #2d2d2d;
16
  --color-message-text-dark: #e0e0e0;
17
- --color-panel-dark: #1e1e1e;
18
  --color-border-dark: #444444a8;
19
- --color-input-dark: #222;
20
- --color-input-focus-dark: #1b1b1b;
21
 
22
  /* Light mode */
23
- --color-background-light: #e8e9e9;
24
  --color-text-light: #333333;
25
- --color-primary-light: #324d66;
26
  --color-secondary-light: #e8eaf6;
27
  --color-accent-light: #b00020;
28
  --color-message-bg-light: #ffffff;
29
  --color-message-text-light: #333333;
30
- --color-panel-light: #ffffff;
31
  --color-border-light: #e0e0e0c7;
32
- --color-input-light: #f1f1f1;
33
- --color-input-focus-light: #ebeced;
34
 
35
  /* Default to dark mode */
36
  --color-background: var(--color-background-dark);
@@ -752,6 +752,11 @@ pre {
752
  }
753
 
754
  /* Text input */
 
 
 
 
 
755
  #chat-input {
756
  background-color: var(--color-input);
757
  border: 1px solid var(--color-border);
@@ -763,8 +768,10 @@ pre {
763
  -webkit-font-optical-sizing: auto;
764
  font-size: 0.875rem;
765
  max-height: 7rem;
766
- min-height: 2.8rem;
767
- padding: 0.65rem var(--spacing-sm) var(--spacing-sm) var(--spacing-sm);
 
 
768
  overflow-y: auto;
769
  scroll-behavior: smooth;
770
  resize: none;
@@ -775,6 +782,36 @@ pre {
775
  -webkit-transition: all 0.3s ease;
776
  }
777
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
778
  #chat-input::-webkit-scrollbar {
779
  width: 6px;
780
  height: 6px;
@@ -798,9 +835,9 @@ pre {
798
  }
799
 
800
  #chat-input:focus {
801
- outline: 0.05rem solid rgba(155, 155, 155, 0.3);
802
  font-size: 0.955rem;
803
- padding-top: 0.58rem;
804
  background-color: var(--color-input-focus);
805
  }
806
 
@@ -1011,6 +1048,7 @@ pre {
1011
  gap: 8px;
1012
  margin-bottom: 10px;
1013
  padding: var(--spacing-xs);
 
1014
  }
1015
 
1016
  .preview-item {
@@ -1098,18 +1136,6 @@ pre {
1098
  }
1099
 
1100
  /* Text input */
1101
- #chat-input {
1102
- flex-grow: 1;
1103
- min-height: 2.7rem;
1104
- padding: var(--spacing-sm) var(--spacing-sm);
1105
- padding-top: 0.65rem;
1106
- margin-right: var(--spacing-xs);
1107
- border: 1px solid var(--color-border);
1108
- border-radius: 8px;
1109
- resize: none;
1110
- align-content: start;
1111
- }
1112
-
1113
  .input-row {
1114
  width: 100%;
1115
  white-space: nowrap;
@@ -1164,6 +1190,7 @@ pre {
1164
 
1165
  #chat-buttons-wrapper {
1166
  gap: var(--spacing-xs);
 
1167
  }
1168
 
1169
  .chat-button {
@@ -1245,7 +1272,10 @@ pre {
1245
  .preview-item {
1246
  position: relative;
1247
  flex-shrink: 0;
 
1248
  animation: fadeIn 0.3s ease;
 
 
1249
  }
1250
 
1251
  .preview-item img {
@@ -1778,57 +1808,57 @@ input:checked + .slider:before {
1778
  }
1779
 
1780
  .light-mode .message-default {
1781
- background-color: #ffffff;
1782
  color: #1a242f;
1783
  }
1784
 
1785
  .light-mode .message-agent {
1786
- background-color: #ffffff;
1787
  color: #356ca3;
1788
  }
1789
 
1790
  .light-mode .message-agent-response {
1791
- background-color: #ffffff;
1792
  color: #188216;
1793
  }
1794
 
1795
  .light-mode .message-agent-delegation {
1796
- background-color: #ffffff;
1797
  color: #12685e;
1798
  }
1799
 
1800
  .light-mode .message-tool {
1801
- background-color: #ffffff;
1802
  color: #1c3c88;
1803
  }
1804
 
1805
  .light-mode .message-code-exe {
1806
- background-color: #ffffff;
1807
  color: #6c43b0;
1808
  }
1809
 
1810
  .light-mode .message-info {
1811
- background-color: #ffffff;
1812
  color: #3f3f3f;
1813
  }
1814
 
1815
  .light-mode .message-util {
1816
- background-color: #ffffff;
1817
  color: #5b5540;
1818
  }
1819
 
1820
  .light-mode .message-warning {
1821
- background-color: #ffffff;
1822
  color: #8f4800;
1823
  }
1824
 
1825
  .light-mode .message-error {
1826
- background-color: #ffffff;
1827
  color: #8f1010;
1828
  }
1829
 
1830
  .light-mode .message-user {
1831
- background-color: #ffffff;
1832
  color: #4e4e4e;
1833
  }
1834
 
@@ -1950,4 +1980,4 @@ input:checked + .slider:before {
1950
  100% {
1951
  transform: scale(1);
1952
  }
1953
- }
 
7
 
8
  :root {
9
  /* Dark mode */
10
+ --color-background-dark: #131313;
11
+ --color-text-dark: #d4d4d4;
12
+ --color-primary-dark: #737a81;
13
+ --color-secondary-dark: #656565;
14
  --color-accent-dark: #cf6679;
15
  --color-message-bg-dark: #2d2d2d;
16
  --color-message-text-dark: #e0e0e0;
17
+ --color-panel-dark: #171717;
18
  --color-border-dark: #444444a8;
19
+ --color-input-dark: #131313;
20
+ --color-input-focus-dark: #101010;
21
 
22
  /* Light mode */
23
+ --color-background-light: #dbdbdb;
24
  --color-text-light: #333333;
25
+ --color-primary-light: #384653;
26
  --color-secondary-light: #e8eaf6;
27
  --color-accent-light: #b00020;
28
  --color-message-bg-light: #ffffff;
29
  --color-message-text-light: #333333;
30
+ --color-panel-light: #f0f0f0;
31
  --color-border-light: #e0e0e0c7;
32
+ --color-input-light: #e4e4e4;
33
+ --color-input-focus-light: #dadada;
34
 
35
  /* Default to dark mode */
36
  --color-background: var(--color-background-dark);
 
752
  }
753
 
754
  /* Text input */
755
+ #chat-input-container {
756
+ position: relative;
757
+ width: 100%;
758
+ }
759
+
760
  #chat-input {
761
  background-color: var(--color-input);
762
  border: 1px solid var(--color-border);
 
768
  -webkit-font-optical-sizing: auto;
769
  font-size: 0.875rem;
770
  max-height: 7rem;
771
+ min-height: 3rem;
772
+ width: 100%;
773
+ padding: 0.5rem 40px var(--spacing-sm) var(--spacing-sm);
774
+ margin-right: var(--spacing-xs);
775
  overflow-y: auto;
776
  scroll-behavior: smooth;
777
  resize: none;
 
782
  -webkit-transition: all 0.3s ease;
783
  }
784
 
785
+ #chat-input {
786
+ outline: 1px solid var(--color-border);
787
+ }
788
+
789
+ #expand-button {
790
+ position: absolute;
791
+ top: 12px;
792
+ right: 10px;
793
+ background: transparent;
794
+ border: none;
795
+ cursor: pointer;
796
+ font-size: 1.2rem;
797
+ color: var(--color-text);
798
+ opacity: 0.4;
799
+ transition: opacity 0.2s;
800
+ }
801
+
802
+ #expand-button:hover {
803
+ opacity: 0.7;
804
+ }
805
+
806
+ #expand-button:active {
807
+ opacity: 1;
808
+ }
809
+
810
+ #expand-button svg {
811
+ width: 1.3rem;
812
+ height: 1.3rem;
813
+ }
814
+
815
  #chat-input::-webkit-scrollbar {
816
  width: 6px;
817
  height: 6px;
 
835
  }
836
 
837
  #chat-input:focus {
838
+ outline: 0.05rem solid rgba(155, 155, 155, 0.5);
839
  font-size: 0.955rem;
840
+ padding-top: 0.5rem;
841
  background-color: var(--color-input-focus);
842
  }
843
 
 
1048
  gap: 8px;
1049
  margin-bottom: 10px;
1050
  padding: var(--spacing-xs);
1051
+ background-color: var(--color-border);
1052
  }
1053
 
1054
  .preview-item {
 
1136
  }
1137
 
1138
  /* Text input */
 
 
 
 
 
 
 
 
 
 
 
 
1139
  .input-row {
1140
  width: 100%;
1141
  white-space: nowrap;
 
1190
 
1191
  #chat-buttons-wrapper {
1192
  gap: var(--spacing-xs);
1193
+ padding-left: var(--spacing-xs);
1194
  }
1195
 
1196
  .chat-button {
 
1272
  .preview-item {
1273
  position: relative;
1274
  flex-shrink: 0;
1275
+ padding: 4px;
1276
  animation: fadeIn 0.3s ease;
1277
+ min-width: min-content;
1278
+ background-color: var(--color-background);
1279
  }
1280
 
1281
  .preview-item img {
 
1808
  }
1809
 
1810
  .light-mode .message-default {
1811
+ background-color: #f3f3f3;
1812
  color: #1a242f;
1813
  }
1814
 
1815
  .light-mode .message-agent {
1816
+ background-color: #f3f3f3;
1817
  color: #356ca3;
1818
  }
1819
 
1820
  .light-mode .message-agent-response {
1821
+ background-color: #f3f3f3;
1822
  color: #188216;
1823
  }
1824
 
1825
  .light-mode .message-agent-delegation {
1826
+ background-color: #f3f3f3;
1827
  color: #12685e;
1828
  }
1829
 
1830
  .light-mode .message-tool {
1831
+ background-color: #f3f3f3;
1832
  color: #1c3c88;
1833
  }
1834
 
1835
  .light-mode .message-code-exe {
1836
+ background-color: #f3f3f3;
1837
  color: #6c43b0;
1838
  }
1839
 
1840
  .light-mode .message-info {
1841
+ background-color: #f3f3f3;
1842
  color: #3f3f3f;
1843
  }
1844
 
1845
  .light-mode .message-util {
1846
+ background-color: #f3f3f3;
1847
  color: #5b5540;
1848
  }
1849
 
1850
  .light-mode .message-warning {
1851
+ background-color: #f3f3f3;
1852
  color: #8f4800;
1853
  }
1854
 
1855
  .light-mode .message-error {
1856
+ background-color: #f3f3f3;
1857
  color: #8f1010;
1858
  }
1859
 
1860
  .light-mode .message-user {
1861
+ background-color: #f3f3f3;
1862
  color: #4e4e4e;
1863
  }
1864
 
 
1980
  100% {
1981
  transform: scale(1);
1982
  }
1983
+ }
webui/index.html CHANGED
@@ -304,10 +304,20 @@
304
  </div>
305
  </div>
306
 
307
- <!-- Text input -->
308
- <textarea id="chat-input" placeholder="Type your message here..." rows="1"></textarea>
309
-
 
 
 
 
 
 
 
 
 
310
  <div id="chat-buttons-wrapper">
 
311
  <!-- Send button -->
312
  <button class="chat-button" id="send-button" aria-label="Send message">
313
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
@@ -682,6 +692,28 @@
682
  </template>
683
  </div>
684
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
685
  </body>
686
 
687
  </html>
 
304
  </div>
305
  </div>
306
 
307
+ <!-- Container for textarea and button -->
308
+ <div id="chat-input-container" style="position: relative;">
309
+ <textarea id="chat-input" placeholder="Type your message here..." rows="1"></textarea>
310
+
311
+ <!-- Expand button inside the textarea container -->
312
+ <button id="expand-button" @click="$store.fullScreenInputModal.openModal()" aria-label="Expand input">
313
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
314
+ <path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/>
315
+ </svg>
316
+ </button>
317
+ </div>
318
+
319
  <div id="chat-buttons-wrapper">
320
+
321
  <!-- Send button -->
322
  <button class="chat-button" id="send-button" aria-label="Send message">
323
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
 
692
  </template>
693
  </div>
694
 
695
+ <!-- Full Screen Input Modal -->
696
+ <div id="fullScreenInputModal" x-data="fullScreenInputModalProxy">
697
+ <template x-teleport="body">
698
+ <div x-show="isOpen" class="modal-overlay" @click.self="handleClose()"
699
+ @keydown.escape.window="handleClose()" x-transition>
700
+ <div class="modal-container full-screen-input-modal">
701
+ <div class="modal-content">
702
+ <button class="modal-close" @click="handleClose()">&times;</button>
703
+ <textarea id="full-screen-input" x-model="inputText"
704
+ placeholder="Type your message here..."
705
+ @keydown.ctrl.enter="handleClose()"></textarea>
706
+ </div>
707
+ <div class="modal-footer">
708
+ <div id="buttons-container">
709
+ <button class="btn btn-ok" @click="handleClose()">Done (Ctrl+Enter)</button>
710
+ </div>
711
+ </div>
712
+ </div>
713
+ </div>
714
+ </template>
715
+ </div>
716
+
717
  </body>
718
 
719
  </html>
webui/js/modal.js CHANGED
@@ -1,3 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  const genericModalProxy = {
2
  isOpen: false,
3
  isLoading: false,
 
1
+ const fullScreenInputModalProxy = {
2
+ isOpen: false,
3
+ inputText: '',
4
+
5
+ openModal() {
6
+ const chatInput = document.getElementById('chat-input');
7
+ this.inputText = chatInput.value;
8
+ this.isOpen = true;
9
+
10
+ // Focus the full screen input after a short delay to ensure the modal is rendered
11
+ setTimeout(() => {
12
+ const fullScreenInput = document.getElementById('full-screen-input');
13
+ fullScreenInput.focus();
14
+ }, 100);
15
+ },
16
+
17
+ handleClose() {
18
+ const chatInput = document.getElementById('chat-input');
19
+ chatInput.value = this.inputText;
20
+ chatInput.dispatchEvent(new Event('input')); // Trigger input event for textarea auto-resize
21
+ this.isOpen = false;
22
+ }
23
+ };
24
+
25
+ // Register the full screen input modal with Alpine as a store
26
+ document.addEventListener('alpine:init', () => {
27
+ Alpine.store('fullScreenInputModal', fullScreenInputModalProxy);
28
+ });
29
+
30
+ // Also register as a component for x-data usage
31
+ document.addEventListener('alpine:init', () => {
32
+ Alpine.data('fullScreenInputModalProxy', () => fullScreenInputModalProxy);
33
+ });
34
+
35
  const genericModalProxy = {
36
  isOpen: false,
37
  isLoading: false,