diff --git a/src/channels/web/static/app.js b/src/channels/web/static/app.js index c64f491e..42ce6ba2 100644 --- a/src/channels/web/static/app.js +++ b/src/channels/web/static/app.js @@ -1690,22 +1690,25 @@ function renderNodes(nodes, container, depth) { const row = document.createElement('div'); row.className = 'tree-row'; row.style.paddingLeft = (depth * 16 + 8) + 'px'; + row.tabIndex = 0; + row.setAttribute('role', 'treeitem'); if (node.is_dir) { + row.setAttribute('aria-expanded', node.expanded ? 'true' : 'false'); const arrow = document.createElement('span'); arrow.className = 'expand-arrow' + (node.expanded ? ' expanded' : ''); arrow.textContent = '\u25B6'; - arrow.addEventListener('click', (e) => { - e.stopPropagation(); - toggleExpand(node); - }); row.appendChild(arrow); const label = document.createElement('span'); label.className = 'tree-label dir'; label.textContent = node.name; - label.addEventListener('click', () => toggleExpand(node)); row.appendChild(label); + + row.addEventListener('click', () => toggleExpand(node)); + row.addEventListener('keydown', (e) => { + if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggleExpand(node); } + }); } else { const spacer = document.createElement('span'); spacer.className = 'expand-arrow-spacer'; @@ -1714,8 +1717,12 @@ function renderNodes(nodes, container, depth) { const label = document.createElement('span'); label.className = 'tree-label file'; label.textContent = node.name; - label.addEventListener('click', () => readMemoryFile(node.path)); row.appendChild(label); + + row.addEventListener('click', () => readMemoryFile(node.path)); + row.addEventListener('keydown', (e) => { + if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); readMemoryFile(node.path); } + }); } container.appendChild(row); diff --git a/src/channels/web/static/style.css b/src/channels/web/static/style.css index 2f1d9a53..1536f9e9 100644 --- a/src/channels/web/static/style.css +++ b/src/channels/web/static/style.css @@ -9,6 +9,7 @@ --text-secondary: #a1a1aa; --accent: #34d399; --accent-hover: #2fc48d; + --accent-soft: rgba(52, 211, 153, 0.15); --success: #34d399; --warning: #F5A623; --danger: #E64C4C; @@ -655,11 +656,11 @@ body { padding: 16px; display: flex; flex-direction: column; - gap: 12px; + gap: 16px; } .message { - max-width: 80%; + max-width: 72%; padding: 10px 14px; border-radius: var(--radius); font-size: 14px; @@ -669,8 +670,8 @@ body { .message.user { align-self: flex-end; - background: var(--accent); - color: #09090b; + background: var(--accent-soft); + color: var(--accent); border-bottom-right-radius: 2px; white-space: pre-wrap; } @@ -680,6 +681,9 @@ body { background: var(--bg-secondary); border: 1px solid var(--border); border-bottom-left-radius: 2px; + padding: 14px 18px; + font-size: 15px; + line-height: 1.6; } .message.system { @@ -710,10 +714,10 @@ body { padding: 0; } -.message p { margin: 0 0 8px 0; } +.message p { margin: 0 0 10px 0; } .message p:last-child { margin-bottom: 0; } .message ul, .message ol { margin: 4px 0; padding-left: 20px; } -.message li { margin: 2px 0; } +.message li { margin: 4px 0; } .message blockquote { margin: 6px 0; padding: 4px 12px; @@ -1062,7 +1066,7 @@ body { } .approval-card .approval-actions button:disabled { - opacity: 0.4; + opacity: 0.5; cursor: not-allowed; } @@ -1241,7 +1245,7 @@ body { } .auth-card .auth-actions button:disabled { - opacity: 0.4; + opacity: 0.5; cursor: not-allowed; } @@ -1301,6 +1305,11 @@ body { box-shadow: 0 0 0 3px rgba(52, 211, 153, 0.1); } +.chat-input textarea:disabled { + opacity: 0.5; + cursor: not-allowed; +} + .chat-input button { padding: 8px 20px; background: var(--accent); @@ -1314,7 +1323,7 @@ body { transition: background 0.2s, transform 0.2s; } -.chat-input button:hover { +.chat-input button:hover:not(:disabled) { background: var(--accent-hover); transform: translateY(-1px); } @@ -1324,8 +1333,18 @@ body { } .chat-input button:disabled { - opacity: 0.5; + opacity: 0.6; cursor: not-allowed; + transform: none; +} + +/* Keyboard accessibility focus rings */ +.chat-input textarea:focus-visible, +.chat-input button:focus-visible, +.tab-bar button:focus-visible, +.tree-row:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; } /* Memory Tab */ @@ -1425,7 +1444,7 @@ body { color: var(--text-secondary); } -.tree-label.file:hover { +.tree-row:hover .tree-label.file { color: var(--accent); } @@ -2307,7 +2326,7 @@ body { } .log-entry:hover { - background: var(--bg-secondary); + background: var(--bg-tertiary); } .log-ts { @@ -3781,7 +3800,7 @@ mark { } /* Image Upload */ -.attach-btn { +.chat-input .attach-btn { background: none; border: none; cursor: pointer; @@ -3794,10 +3813,13 @@ mark { display: flex; align-items: center; justify-content: center; + font-weight: 400; } -.attach-btn:hover { +.chat-input .attach-btn:hover { + background: none; color: var(--text); + transform: none; } .image-preview-strip {