fix: clarify sidebar session tooltips
This commit is contained in:
parent
9f775d3f63
commit
c26e25414e
3 changed files with 73 additions and 4 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
34
tests/test_sidebar_tooltips.py
Normal file
34
tests/test_sidebar_tooltips.py
Normal 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
|
||||
Loading…
Reference in a new issue