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 -