fix: clarify sidebar session tooltips

This commit is contained in:
ai-ag2026 2026-05-30 20:56:59 +02:00
parent 9f775d3f63
commit c26e25414e
3 changed files with 73 additions and 4 deletions

View file

@ -3,6 +3,10 @@
## [Unreleased]
### Fixed
- Sidebar session row tooltips now explain fork, prior-turn, child-session, and status badges, and hovering the truncated chat title now shows the full title instead of the old rename hint.
## [v0.51.173] — 2026-05-30 — Release ES (stage-batch55 — Windows path/journal safety + pin-quota snapshot fix + tool-card paging anchor + sidebar dedupe + quieter tool cards)
### Fixed

View file

@ -3145,6 +3145,36 @@ function _sessionTitleForForkParent(parentSid){
return title;
}
function _sessionFullTitleTooltip(rawTitle, cleanTitle){
const fallback=String(cleanTitle||'Untitled').trim()||'Untitled';
const full=String(rawTitle||fallback).trim()||fallback;
if(full.startsWith('[SYSTEM:')) return fallback;
return full;
}
function _sessionForkTooltip(parentLabel){
const parent=String(parentLabel||'').trim()||'unknown parent';
return `Forked conversation — parent: ${parent}`;
}
function _sessionLineageBadgeTooltip(label, canExpand){
const base=String(label||'Prior turns').trim()||'Prior turns';
return canExpand
? `${base} — earlier context turns are collapsed here. Click to show or hide them.`
: `${base} — earlier context turns are collapsed here.`;
}
function _sessionChildBadgeTooltip(label){
const base=String(label||'Child sessions').trim()||'Child sessions';
return `${base} — child conversations spawned from this session. Click to show or hide them.`;
}
function _sessionStateTooltip({isStreaming=false,hasUnread=false}={}){
if(isStreaming) return 'Conversation is running';
if(hasUnread) return 'Unread completion';
return '';
}
function _attachChildSessionsToSidebarRows(collapsedRows, rawSessions){
const rows=(collapsedRows||[]).filter(s=>!_isChildSession(s)).map(s=>({...s}));
const visibleBySid=new Map();
@ -3843,7 +3873,7 @@ function renderSessionListFromCache(){
branchInd.className='session-branch-indicator';
branchInd.innerHTML=li('git-branch',12);
const parentLabel=_sessionTitleForForkParent(s.parent_session_id)||_truncatedSessionId(s.parent_session_id);
branchInd.title=(typeof t==='function'?t('forked_from'):'Forked from')+' '+parentLabel;
branchInd.title=_sessionForkTooltip(parentLabel);
titleRow.appendChild(branchInd);
}
const title=document.createElement('span');
@ -3852,7 +3882,7 @@ function renderSessionListFromCache(){
const titleMatched=Boolean(searchQueryRaw&&displayTitle.toLowerCase().includes(searchQueryRaw.toLowerCase()));
if(titleMatched) _appendHighlightedText(title,displayTitle,searchQueryRaw,'session-search-hit');
else title.textContent=displayTitle;
title.title=readOnly?'Read-only imported session':'Double-click to rename';
title.title=_sessionFullTitleTooltip(rawTitle,cleanTitle);
const tsMs=_sessionTimestampMs(s);
const ts=document.createElement('span');
const hasAttentionState=isStreaming||hasUnread;
@ -3888,7 +3918,7 @@ function renderSessionListFromCache(){
segmentCountEl.className='session-lineage-count'+(canExpandLineageSegments?' expandable':'');
const segmentLabel=t('session_meta_segments', segmentCount);
segmentCountEl.textContent=segmentLabel;
segmentCountEl.title=segmentLabel;
segmentCountEl.title=_sessionLineageBadgeTooltip(segmentLabel,canExpandLineageSegments);
if(canExpandLineageSegments){
segmentCountEl.setAttribute('role','button');
segmentCountEl.setAttribute('tabindex','0');
@ -3917,7 +3947,7 @@ function renderSessionListFromCache(){
childCountEl.className='session-child-count';
const childLabel=t('session_meta_children', childCount);
childCountEl.textContent=childLabel;
childCountEl.title=childLabel;
childCountEl.title=_sessionChildBadgeTooltip(childLabel);
['pointerdown','pointerup','click'].forEach(ev=>childCountEl.addEventListener(ev,e=>e.stopPropagation()));
childCountEl.onclick=(e)=>{
e.stopPropagation();
@ -4104,6 +4134,7 @@ function renderSessionListFromCache(){
const state=document.createElement('span');
state.className='session-attention-indicator session-state-indicator'+(isStreaming?' is-streaming':(hasUnread?' is-unread':''));
state.setAttribute('aria-hidden','true');
state.title=_sessionStateTooltip({isStreaming,hasUnread});
el.appendChild(state);
// Single trigger button that opens a shared dropdown menu
let actions=null;

View file

@ -0,0 +1,34 @@
"""Sidebar tooltip contract tests."""
from pathlib import Path
REPO_ROOT = Path(__file__).parent.parent.resolve()
SESSIONS_JS_PATH = REPO_ROOT / "static" / "sessions.js"
def _sessions_js() -> str:
return SESSIONS_JS_PATH.read_text(encoding="utf-8")
def test_session_title_hover_shows_full_title_not_rename_hint():
"""The truncated sidebar title needs a real full-title tooltip.
The old "Double-click to rename" title hid the only native hover affordance
that can reveal a long chat title when badges/tags squeeze the row.
"""
js = _sessions_js()
assert "Double-click to rename" not in js
assert "title.title=_sessionFullTitleTooltip(rawTitle,cleanTitle);" in js
def test_sidebar_status_badges_have_explanatory_tooltips():
"""Compact badges/icons must explain what they mean, not repeat the chip text."""
js = _sessions_js()
assert "function _sessionFullTitleTooltip" in js
assert "function _sessionForkTooltip" in js
assert "function _sessionLineageBadgeTooltip" in js
assert "function _sessionChildBadgeTooltip" in js
assert "function _sessionStateTooltip" in js
assert "branchInd.title=_sessionForkTooltip(parentLabel);" in js
assert "segmentCountEl.title=_sessionLineageBadgeTooltip(segmentLabel,canExpandLineageSegments);" in js
assert "childCountEl.title=_sessionChildBadgeTooltip(childLabel);" in js
assert "state.title=_sessionStateTooltip({isStreaming,hasUnread});" in js