fix: reveal conversation actions on hover

Conversation rows always reserved space for the more-actions button, and the active row kept it visible. The button now replaces the right-side timestamp only on hover, keyboard focus, or while its menu is open, leaving more room for conversation titles and timestamps by default.

Release note: 会话列表仅在悬停或键盘聚焦时显示更多操作按钮,更新时间默认更靠右,为会话标题留出更多空间。
This commit is contained in:
mesalogo
2026-08-22 15:52:04 +08:00
parent fb51793595
commit 7c34abdfbf
5 changed files with 43 additions and 24 deletions
+5 -3
View File
@@ -285,9 +285,11 @@
- 关联 Task 的 Conversation 在行最左侧显示独立展开按钮,父会话行不重复任务标签或数量;
展开后的每个 Task 子项左侧显示名称,模式、计划和共享状态标记收在右侧,与父会话的
更新时间位置一致;展开层级只到 Task,不展示 Job、Subjob 或 Run。
- 会话标题保持单行且不挤压时间或操作按钮。标题实际溢出时,悬停会话行才在标题的固定裁切
区域内平滑横向滑动以展示完整名称;移开后快速复位。未溢出标题不产生位移动效,
`prefers-reduced-motion` 下禁用滑动并保留完整标题提示。
- 会话标题保持单行且不挤压更新时间。更新时间默认靠近行右侧;低频的更多操作按钮不常驻
占位,只在悬停会话行时替换右侧时间显示。键盘焦点进入会话行或操作菜单展开时,按钮仍
保持可见。标题实际溢出时,悬停会话行才在标题的固定裁切区域内平滑横向滑动以展示完整
名称;移开后快速复位。未溢出标题不产生位移动效,`prefers-reduced-motion` 下禁用滑动
并保留完整标题提示。
- 分支会话在侧栏标题前和聊天顶栏标题旁显示同一个横向分叉徽标;徽标通过可访问名称和
工具提示说明来源会话,不能只靠图形表达。分支不改成树状会话列表,也不挤压更新时间。
- 新建 Task 后可以首次自动展开所属 Conversation;用户手动折叠后保持其选择,后台状态变化
+4 -2
View File
@@ -76,8 +76,10 @@ Task 行只显示聚合后的用户状态,不要求用户理解内部 Job/Run
- 无 Task 的 Conversation 保持现有单行样式。
- 有 Task 时在行最左侧显示独立展开按钮;父会话行不重复显示任务标签或数量。
- 会话标题溢出时保持时间和操作区固定;悬停会话行后,标题在自身裁切区域内横向滑动展示
完整名称。未溢出标题不滑动,减少动态效果偏好下使用完整标题提示而不产生位移。
- 更新时间默认靠近行右侧,更多操作按钮不常驻占位;悬停会话行时,按钮替换右侧时间显示。
键盘焦点进入会话行或操作菜单展开时,按钮仍保持可见。会话标题溢出时保持右侧区域固定,
并在自身裁切区域内横向滑动展示完整名称。未溢出标题不滑动,减少动态效果偏好下使用完整
标题提示而不产生位移。
- 展开后每个 Task 子项左侧显示名称,右侧显示本地化的模式、计划和状态标记,与父会话
更新时间对齐;已完成使用带勾成功点并将文案保留给辅助技术。列表不显示 Job、Subjob、
Run 或工具步骤。
+1 -7
View File
@@ -7640,13 +7640,7 @@ function App(): React.JSX.Element {
`conversation-branch-disabled-${conversation.id}`
return (
<div className="conversation-entry" key={conversation.id}>
<div
className={
conversation.id === activeId
? 'conversation-row conversation-row--active'
: 'conversation-row'
}
>
<div className="conversation-row">
{conversationTasks.length > 0 && (
<button
aria-expanded={tasksExpanded}
+14 -5
View File
@@ -251,24 +251,33 @@ describe('WorkspacePrimitives', () => {
)
})
it('keeps the conversation action close to the sidebar edge', () => {
it('reveals the conversation action without reserving its space', () => {
expect(stylesheet).toMatch(
/\.conversation-row:has\(\.conversation-task-toggle\) \.conversation-item\s*\{[^}]*padding-left:\s*34px;/u
)
expect(stylesheet).toMatch(
/\.conversation-task-toggle\s*\{[^}]*left:\s*3px;[^}]*width:\s*28px;[^}]*height:\s*28px;/u
)
expect(stylesheet).toMatch(
/\.conversation-row \.conversation-item\s*\{[^}]*padding-right:\s*36px;/u
expect(stylesheet).not.toMatch(
/\.conversation-row \.conversation-item\s*\{[^}]*padding-right:/u
)
expect(stylesheet).toMatch(
/\.conversation-more\s*\{[^}]*right:\s*5px;/u
)
expect(stylesheet).toMatch(
/\.conversation-row:has\(\.conversation-activity-indicator\)\s+\.conversation-item\s*\{[^}]*padding-right:\s*52px;/u
/\.conversation-row:hover \.conversation-more,\s*\.conversation-row:focus-within \.conversation-more,[^{]*\{[^}]*opacity:\s*1;/u
)
expect(stylesheet).toMatch(
/\.conversation-activity-indicator\s*\{[^}]*right:\s*38px;/u
/\.conversation-row:hover \.conversation-item small,[^{]*\.conversation-item small\s*\{[^}]*opacity:\s*0;/u
)
expect(stylesheet).not.toContain(
'.conversation-row--active .conversation-more'
)
expect(stylesheet).toMatch(
/\.conversation-row:has\(\.conversation-activity-indicator\)\s+\.conversation-item\s*\{[^}]*padding-right:\s*28px;/u
)
expect(stylesheet).toMatch(
/\.conversation-activity-indicator\s*\{[^}]*right:\s*10px;/u
)
expect(stylesheet).not.toContain('.conversation-delete')
})
+19 -7
View File
@@ -2846,6 +2846,7 @@ textarea:focus-visible {
flex: 0 0 auto;
color: var(--text-muted);
font-size: var(--font-caption);
transition: opacity var(--motion-fast) ease-out;
}
.overflow-marquee {
@@ -8900,18 +8901,14 @@ details.settings-section > :not(summary) + :not(summary) {
align-items: center;
}
.conversation-row .conversation-item {
padding-right: 36px;
}
.conversation-row:has(.conversation-activity-indicator)
.conversation-item {
padding-right: 52px;
padding-right: 28px;
}
.conversation-activity-indicator {
position: absolute;
right: 38px;
right: 10px;
width: 8px;
height: 8px;
border-radius: 50%;
@@ -8920,6 +8917,7 @@ details.settings-section > :not(summary) + :not(summary) {
box-shadow: 0 0 0 4px
color-mix(in srgb, var(--success) 14%, transparent);
pointer-events: none;
transition: right var(--motion-fast) ease-out;
}
.conversation-more {
@@ -8940,11 +8938,25 @@ details.settings-section > :not(summary) + :not(summary) {
}
.conversation-row:hover .conversation-more,
.conversation-row--active .conversation-more,
.conversation-row:focus-within .conversation-more,
.conversation-more:focus-visible {
opacity: 1;
}
.conversation-row:hover .conversation-item small,
.conversation-row:focus-within .conversation-item small,
.conversation-row:has(.conversation-more[aria-expanded='true'])
.conversation-item small {
opacity: 0;
}
.conversation-row:hover .conversation-activity-indicator,
.conversation-row:focus-within .conversation-activity-indicator,
.conversation-row:has(.conversation-more[aria-expanded='true'])
.conversation-activity-indicator {
right: 38px;
}
.conversation-more[aria-expanded='true'] {
background: var(--accent-subtle);
color: var(--accent);