fix: chat list fit-content/grow
- unwrapped chat/tasks list from removed lists-wrapper div - made chat/tasks list scrollable while mantaining the title sticky - when you are at the bottom of the chat list and you create a new chat, the list now scroll up to top thx to the new scrollChatsToTop helper
Alessandro committed
Oct 13, 2025 at 03:54 UTC
184fbd1538e6f9e11a284ba45e5b14f8c7007077
4 files changed
+132
-144
webui/components/sidebar/chats/chats-list.html
+57
-62
@@ -28,67 +28,62 @@
28
</template>
29
</div>
30
31
+ <style>
32
+ .chats-list-container .section-header {
33
+ position: sticky;
34
+ top: 0;
35
+ flex-shrink: 0;
36
+ z-index: 10;
37
+ }
38
+ /* Chats list container and items */
39
+ .chats-list-container {
40
+ display: flex;
41
+ flex-direction: column;
42
+ flex: 1;
43
+ min-height: 0;
44
+ margin-top: var(--spacing-md);
45
+ }
46
+
47
+ .chats-config-list {
48
+ flex: 1;
49
+ min-height: 0;
50
+ overflow: scroll;
51
+ scroll-behavior: smooth;
52
+ max-height: 100%;
53
+ scrollbar-width: none; /* Firefox */
54
+ -ms-overflow-style: none; /* IE/Edge */
55
+ }
56
+ /* Hide scrollbar for Chrome/Safari/Webkit */
57
+ .chats-config-list::-webkit-scrollbar {
58
+ display: none;
59
+ }
60
+
61
+ .chat-list-button { display: block; width: 100%; padding: 8px 5px; cursor: pointer; overflow: hidden; position: relative; border-radius: 4px; transition: background-color 0.2s ease-in-out; }
62
+ .chat-list-button.has-task-container { padding-top: 6px; padding-bottom: 6px; }
63
+ .chat-list-button:hover { background-color: rgba(255, 255, 255, 0.03); }
64
+ .light-mode .chat-list-button:hover { background-color: rgba(0, 0, 0, 0.02); }
65
+
66
+ .chat-name { display: inline-block; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; padding: 3px 8px; border-radius: 4px; transition: background-color 0.2s; margin-right: 60px; font-size: var(--font-size-small); }
67
+ .chat-name:hover { background-color: rgba(255, 255, 255, 0.1); text-decoration: none; }
68
+ .light-mode .chat-name:hover { background-color: rgba(0, 0, 0, 0.05); }
69
+
70
+ .chat-container { display: flex; align-items: center; position: relative; width: 100%; min-height: 30px; gap: 0; }
71
+
72
+ .edit-button { background-color: transparent; border: 1px solid var(--color-border); border-radius: 0.1875rem; color: var(--color-primary); cursor: pointer; padding: 0.125rem 0.5rem; -webkit-transition: all var(--transition-speed) ease-in-out; transition: all var(--transition-speed) ease-in-out; width: 2rem; height: 2rem; }
73
+ .edit-button:hover { border-color: var(--color-primary); background-color: #32455690; }
74
+ .edit-button:active { background-color: #131a2090; color: rgba(253, 253, 253, 0.35); }
75
+ .light-mode .edit-button { border-color: var(--color-primary-light); color: var(--color-primary-light); }
76
+ .light-mode .edit-button:hover { background-color: #e4e7f0; }
77
+ .light-mode .edit-button:active { background-color: #979fb9; color: rgba(0,0,0,0.35); }
78
+
79
+ .empty-list-message { display: flex; justify-content: center; align-items: center; height: 100px; color: var(--color-secondary); text-align: center; opacity: 0.7; font-style: italic; }
80
+ .light-mode .empty-list-message { color: var(--color-secondary-light); }
81
+
82
+ /* Selected chat accent */
83
+ .chat-list-button.font-bold { position: relative; background-color: var(--color-border) 0.05; }
84
+ .chat-list-button.font-bold::before { content: ""; position: absolute; left: 0; top: 0; height: 100%; width: 3px; background-color: var(--color-border); border-top-left-radius: 3px; border-bottom-left-radius: 3px; }
85
+ .light-mode .chat-list-button.font-bold { background-color: var(--color-border) 0.05; }
86
+ .light-mode .chat-list-button.font-bold::before { background-color: var(--color-border); }
87
+ </style>
88
</body>
89
</html>
33
-
34
-<style>
35
- /* Chats list container and items */
36
- .chats-list-container {
37
- display: flex;
38
- flex-direction: column;
39
- flex: 1;
40
- min-height: 0;
41
- overflow: hidden;
42
- }
43
-
44
- /* Sticky header for chats list */
45
- .chats-list-container .section-header {
46
- flex-shrink: 0;
47
- z-index: 10;
48
- }
49
-
50
- /* Scrollable config list */
51
- .chats-config-list {
52
- flex: 1;
53
- min-height: 0;
54
- overflow-y: auto;
55
- scroll-behavior: smooth;
56
- max-height: 23vh;
57
- /* Hide scrollbar but keep functionality */
58
- scrollbar-width: none; /* Firefox */
59
- -ms-overflow-style: none; /* IE/Edge */
60
- }
61
- /* Hide scrollbar for Chrome/Safari/Webkit */
62
- .chats-config-list::-webkit-scrollbar {
63
- display: none;
64
- }
65
-
66
- .chat-list-button { display: block; width: 100%; padding: 8px 5px; cursor: pointer; overflow: hidden; position: relative; border-radius: 4px; transition: background-color 0.2s ease-in-out; }
67
- .chat-list-button.has-task-container { padding-top: 6px; padding-bottom: 6px; }
68
- .chat-list-button:hover { background-color: rgba(255, 255, 255, 0.03); }
69
- .light-mode .chat-list-button:hover { background-color: rgba(0, 0, 0, 0.02); }
70
-
71
- .chat-name { display: inline-block; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; padding: 3px 8px; border-radius: 4px; transition: background-color 0.2s; margin-right: 60px; font-size: var(--font-size-small); }
72
- .chat-name:hover { background-color: rgba(255, 255, 255, 0.1); text-decoration: none; }
73
- .light-mode .chat-name:hover { background-color: rgba(0, 0, 0, 0.05); }
74
-
75
- .chat-container { display: flex; align-items: center; position: relative; width: 100%; min-height: 30px; gap: 0; }
76
-
77
- .edit-button { background-color: transparent; border: 1px solid var(--color-border); border-radius: 0.1875rem; color: var(--color-primary); cursor: pointer; padding: 0.125rem 0.5rem; -webkit-transition: all var(--transition-speed) ease-in-out; transition: all var(--transition-speed) ease-in-out; width: 2rem; height: 2rem; }
78
- .edit-button:hover { border-color: var(--color-primary); background-color: #32455690; }
79
- .edit-button:active { background-color: #131a2090; color: rgba(253, 253, 253, 0.35); }
80
- .light-mode .edit-button { border-color: var(--color-primary-light); color: var(--color-primary-light); }
81
- .light-mode .edit-button:hover { background-color: #e4e7f0; }
82
- .light-mode .edit-button:active { background-color: #979fb9; color: rgba(0,0,0,0.35); }
83
-
84
- .empty-list-message { display: flex; justify-content: center; align-items: center; height: 100px; color: var(--color-secondary); text-align: center; opacity: 0.7; font-style: italic; }
85
- .light-mode .empty-list-message { color: var(--color-secondary-light); }
86
-
87
- /* Selected chat accent */
88
- .chat-list-button.font-bold { position: relative; background-color: var(--color-border) 0.05; }
89
- .chat-list-button.font-bold::before { content: ""; position: absolute; left: 0; top: 0; height: 100%; width: 3px; background-color: var(--color-border); border-top-left-radius: 3px; border-bottom-left-radius: 3px; }
90
- .light-mode .chat-list-button.font-bold { background-color: var(--color-border) 0.05; }
91
- .light-mode .chat-list-button.font-bold::before { background-color: var(--color-border); }
92
-</style>
93
-
94
-
webui/components/sidebar/chats/chats-store.js
+9
@@ -139,6 +139,8 @@ const model = {
139
if (globalThis.updateAfterScroll) {
140
globalThis.updateAfterScroll();
141
}
142
+ // UX: scroll-to-top
143
+ requestAnimationFrame(() => this._scrollChatsToTop());
144
} catch (e) {
145
if (globalThis.toastFetchError) {
146
globalThis.toastFetchError("Error creating new chat", e);
@@ -146,6 +148,13 @@ const model = {
148
}
149
},
150
151
+ // Smoothly scroll the chats list to top if present
152
+ _scrollChatsToTop() {
153
+ const listEl = document.querySelector('#chats-section .chats-config-list');
154
+ if (!listEl) return; // no-op if not in DOM
155
+ listEl.scrollTo({ top: 0, behavior: 'smooth' });
156
+ },
157
+
158
// Load chats from files
159
async loadChats() {
160
try {
webui/components/sidebar/left-sidebar.html
+13
-24
@@ -11,18 +11,14 @@
11
<div class="left-panel-top">
12
<!-- Top Section: Header Icons + Quick Actions -->
13
<x-component path="sidebar/top-section/sidebar-top.html"></x-component>
14
+ <!-- Chats List -->
15
+ <div class="config-section" id="chats-section">
16
+ <x-component path="sidebar/chats/chats-list.html"></x-component>
17
+ </div>
18
15
- <!-- Chats and Tasks Wrapper -->
16
- <div class="lists-wrapper">
17
- <!-- Chats List -->
18
- <div class="config-section" id="chats-section">
19
- <x-component path="sidebar/chats/chats-list.html"></x-component>
20
- </div>
21
-
22
- <!-- Tasks List -->
23
- <div class="config-section" id="tasks-section">
24
- <x-component path="sidebar/tasks/tasks-list.html"></x-component>
25
- </div>
19
+ <!-- Tasks List -->
20
+ <div class="config-section" id="tasks-section">
21
+ <x-component path="sidebar/tasks/tasks-list.html"></x-component>
22
</div>
23
</div>
24
<!--Sidebar lower elements-->
@@ -31,7 +27,6 @@
27
</div>
28
</div>
29
34
-
30
<style>
31
/* Left Panel styles from index.css */
32
#left-panel {
@@ -75,15 +70,6 @@
70
margin-top: 3.5rem;
71
padding: var(--spacing-md) var(--spacing-md) 0 var(--spacing-md);
72
}
78
-
79
- /* Wrapper for Chats and Tasks lists */
80
- .lists-wrapper {
81
- display: flex;
82
- flex-direction: column;
83
- flex: 1;
84
- min-height: 0;
85
- overflow: hidden;
86
- }
73
.left-panel-top::-webkit-scrollbar {
74
width: 0px;
75
}
@@ -105,10 +91,15 @@
91
display: flex;
92
flex-direction: column;
93
min-height: 0;
108
- flex: 0 auto;
94
+ flex: 1 1 auto; /* Allow to grow and fill available space */
95
margin-top: var(--spacing-md);
96
overflow: hidden;
97
}
98
+ /* Flatten wrapper elements to maintain flex chain for inner scroll containers */
99
+ #chats-section, #tasks-section > x-component,
100
+ #chats-section, #tasks-section > x-component > div[x-data] {
101
+ display: contents;
102
+ }
103
/* Tasks section container inside sidebar */
104
#tasks-section {
105
display: -webkit-flex;
@@ -173,5 +164,3 @@
164
</style>
165
</body>
166
</html>
176
-
177
-
webui/components/sidebar/tasks/tasks-list.html
+53
-58
@@ -59,63 +59,58 @@
59
</template>
60
</div>
61
62
+ <style>
63
+ .tasks-list-container .section-header {
64
+ position: sticky;
65
+ top: 0;
66
+ flex-shrink: 0;
67
+ z-index: 10;
68
+ }
69
+
70
+ .tasks-list-container {
71
+ display: flex;
72
+ flex-direction: column;
73
+ max-height: 100%;
74
+ overflow: hidden;
75
+ position: relative;
76
+ }
77
+
78
+ /* Scrollable tasks config list */
79
+ .tasks-config-list {
80
+ flex: 1;
81
+ min-height: 0;
82
+ overflow-y: auto;
83
+ scroll-behavior: smooth;
84
+ scrollbar-width: none; /* Firefox */
85
+ -ms-overflow-style: none; /* IE/Edge */
86
+ }
87
+ /* Hide scrollbar for Chrome/Safari/Webkit */
88
+ .tasks-config-list::-webkit-scrollbar {
89
+ display: none;
90
+ }
91
+
92
+ .task-name { display: block; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 3px 0; margin-left: 10px; cursor: pointer; border-radius: 4px; transition: background-color 0.2s; font-size: var(--font-size-small); margin-bottom: 2px; }
93
+ .task-name:hover { background-color: rgba(255,255,255,0.1); text-decoration: none; }
94
+ .light-mode .task-name:hover { background-color: rgba(0,0,0,0.05); }
95
+
96
+ .task-info-line { display: flex; justify-content: space-between; align-items: center; width: 100%; margin-top: 2px; margin-left: 5px; }
97
+
98
+ .task-container-vertical { display: flex; flex-direction: column; width: 100%; gap: 6px; }
99
+
100
+ /* Scheduler badges (subset used in sidebar) */
101
+ .scheduler-status-badge { display: inline-block; padding: 4px 8px; border-radius: 4px; font-size: 12px; font-weight: 500; text-transform: capitalize; white-space: nowrap; }
102
+ .scheduler-status-badge-small { font-size: 10px; padding: 2px 6px; margin-right: 5px; min-width: 40px; text-align: center; }
103
+ .scheduler-status-idle { background-color: rgba(0, 100, 0, 0.2); color: #2a9d8f; border: 1px solid rgba(42, 157, 143, 0.3); }
104
+ .scheduler-status-running { background-color: rgba(0, 60, 120, 0.2); color: #4361ee; border: 1px solid rgba(67, 97, 238, 0.3); }
105
+ .scheduler-status-disabled { background-color: rgba(70, 70, 70, 0.2); color: #6c757d; border: 1px solid rgba(108, 117, 125, 0.3); }
106
+ .scheduler-status-error { background-color: rgba(120, 0, 0, 0.2); color: #e63946; border: 1px solid rgba(230, 57, 70, 0.3); }
107
+ .light-mode .scheduler-status-idle { background-color: rgba(42, 157, 143, 0.1); color: #1a6f65; }
108
+ .light-mode .scheduler-status-running { background-color: rgba(67, 97, 238, 0.1); color: #2540b3; }
109
+ .light-mode .scheduler-status-disabled { background-color: rgba(108, 117, 125, 0.1); color: #495057; }
110
+ .light-mode .scheduler-status-error { background-color: rgba(230, 57, 70, 0.1); color: #c5283d; }
111
+
112
+ .empty-list-message { display: flex; justify-content: center; align-items: center; height: 100px; color: var(--color-secondary); text-align: center; opacity: 0.7; font-style: italic; }
113
+ .light-mode .empty-list-message { color: var(--color-secondary-light); }
114
+ </style>
115
</body>
116
</html>
64
-
65
-<style>
66
- /* Tasks list styling (migrated) */
67
- .tasks-list-container {
68
- display: flex;
69
- flex-direction: column;
70
- max-height: 30vh;
71
- overflow: hidden;
72
- position: relative;
73
- }
74
-
75
- /* Scrollable tasks config list */
76
- .tasks-config-list {
77
- flex: 1;
78
- min-height: 0;
79
- overflow-y: auto;
80
- scroll-behavior: smooth;
81
- max-height: 23vh;
82
- /* Hide scrollbar but keep functionality */
83
- scrollbar-width: none; /* Firefox */
84
- -ms-overflow-style: none; /* IE/Edge */
85
- }
86
- /* Hide scrollbar for Chrome/Safari/Webkit */
87
- .tasks-config-list::-webkit-scrollbar {
88
- display: none;
89
- }
90
-
91
-
92
- .tasks-list-container .section-header {
93
- flex-shrink: 0;
94
- z-index: 10;
95
- }
96
-
97
- .task-name { display: block; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 3px 0; margin-left: 10px; cursor: pointer; border-radius: 4px; transition: background-color 0.2s; font-size: var(--font-size-small); margin-bottom: 2px; }
98
- .task-name:hover { background-color: rgba(255,255,255,0.1); text-decoration: none; }
99
- .light-mode .task-name:hover { background-color: rgba(0,0,0,0.05); }
100
-
101
- .task-info-line { display: flex; justify-content: space-between; align-items: center; width: 100%; margin-top: 2px; margin-left: 5px; }
102
-
103
- .task-container-vertical { display: flex; flex-direction: column; width: 100%; gap: 6px; }
104
-
105
- /* Scheduler badges (subset used in sidebar) */
106
- .scheduler-status-badge { display: inline-block; padding: 4px 8px; border-radius: 4px; font-size: 12px; font-weight: 500; text-transform: capitalize; white-space: nowrap; }
107
- .scheduler-status-badge-small { font-size: 10px; padding: 2px 6px; margin-right: 5px; min-width: 40px; text-align: center; }
108
- .scheduler-status-idle { background-color: rgba(0, 100, 0, 0.2); color: #2a9d8f; border: 1px solid rgba(42, 157, 143, 0.3); }
109
- .scheduler-status-running { background-color: rgba(0, 60, 120, 0.2); color: #4361ee; border: 1px solid rgba(67, 97, 238, 0.3); }
110
- .scheduler-status-disabled { background-color: rgba(70, 70, 70, 0.2); color: #6c757d; border: 1px solid rgba(108, 117, 125, 0.3); }
111
- .scheduler-status-error { background-color: rgba(120, 0, 0, 0.2); color: #e63946; border: 1px solid rgba(230, 57, 70, 0.3); }
112
- .light-mode .scheduler-status-idle { background-color: rgba(42, 157, 143, 0.1); color: #1a6f65; }
113
- .light-mode .scheduler-status-running { background-color: rgba(67, 97, 238, 0.1); color: #2540b3; }
114
- .light-mode .scheduler-status-disabled { background-color: rgba(108, 117, 125, 0.1); color: #495057; }
115
- .light-mode .scheduler-status-error { background-color: rgba(230, 57, 70, 0.1); color: #c5283d; }
116
-
117
- .empty-list-message { display: flex; justify-content: center; align-items: center; height: 100px; color: var(--color-secondary); text-align: center; opacity: 0.7; font-style: italic; }
118
- .light-mode .empty-list-message { color: var(--color-secondary-light); }
119
-</style>
120
-
121
-