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 - scrollable chats and tasks fix
Alessandro committed
Oct 13, 2025 at 03:54 UTC
d78080bf2455e05f71ec8a4d5a7ffc870e0f07a2
4 files changed
+209
-196
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
+38
-37
@@ -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 {
@@ -47,6 +42,9 @@
42
color: var(--color-text);
43
box-shadow: 1px 0 5px rgba(0, 0, 0, 0.3);
44
user-select: none;
45
+ -webkit-user-select: none; /* Safari compatibility */
46
+ height: 100vh; /* Ensure full height */
47
+ overflow: hidden; /* Prevent overall panel overflow */
48
}
49
50
/* Ensure component host behaves like the original direct children for flex layout */
@@ -66,61 +64,65 @@
64
}
65
66
.left-panel-top {
69
- flex: 1;
67
+ flex: 1 1 auto; /* Take available space */
68
display: -webkit-flex;
69
display: flex;
70
flex-direction: column;
73
- min-height: 0;
71
+ min-height: 0; /* Critical for allowing flex children to shrink */
72
overflow: hidden;
73
+ justify-content: space-between;
74
margin-top: 3.5rem;
75
padding: var(--spacing-md) var(--spacing-md) 0 var(--spacing-md);
77
- }
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;
76
+ scrollbar-width: none;
77
+ -ms-overflow-style: none;
78
}
79
.left-panel-top::-webkit-scrollbar {
80
width: 0px;
81
}
90
- .left-panel-top {
91
- scrollbar-width: none;
92
- -ms-overflow-style: none;
93
- }
82
.left-panel-bottom {
83
position: relative;
84
flex-shrink: 0;
85
+ flex-grow: 0; /* Prevent bottom from growing */
86
}
98
- /* Ensure non-chat sections don't shrink */
99
- .config-section:not(#chats-section) {
100
- flex-shrink: 0;
101
- }
87
+
88
/* Chats section container inside sidebar */
89
#chats-section {
90
display: -webkit-flex;
91
display: flex;
92
flex-direction: column;
93
min-height: 0;
108
- flex: 0 auto;
109
- margin-top: var(--spacing-md);
94
+ flex: 1 1 auto; /* Take all available space */
95
+ max-height: 100%;
96
overflow: hidden;
97
}
98
+
99
/* Tasks section container inside sidebar */
100
#tasks-section {
101
display: -webkit-flex;
102
display: flex;
103
flex-direction: column;
104
min-height: 0;
118
- flex: 0 auto;
105
+ flex: 0 0 auto; /* Shrink to content, no reserved space */
106
+ max-height: 40%; /* Limit to 40% of viewport height when expanded */
107
margin-top: 0;
108
padding-top: var(--spacing-md);
121
- border-top: 1px solid var(--color-border);
109
+ overflow: hidden;
110
}
111
112
+ /* Flatten wrapper elements to maintain flex chain for inner scroll containers */
113
+ #chats-section > x-component,
114
+ #chats-section > x-component > div[x-data],
115
+ #tasks-section > x-component,
116
+ #tasks-section > x-component > div[x-data],
117
+ #tasks-section > x-component > div[x-data] > div[x-data] {
118
+ display: contents;
119
+ }
120
+
121
+ /* Ensure the collapse wrapper participates in flex sizing */
122
+ #tasks-section div[x-show][x-collapse] {
123
+ display: contents;
124
+ }
125
+
126
/* Common section header styling (Chats, Tasks) - matching Preferences style */
127
.section-header {
128
display: flex;
@@ -129,6 +131,7 @@
131
gap: 6px;
132
margin: 0 0 0.5rem 0;
133
padding: 0;
134
+ -webkit-user-select: none; /* Safari compatibility */
135
user-select: none;
136
font-size: var(--font-size-normal);
137
}
@@ -173,5 +176,3 @@
176
</style>
177
</body>
178
</html>
176
-
177
-
webui/components/sidebar/tasks/tasks-list.html
+105
-97
@@ -5,117 +5,125 @@
5
</script>
6
</head>
7
<body>
8
- <div x-data="{ tasksOpen: true }">
8
+ <div x-data="{ tasksOpen: true }" class="tasks-list-root">
9
<template x-if="$store.tasks">
10
- <div x-data>
10
+ <div x-data class="tasks-list-inner">
11
<h3 class="section-header section-header-collapsible" @click="tasksOpen = !tasksOpen">
12
Tasks
13
<svg class="arrow-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16" :class="{'rotated': !tasksOpen}">
14
<path d="M8 4l8 8-8 8" />
15
</svg>
16
</h3>
17
- <div x-show="tasksOpen" x-collapse x-transition>
17
+ <div class="tasks-list-body" x-show="tasksOpen" x-collapse x-transition>
18
<div class="tasks-list-container" x-data>
19
- <ul class="config-list tasks-config-list" x-show="$store.tasks.tasks.length > 0">
20
- <template x-for="task in $store.tasks.tasks" :key="task.id">
21
- <li>
22
- <div :class="{'chat-list-button': true, 'font-bold': task.id === $store.tasks.selected, 'has-task-container': true}"
23
- @click="$store.tasks.selectTask(task.id)">
24
- <div class="task-container task-container-vertical">
25
- <span class="task-name"
26
- :title="(task.task_name || `Task #${task.no}`) + ' (' + (task.name || `Chat #${task.no}`) + ')'"
27
- x-text="(task.task_name || `Task #${task.no}`) + ' (' + (task.name || `Chat #${task.no}`) + ')'"
28
- :data-task-id="task.id"></span>
29
- <div class="task-info-line">
30
- <span class="scheduler-status-badge scheduler-status-badge-small"
31
- :class="task.state ? `scheduler-status-${task.state}` : 'scheduler-status-idle'"
32
- x-text="task.state || 'idle'"></span>
33
- <button class="edit-button"
34
- @click.stop="$store.tasks.openDetail(task.id)"
35
- title="View task details" style="margin-left: auto; margin-right: 5px;">
36
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" fill="var(--color-primary)" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
37
- <path d="M256 0c70.69 0 134.69 28.66 181.02 74.98C483.34 121.3 512 185.31 512 256c0 70.69-28.66 134.7-74.98 181.02C390.69 483.34 326.69 512 256 512c-70.69 0-134.69-28.66-181.02-74.98C28.66 390.69 0 326.69 0 256c0-70.69 28.66-134.69 74.98-181.02C121.31 28.66 185.31 0 256 0zm-9.96 161.03c0-4.28.76-8.26 2.27-11.91 1.5-3.63 3.77-6.94 6.79-9.91 3-2.95 6.29-5.2 9.84-6.7 3.57-1.5 7.41-2.28 11.52-2.28 4.12 0 7.96.78 11.49 2.27 3.54 1.51 6.78 3.76 9.75 6.73 2.95 2.97 5.16 6.26 6.64 9.91 1.49 3.63 2.22 7.61 2.22 11.89 0 4.17-.73 8.08-2.21 11.69-1.48 3.6-3.68 6.94-6.65 9.97-2.94 3.03-6.18 5.32-9.72 6.84-3.54 1.51-7.38 2.29-11.52 2.29-4.22 0-8.14-.76-11.75-2.26-3.58-1.51-6.86-3.79-9.83-6.79-2.94-3.02-5.16-6.34-6.63-9.97-1.48-3.62-2.21-7.54-2.21-11.77zm13.4 178.16c-1.11 3.97-3.35 11.76 3.3 11.76 1.44 0 3.27-.81 5.46-2.4 2.37-1.71 5.09-4.31 8.13-7.75 3.09-3.5 6.32-7.65 9.67-12.42 3.33-4.76 6.84-10.22 10.49-16.31.37-.65 1.23-.87 1.89-.48l12.36 9.18c.6.43.73 1.25.35 1.86-5.69 9.88-11.44 18.51-17.26 25.88-5.85 7.41-11.79 13.57-17.8 18.43l-.1.06c-6.02 4.88-12.19 8.55-18.51 11.01-17.58 6.81-45.36 5.7-53.32-14.83-5.02-12.96-.9-27.69 3.06-40.37l19.96-60.44c1.28-4.58 2.89-9.62 3.47-14.33.97-7.87-2.49-12.96-11.06-12.96h-17.45c-.76 0-1.38-.62-1.38-1.38l.08-.48 4.58-16.68c.16-.62.73-1.04 1.35-1.02l89.12-2.79c.76-.03 1.41.57 1.44 1.33l-.07.43-37.76 124.7zm158.3-244.93c-41.39-41.39-98.58-67-161.74-67-63.16 0-120.35 25.61-161.74 67-41.39 41.39-67 98.58-67 161.74 0 63.16 25.61 120.35 67 161.74 41.39 41.39 98.58 67 161.74 67 63.16 0 120.35-25.61 161.74-67 41.39-41.39 67-98.58 67-161.74 0-63.16-25.61-120.35-67-161.74z"/>
38
- </svg>
39
- </button>
40
- <button class="edit-button" title="Clear task chat"
41
- @click.stop="$store.tasks.reset(task.id)" style="margin-right: 5px;">
42
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 122.88 121.1" fill="var(--color-primary)" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
43
- <path d="M62.89,56.03c1.11-0.35,2.34-0.25,3.72,0.37l10.4,7.87c2.26,1.71,4.24,3.78,2.73,6.9 c-0.51,1.06-1.4,2.1-2.38,3.49l-0.53,0.75c-1.97,2.8-2.61,2-5.71,1.83c0.56,13.37,1.75,27.82-2.64,40.88 c-0.87,2.7-3.32,3.44-6.95,2.71l-6.1-2.03c4.11-6.14,6.16-13.85,6.44-22.89c-3.46,8.58-6.8,16.96-10.68,20.86l-6.28-2.08 c0.61-3.05,1.05-5.43,0.35-6.9l-4.07,4.24l-9.33-5.77c6.36-3.36,11.62-7.87,15.6-13.73c-6.69,5.01-12.76,8.1-18.14,8.99 c-2.75,0.83-4.49,0.35-5.16-1.53c-0.48-1.34-0.05-1.77,0.81-2.86c1.11-1.41,2.61-2.67,4.35-3.79c-3.13,1.1-4.64,0.95-6.37,1.51 c-4.9,1.59-9.94-1.86-8.26-6.9c1.07-3.23,3.54-3.09,6.67-4.07l5.42-1.69c-5.19,0.28-10.32,0.45-15.02-0.25 c-5.4-0.8-5.31-0.99-8.24-5.38c-3.94-5.91-6.25-11.45,2.52-9.16c16.73,3.18,33.56,5.34,51.25-0.98c-0.76-1.32-0.9-2.57-0.5-3.73 C57.37,60.94,61.13,56.58,62.89,56.03L62.89,56.03z M113.8,2.42L74.45,51.53c-4.71,6.68,3.2,11.91,8.39,5.64l39.2-49.27 C125.12,1.86,119.13-3.16,113.8,2.42L113.8,2.42z"/>
44
- </svg>
45
- </button>
46
- <button class="edit-button" title="Delete task" @click.stop="$store.tasks.deleteTask(task.id)">X</button>
19
+ <ul class="config-list tasks-config-list" x-show="$store.tasks.tasks.length > 0">
20
+ <template x-for="task in $store.tasks.tasks" :key="task.id">
21
+ <li>
22
+ <div :class="{'chat-list-button': true, 'font-bold': task.id === $store.tasks.selected, 'has-task-container': true}"
23
+ @click="$store.tasks.selectTask(task.id)">
24
+ <div class="task-container task-container-vertical">
25
+ <span class="task-name"
26
+ :title="(task.task_name || `Task #${task.no}`) + ' (' + (task.name || `Chat #${task.no}`) + ')'"
27
+ x-text="(task.task_name || `Task #${task.no}`) + ' (' + (task.name || `Chat #${task.no}`) + ')'"
28
+ :data-task-id="task.id"></span>
29
+ <div class="task-info-line">
30
+ <span class="scheduler-status-badge scheduler-status-badge-small"
31
+ :class="task.state ? `scheduler-status-${task.state}` : 'scheduler-status-idle'"
32
+ x-text="task.state || 'idle'"></span>
33
+ <button class="edit-button"
34
+ @click.stop="$store.tasks.openDetail(task.id)"
35
+ title="View task details" style="margin-left: auto; margin-right: 5px;">
36
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512" fill="var(--color-primary)" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
37
+ <path d="M256 0c70.69 0 134.69 28.66 181.02 74.98C483.34 121.3 512 185.31 512 256c0 70.69-28.66 134.7-74.98 181.02C390.69 483.34 326.69 512 256 512c-70.69 0-134.69-28.66-181.02-74.98C28.66 390.69 0 326.69 0 256c0-70.69 28.66-134.69 74.98-181.02C121.31 28.66 185.31 0 256 0zm-9.96 161.03c0-4.28.76-8.26 2.27-11.91 1.5-3.63 3.77-6.94 6.79-9.91 3-2.95 6.29-5.2 9.84-6.7 3.57-1.5 7.41-2.28 11.52-2.28 4.12 0 7.96.78 11.49 2.27 3.54 1.51 6.78 3.76 9.75 6.73 2.95 2.97 5.16 6.26 6.64 9.91 1.49 3.63 2.22 7.61 2.22 11.89 0 4.17-.73 8.08-2.21 11.69-1.48 3.6-3.68 6.94-6.65 9.97-2.94 3.03-6.18 5.32-9.72 6.84-3.54 1.51-7.38 2.29-11.52 2.29-4.22 0-8.14-.76-11.75-2.26-3.58-1.51-6.86-3.79-9.83-6.79-2.94-3.02-5.16-6.34-6.63-9.97-1.48-3.62-2.21-7.54-2.21-11.77zm13.4 178.16c-1.11 3.97-3.35 11.76 3.3 11.76 1.44 0 3.27-.81 5.46-2.4 2.37-1.71 5.09-4.31 8.13-7.75 3.09-3.5 6.32-7.65 9.67-12.42 3.33-4.76 6.84-10.22 10.49-16.31.37-.65 1.23-.87 1.89-.48l12.36 9.18c.6.43.73 1.25.35 1.86-5.69 9.88-11.44 18.51-17.26 25.88-5.85 7.41-11.79 13.57-17.8 18.43l-.1.06c-6.02 4.88-12.19 8.55-18.51 11.01-17.58 6.81-45.36 5.7-53.32-14.83-5.02-12.96-.9-27.69 3.06-40.37l19.96-60.44c1.28-4.58 2.89-9.62 3.47-14.33.97-7.87-2.49-12.96-11.06-12.96h-17.45c-.76 0-1.38-.62-1.38-1.38l.08-.48 4.58-16.68c.16-.62.73-1.04 1.35-1.02l89.12-2.79c.76-.03 1.41.57 1.44 1.33l-.07.43-37.76 124.7zm158.3-244.93c-41.39-41.39-98.58-67-161.74-67-63.16 0-120.35 25.61-161.74 67-41.39 41.39-67 98.58-67 161.74 0 63.16 25.61 120.35 67 161.74 41.39 41.39 98.58 67 161.74 67 63.16 0 120.35-25.61 161.74-67 41.39-41.39 67-98.58 67-161.74 0-63.16-25.61-120.35-67-161.74z"/>
38
+ </svg>
39
+ </button>
40
+ <button class="edit-button" title="Clear task chat"
41
+ @click.stop="$store.tasks.reset(task.id)" style="margin-right: 5px;">
42
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 122.88 121.1" fill="var(--color-primary)" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
43
+ <path d="M62.89,56.03c1.11-0.35,2.34-0.25,3.72,0.37l10.4,7.87c2.26,1.71,4.24,3.78,2.73,6.9 c-0.51,1.06-1.4,2.1-2.38,3.49l-0.53,0.75c-1.97,2.8-2.61,2-5.71,1.83c0.56,13.37,1.75,27.82-2.64,40.88 c-0.87,2.7-3.32,3.44-6.95,2.71l-6.1-2.03c4.11-6.14,6.16-13.85,6.44-22.89c-3.46,8.58-6.8,16.96-10.68,20.86l-6.28-2.08 c0.61-3.05,1.05-5.43,0.35-6.9l-4.07,4.24l-9.33-5.77c6.36-3.36,11.62-7.87,15.6-13.73c-6.69,5.01-12.76,8.1-18.14,8.99 c-2.75,0.83-4.49,0.35-5.16-1.53c-0.48-1.34-0.05-1.77,0.81-2.86c1.11-1.41,2.61-2.67,4.35-3.79c-3.13,1.1-4.64,0.95-6.37,1.51 c-4.9,1.59-9.94-1.86-8.26-6.9c1.07-3.23,3.54-3.09,6.67-4.07l5.42-1.69c-5.19,0.28-10.32,0.45-15.02-0.25 c-5.4-0.8-5.31-0.99-8.24-5.38c-3.94-5.91-6.25-11.45,2.52-9.16c16.73,3.18,33.56,5.34,51.25-0.98c-0.76-1.32-0.9-2.57-0.5-3.73 C57.37,60.94,61.13,56.58,62.89,56.03L62.89,56.03z M113.8,2.42L74.45,51.53c-4.71,6.68,3.2,11.91,8.39,5.64l39.2-49.27 C125.12,1.86,119.13-3.16,113.8,2.42L113.8,2.42z"/>
44
+ </svg>
45
+ </button>
46
+ <button class="edit-button" title="Delete task" @click.stop="$store.tasks.deleteTask(task.id)">X</button>
47
+ </div>
48
+ </div>
49
</div>
48
- </div>
49
- </div>
50
- </li>
51
- </template>
52
- </ul>
53
- <div class="empty-list-message" x-show="$store.tasks.tasks.length === 0">
54
- <p><i>No tasks to list.</i></p>
50
+ </li>
51
+ </template>
52
+ </ul>
53
+ <div class="empty-list-message" x-show="$store.tasks.tasks.length === 0">
54
+ <p><i>No tasks to list.</i></p>
55
+ </div>
56
</div>
57
</div>
57
- </div>
58
</div>
59
</template>
60
</div>
61
+ </template>
62
+ </div>
63
+
64
+ <style>
65
+ /* Root wrappers provide flex context when embedded */
66
+ .tasks-list-root,
67
+ .tasks-list-inner,
68
+ .tasks-list-body {
69
+ display: contents;
70
+ }
71
+ .tasks-list-container .section-header {
72
+ position: sticky;
73
+ top: 0;
74
+ flex-shrink: 0;
75
+ z-index: 10;
76
+ }
77
78
+ .tasks-list-container {
79
+ display: flex;
80
+ flex-direction: column;
81
+ flex: 1;
82
+ min-height: 0;
83
+ overflow: hidden;
84
+ position: relative;
85
+ }
86
+
87
+ /* Scrollable tasks config list */
88
+ .tasks-config-list {
89
+ flex: 1;
90
+ min-height: 0;
91
+ overflow-y: auto;
92
+ -webkit-overflow-scrolling: touch; /* smooth scrolling on iOS */
93
+ scroll-behavior: smooth;
94
+ scrollbar-width: none; /* Firefox */
95
+ -ms-overflow-style: none; /* IE/Edge */
96
+ overscroll-behavior: contain; /* avoid scroll chaining */
97
+ }
98
+ /* Hide scrollbar for Chrome/Safari/Webkit */
99
+ .tasks-config-list::-webkit-scrollbar {
100
+ display: none;
101
+ width: 0;
102
+ height: 0;
103
+ }
104
+
105
+ .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; }
106
+ .task-name:hover { background-color: rgba(255,255,255,0.1); text-decoration: none; }
107
+ .light-mode .task-name:hover { background-color: rgba(0,0,0,0.05); }
108
+
109
+ .task-info-line { display: flex; justify-content: space-between; align-items: center; width: 100%; margin-top: 2px; margin-left: 5px; }
110
+
111
+ .task-container-vertical { display: flex; flex-direction: column; width: 100%; gap: 6px; }
112
+
113
+ /* Scheduler badges (subset used in sidebar) */
114
+ .scheduler-status-badge { display: inline-block; padding: 4px 8px; border-radius: 4px; font-size: 12px; font-weight: 500; text-transform: capitalize; white-space: nowrap; }
115
+ .scheduler-status-badge-small { font-size: 10px; padding: 2px 6px; margin-right: 5px; min-width: 40px; text-align: center; }
116
+ .scheduler-status-idle { background-color: rgba(0, 100, 0, 0.2); color: #2a9d8f; border: 1px solid rgba(42, 157, 143, 0.3); }
117
+ .scheduler-status-running { background-color: rgba(0, 60, 120, 0.2); color: #4361ee; border: 1px solid rgba(67, 97, 238, 0.3); }
118
+ .scheduler-status-disabled { background-color: rgba(70, 70, 70, 0.2); color: #6c757d; border: 1px solid rgba(108, 117, 125, 0.3); }
119
+ .scheduler-status-error { background-color: rgba(120, 0, 0, 0.2); color: #e63946; border: 1px solid rgba(230, 57, 70, 0.3); }
120
+ .light-mode .scheduler-status-idle { background-color: rgba(42, 157, 143, 0.1); color: #1a6f65; }
121
+ .light-mode .scheduler-status-running { background-color: rgba(67, 97, 238, 0.1); color: #2540b3; }
122
+ .light-mode .scheduler-status-disabled { background-color: rgba(108, 117, 125, 0.1); color: #495057; }
123
+ .light-mode .scheduler-status-error { background-color: rgba(230, 57, 70, 0.1); color: #c5283d; }
124
+
125
+ .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; }
126
+ .light-mode .empty-list-message { color: var(--color-secondary-light); }
127
+ </style>
128
</body>
129
</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
-