fix(desktop): move the session metadata back under the title

Pinning the metadata to the right end of the title row left a wide gap
between them, so the two read as unrelated blocks rather than one header.
Put it back on its own line under the title at 11px, and give the header
back some of the height it lost: a 17px title (15px in the workspace
layout) and py-3. Measured 66.75px on a real session, between the 123.5px
original and the 35.75px single-line version. The title still truncates to
one line with the full text in a hover tooltip, so a long title cannot push
the transcript down again.
This commit is contained in:
程序员阿江(Relakkes) 2026-07-27 02:43:13 +08:00
parent 5b891151ae
commit eaf1a96a3e
2 changed files with 42 additions and 37 deletions

View File

@ -1949,7 +1949,7 @@ describe('ActiveSession task polling', () => {
describe('ActiveSession header', () => {
// 回归锚点:标题曾经是 text-[22px] 且不截断,长标题会折成两行再加一行元数据,
// 连同 pt-6/pb-4 把聊天区顶掉约 90px。标题必须单行截断元数据与它同一行。
// 连同 pt-6/pb-4 把聊天区顶掉约 120px。标题必须单行截断元数据留在它下面那行。
const longTitle = 'Create a todo_cccc-ccccbb directory, write a throwaway todo app with react + vite + tailwindcss, then start it'
function mountSessionWithLongTitle(sessionId: string) {
@ -2013,7 +2013,7 @@ describe('ActiveSession header', () => {
expect(heading.className).not.toMatch(/text-\[22px\]/)
})
it('puts the session metadata on the title row instead of a second line', () => {
it('gives the metadata its own line under the title', () => {
const sessionId = 'header-meta-session'
mountSessionWithLongTitle(sessionId)
@ -2022,10 +2022,13 @@ describe('ActiveSession header', () => {
const header = screen.getByTestId('session-header')
const heading = within(header).getByRole('heading', { level: 1 })
const titleRow = heading.parentElement as HTMLElement
const meta = titleRow.nextElementSibling as HTMLElement
expect(within(titleRow).getByText('2 messages')).toBeInTheDocument()
expect(within(titleRow).getByText('15k tokens')).toBeInTheDocument()
expect(header).toHaveClass('py-2')
// 元数据挤在标题右侧时会离标题很远,读起来像飘在角落的另一块内容。
expect(within(titleRow).queryByText('2 messages')).not.toBeInTheDocument()
expect(within(meta).getByText('2 messages')).toBeInTheDocument()
expect(within(meta).getByText('15k tokens')).toBeInTheDocument()
expect(header).toHaveClass('py-3')
})
it('keeps the separators between metadata items, never in front of them', () => {
@ -2035,7 +2038,7 @@ describe('ActiveSession header', () => {
render(<ActiveSession />)
const heading = within(screen.getByTestId('session-header')).getByRole('heading', { level: 1 })
const meta = (heading.parentElement as HTMLElement).lastElementChild as HTMLElement
const meta = (heading.parentElement as HTMLElement).nextElementSibling as HTMLElement
// 空闲会话只有三项元数据tokens / 更新时间 / 消息数),之间两个「·」,开头不该有。
// 分隔符是纯装饰,读屏时不该被念出来。

View File

@ -624,20 +624,23 @@ export function ActiveSession() {
data-testid="session-header"
className={
showRightPanel
? 'flex w-full items-center border-b border-[var(--color-border)] px-4 py-2'
: 'w-full border-b border-[var(--color-border)] px-9 py-2'
? 'flex w-full items-center border-b border-[var(--color-border)] px-4 py-2.5'
: 'w-full border-b border-[var(--color-border)] px-9 py-3'
}
>
<div className={showRightPanel ? 'min-w-0 flex-1' : 'mx-auto w-full max-w-[900px] min-w-0'}>
<div className="flex min-w-0 items-center gap-3">
<h1
className="min-w-0 flex-1 truncate text-[15px] font-bold leading-tight tracking-[-0.2px] text-[var(--color-text-primary)]"
className={`min-w-0 flex-1 truncate font-bold leading-tight tracking-[-0.2px] text-[var(--color-text-primary)] ${
showRightPanel ? 'text-[15px]' : 'text-[17px]'
}`}
style={{ fontFamily: 'var(--font-headline)' }}
title={headerTitle}
>
{headerTitle}
</h1>
<div className="flex min-w-0 shrink items-center gap-1.5 overflow-hidden whitespace-nowrap text-[11px] text-[var(--color-text-tertiary)]">
</div>
<div className="mt-1 flex min-w-0 items-center gap-1.5 overflow-hidden whitespace-nowrap text-[11px] text-[var(--color-text-tertiary)]">
{[
isActive && (
<span key="active" className="flex shrink-0 items-center gap-1.5 text-[var(--color-text-secondary)]">
@ -665,7 +668,6 @@ export function ActiveSession() {
</Fragment>
))}
</div>
</div>
{session && getSessionWorkspaceState(session) !== 'available' && (
<div className={`mt-2 inline-flex max-w-full items-center gap-2 rounded-[var(--radius-md)] border px-3 py-1.5 text-[11px] ${
getSessionWorkspaceState(session) === 'worktree_removed'