chats and tasks lists polishing

frdel committed Nov 4, 2025 at 14:15 UTC d96d13d24e63b407dad2c8b9a672f55c6b49581f
3 files changed +66 -26
webui/components/sidebar/chats/chats-list.html
+13 -17
@@ -14,10 +14,9 @@
14 <ul class="config-list chats-config-list" x-show="$store.chats.contexts.length > 0">
15 <template x-for="context in $store.chats.contexts" :key="context.id">
16 <li>
17 - <div :class="{'chat-container': true, 'chat-selected': context.id === $store.chats.selected}">
18 - <div class="chat-stripe" :style="'background-color: ' + (context.project?.color || 'transparent')">
19 - </div>
20 - <div class="chat-list-button" @click="$store.chats.selectChat(context.id)">
17 + <div :class="{'chat-container': true, 'chat-selected': context.id === $store.chats.selected}" @click="$store.chats.selectChat(context.id)">
18 + <div class="chat-list-button">
19 + <span class="project-color-ball" :style="context.project?.color ? { backgroundColor: context.project.color } : { border: '1px solid var(--color-border)' }"></span>
20 <span class="chat-name" :title="context.name ? context.name : 'Chat #' + context.no"
21 x-text="context.name ? context.name : 'Chat #' + context.no"></span>
22 </div>
@@ -69,7 +68,6 @@
68
69 .chat-container {
70 position: relative;
72 - /* Anchor for the stripe */
71 display: flex;
72 align-items: center;
73 justify-content: space-between;
@@ -78,7 +76,7 @@
76 border-radius: 4px;
77 transition: background-color 0.2s ease-in-out;
78 overflow: hidden;
81 - /* Important for containing the stripe's corners */
79 + cursor: pointer;
80 }
81
82 .chat-container:hover {
@@ -89,20 +87,18 @@
87 display: flex;
88 align-items: center;
89 flex-grow: 1;
92 - cursor: pointer;
93 - padding: 8px 8px 8px 10px;
94 - /* Top/Right/Bottom/Left - Left padding for stripe */
90 + padding: 8px;
91 overflow: hidden;
92 + gap: 0.5em;
93 }
94
98 - .chat-stripe {
99 - position: absolute;
100 - left: 0;
101 - top: 0;
102 - width: 5px;
103 - height: 100%;
104 - border-radius: 0;
105 - /* No rounded corners */
95 + .project-color-ball {
96 + width: 0.6em;
97 + height: 0.6em;
98 + border-radius: 50%;
99 + display: inline-block;
100 + box-sizing: border-box;
101 + flex-shrink: 0;
102 }
103
104 .chat-name {
webui/components/sidebar/chats/chats-store.js
+3
@@ -11,6 +11,7 @@ import {
11 getConnectionStatus,
12 } from "/index.js";
13 import { store as notificationStore } from "/components/notifications/notification-store.js";
14 +import { store as tasksStore } from "/components/sidebar/tasks/tasks-store.js";
15
16 const model = {
17 contexts: [],
@@ -272,6 +273,8 @@ const model = {
273 setSelected(contextId) {
274 this.selected = contextId;
275 this.selectedContext = this.contexts.find((ctx) => ctx.id === contextId);
276 + // if not found in contexts, try to find in tasks < not nice, will need refactor later
277 + if(!this.selectedContext) this.selectedContext = tasksStore.tasks.find((ctx) => ctx.id === contextId);
278 localStorage.setItem("lastSelectedChat", contextId);
279 },
280
webui/components/sidebar/tasks/tasks-list.html
+50 -9
@@ -24,13 +24,16 @@
24 <ul class="config-list tasks-config-list" x-show="$store.tasks.tasks.length > 0">
25 <template x-for="task in $store.tasks.tasks" :key="task.id">
26 <li>
27 - <div :class="{'chat-list-button': true, 'font-bold': task.id === $store.tasks.selected, 'has-task-container': true}"
28 - @click="$store.tasks.selectTask(task.id)">
29 - <div class="task-container task-container-vertical">
30 - <span class="task-name"
31 - :title="(task.task_name || `Task #${task.no}`) + ' (' + (task.name || `Chat #${task.no}`) + ')'"
32 - x-text="(task.task_name || `Task #${task.no}`) + ' (' + (task.name || `Chat #${task.no}`) + ')'"
27 + <div class="task-container" :class="{'task-selected': task.id === $store.tasks.selected}">
28 + <div class="chat-list-button" @click="$store.tasks.selectTask(task.id)">
29 + <div class="task-container-vertical">
30 + <div class="task-title-line">
31 + <span class="project-color-ball" :style="task.project?.color ? { backgroundColor: task.project.color } : { border: '1px solid var(--color-border)' }"></span>
32 + <span class="task-name"
33 + :title="(task.task_name || `Task #${task.no}`)"
34 + x-text="(task.task_name || `Task #${task.no}`)"
35 :data-task-id="task.id"></span>
36 + </div>
37 <div class="task-info-line">
38 <span class="scheduler-status-badge scheduler-status-badge-small"
39 :class="task.state ? `scheduler-status-${task.state}` : 'scheduler-status-idle'"
@@ -50,6 +53,7 @@
53 </button>
54 <button class="edit-button" title="Delete task" @click.stop="$store.tasks.deleteTask(task.id)">X</button>
55 </div>
56 + </div>
57 </div>
58 </div>
59 </li>
@@ -115,13 +119,50 @@
119 height: 0;
120 }
121
118 - .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; }
119 - .task-name:hover { background-color: rgba(255,255,255,0.1); text-decoration: none; }
122 + .task-title-line {
123 + display: flex;
124 + align-items: center;
125 + gap: 0.5em;
126 + }
127 +
128 + .project-color-ball {
129 + width: 0.6em;
130 + height: 0.6em;
131 + border-radius: 50%;
132 + display: inline-block;
133 + box-sizing: border-box;
134 + flex-shrink: 0;
135 + }
136 +
137 + .task-name { display: block; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 3px 0; cursor: pointer; border-radius: 4px; transition: background-color 0.2s; font-size: var(--font-size-small); margin-bottom: 2px; }
138 .light-mode .task-name:hover { background-color: rgba(0,0,0,0.05); }
139
122 - .task-info-line { display: flex; justify-content: space-between; align-items: center; width: 100%; margin-top: 2px; margin-left: 5px; }
140 + .task-info-line { display: flex; justify-content: space-between; align-items: center; width: 100%; margin-top: 2px; }
141
142 + .task-container {
143 + width: 100%;
144 + display: flex;
145 + align-items: stretch;
146 + position: relative;
147 + border-radius: 4px;
148 + overflow: hidden;
149 + }
150 +
151 + .task-container:hover {
152 + background-color: rgba(255, 255, 255, 0.03);
153 + }
154 +
155 +
156 .task-container-vertical { display: flex; flex-direction: column; width: 100%; gap: 6px; }
157 +
158 + /* Selected task accent */
159 + .task-selected {
160 + background-color: rgba(var(--color-border-rgb, 50, 50, 50), 0.5);
161 + }
162 +
163 + .task-selected .task-name {
164 + font-weight: bold;
165 + }
166
167 /* Scheduler badges (subset used in sidebar) */
168 .scheduler-status-badge { display: inline-block; padding: 4px 8px; border-radius: 4px; font-size: 12px; font-weight: 500; text-transform: capitalize; white-space: nowrap; }