personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move chat bar response above input with expandable panel and dismiss

+95 -23
+45 -8
convey/static/app.css
··· 995 995 transform: translateX(-50%); 996 996 width: 80%; 997 997 z-index: var(--z-bars); 998 - height: var(--app-bar-height); 999 - padding: 0 16px; 1000 998 display: flex; 1001 - flex-direction: row; 999 + min-height: var(--app-bar-height); 1000 + flex-direction: column; 1002 1001 align-items: center; 1003 - justify-content: center; 1004 - gap: 12px; 1005 1002 border-radius: 12px; 1006 1003 border: 1px solid var(--facet-border, #e0e0e0); 1007 1004 box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); ··· 1034 1031 border-radius: 12px; 1035 1032 } 1036 1033 1034 + .chat-bar-input-row { 1035 + display: flex; 1036 + flex-direction: row; 1037 + align-items: center; 1038 + gap: 12px; 1039 + width: 100%; 1040 + padding: 0 16px; 1041 + min-height: var(--app-bar-height); 1042 + } 1043 + 1044 + .chat-bar-response-panel { 1045 + position: relative; 1046 + padding: 12px 16px; 1047 + padding-right: 36px; 1048 + border-bottom: 1px solid var(--facet-border, #e0e0e0); 1049 + width: 100%; 1050 + } 1051 + 1052 + .chat-bar-dismiss { 1053 + position: absolute; 1054 + top: 8px; 1055 + right: 8px; 1056 + width: 24px; 1057 + height: 24px; 1058 + border: none; 1059 + background: transparent; 1060 + color: #999; 1061 + font-size: 14px; 1062 + cursor: pointer; 1063 + display: flex; 1064 + align-items: center; 1065 + justify-content: center; 1066 + border-radius: 50%; 1067 + z-index: 1; 1068 + } 1069 + 1070 + .chat-bar-dismiss:hover { 1071 + background: rgba(0, 0, 0, 0.05); 1072 + color: #666; 1073 + } 1074 + 1037 1075 /* Chat Bar Elements */ 1038 1076 .chat-bar-input { 1039 1077 flex: 1; ··· 1105 1143 } 1106 1144 1107 1145 .chat-bar-response { 1108 - flex: 1; 1109 1146 font-size: 13px; 1110 1147 color: #666; 1111 - white-space: nowrap; 1112 1148 overflow: hidden; 1113 - text-overflow: ellipsis; 1149 + max-height: 5em; 1150 + line-height: 1.4; 1114 1151 position: relative; 1115 1152 z-index: 1; 1116 1153 }
+50 -15
convey/templates/app.html
··· 68 68 69 69 <!-- Chat Bar (universal) --> 70 70 <div class="app-bar"> 71 - <form id="chatInputForm" style="display: contents;"> 72 - <textarea id="chatMessageInput" class="chat-bar-input" rows="1" placeholder="{{ chat_bar_placeholder|default('Send a message...') }}"></textarea> 73 - <button type="submit" class="chat-bar-send" title="Send" style="display: none;">↑</button> 74 - </form> 75 - <div class="chat-bar-thinking" style="display: none;"> 76 - <span class="chat-bar-thinking-dot"></span> 77 - Thinking… 71 + <div class="chat-bar-response-panel" style="display: none;"> 72 + <div class="chat-bar-thinking" style="display: none;"> 73 + <span class="chat-bar-thinking-dot"></span> 74 + Thinking… 75 + </div> 76 + <div class="chat-bar-response" style="display: none;"></div> 77 + <button class="chat-bar-dismiss" style="display: none;" title="Dismiss">✕</button> 78 + </div> 79 + <div class="chat-bar-input-row"> 80 + <form id="chatInputForm" style="display: contents;"> 81 + <textarea id="chatMessageInput" class="chat-bar-input" rows="1" placeholder="{{ chat_bar_placeholder|default('Send a message...') }}"></textarea> 82 + <button type="submit" class="chat-bar-send" title="Send" style="display: none;">↑</button> 83 + </form> 78 84 </div> 79 - <div class="chat-bar-response" style="display: none;"></div> 80 85 </div> 81 86 82 87 <!-- Main Content --> ··· 94 99 const chatBarThinking = document.querySelector('.chat-bar-thinking'); 95 100 const chatBarResponse = document.querySelector('.chat-bar-response'); 96 101 const chatBarSend = document.querySelector('.chat-bar-send'); 102 + const chatBarPanel = document.querySelector('.chat-bar-response-panel'); 103 + const chatBarDismiss = document.querySelector('.chat-bar-dismiss'); 97 104 const isChatApp = window.location.pathname.startsWith('/app/chat'); 98 105 const STORAGE_KEY = 'solstone:chatBarState'; 99 106 100 107 if (!chatBarInput || !chatBarForm) return; 101 108 109 + // --- Panel visibility helpers --- 110 + function showPanel() { 111 + if (chatBarPanel) chatBarPanel.style.display = ''; 112 + } 113 + function hidePanel() { 114 + if (chatBarPanel) chatBarPanel.style.display = 'none'; 115 + if (chatBarThinking) chatBarThinking.style.display = 'none'; 116 + if (chatBarResponse) chatBarResponse.style.display = 'none'; 117 + if (chatBarDismiss) chatBarDismiss.style.display = 'none'; 118 + } 119 + 120 + // --- Dismiss button --- 121 + if (chatBarDismiss) { 122 + chatBarDismiss.addEventListener('click', () => { 123 + hidePanel(); 124 + }); 125 + } 126 + 102 127 // --- Auto-resize textarea --- 103 128 chatBarInput.addEventListener('input', () => { 104 129 chatBarInput.style.height = 'auto'; ··· 122 147 if (saved && saved.response && !isChatApp && chatBarResponse) { 123 148 chatBarResponse.textContent = saved.response; 124 149 chatBarResponse.style.display = ''; 150 + if (chatBarDismiss) chatBarDismiss.style.display = ''; 151 + showPanel(); 125 152 } 126 153 } catch {} 127 154 ··· 147 174 chatBarSend.style.display = 'none'; 148 175 } 149 176 chatBarInput.disabled = true; 150 - if (chatBarThinking) { 151 - chatBarThinking.style.display = ''; 152 - } 153 - if (chatBarResponse) { 154 - chatBarResponse.style.display = 'none'; 155 - } 177 + if (chatBarThinking) chatBarThinking.style.display = ''; 178 + if (chatBarResponse) chatBarResponse.style.display = 'none'; 179 + if (chatBarDismiss) chatBarDismiss.style.display = 'none'; 180 + showPanel(); 156 181 157 182 try { 158 183 const r = await fetch('/api/triage', { ··· 170 195 const data = await r.json(); 171 196 if (chatBarResponse) { 172 197 chatBarResponse.textContent = data.response || ''; 173 - chatBarResponse.style.display = data.response ? '' : 'none'; 198 + if (data.response) { 199 + chatBarResponse.style.display = ''; 200 + if (chatBarDismiss) chatBarDismiss.style.display = ''; 201 + } else { 202 + chatBarResponse.style.display = 'none'; 203 + hidePanel(); 204 + } 174 205 } 175 206 176 207 // Save to localStorage ··· 184 215 } else if (chatBarResponse) { 185 216 chatBarResponse.textContent = 'Something went wrong. Try again.'; 186 217 chatBarResponse.style.display = ''; 218 + if (chatBarDismiss) chatBarDismiss.style.display = ''; 219 + showPanel(); 187 220 } 188 221 } catch (err) { 189 222 if (chatBarResponse) { 190 223 chatBarResponse.textContent = 'Connection error. Try again.'; 191 224 chatBarResponse.style.display = ''; 225 + if (chatBarDismiss) chatBarDismiss.style.display = ''; 226 + showPanel(); 192 227 } 193 228 } finally { 194 229 if (chatBarThinking) {