mirror of
https://github.com/NanmiCoder/claude-code-haha.git
synced 2026-10-10 20:03:13 +08:00
fix(desktop): hide short-project fold control and shrink context meter
The fold button was shown whenever a project was marked expanded, including short lists auto-expanded by history paging. Keep it only above the 6-session threshold. Replace the composer percentage chip with a compact ring.
This commit is contained in:
@@ -635,7 +635,7 @@ describe('ContextUsageIndicator touch target', () => {
|
||||
render(<ContextUsageIndicator sessionId="session-1" chatState="idle" messageCount={1} compact />)
|
||||
|
||||
const trigger = screen.getByTestId('context-usage-indicator')
|
||||
expect(trigger).toHaveClass('h-8')
|
||||
expect(trigger).toHaveClass('h-8', 'w-8')
|
||||
expect(trigger).not.toHaveClass('h-11')
|
||||
})
|
||||
|
||||
@@ -646,7 +646,7 @@ describe('ContextUsageIndicator touch target', () => {
|
||||
render(<ContextUsageIndicator sessionId="session-1" chatState="idle" messageCount={1} compact />)
|
||||
|
||||
const trigger = screen.getByTestId('context-usage-indicator')
|
||||
expect(trigger).toHaveClass('h-11')
|
||||
expect(trigger).toHaveClass('h-11', 'w-11')
|
||||
expect(trigger).not.toHaveClass('h-8')
|
||||
})
|
||||
|
||||
@@ -700,6 +700,9 @@ describe('ContextUsageIndicator presentation', () => {
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('context-usage-indicator')).toHaveTextContent('21%')
|
||||
})
|
||||
const trigger = screen.getByTestId('context-usage-indicator')
|
||||
expect(trigger).toHaveClass('h-8', 'w-8')
|
||||
expect(trigger.querySelector('.font-mono')).not.toBeInTheDocument()
|
||||
expect(screen.queryByTestId('context-usage-popover')).not.toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByTestId('context-usage-indicator'))
|
||||
|
||||
@@ -544,29 +544,31 @@ export function ContextUsageIndicator({
|
||||
onClick={handleTriggerClick}
|
||||
title={t('contextIndicator.title')}
|
||||
data-testid="context-usage-indicator"
|
||||
className={`flex shrink-0 items-center gap-[7px] rounded-full border border-[var(--color-border)] bg-transparent text-[var(--color-text-secondary)] transition-[background-color,color,border-color] duration-150 ease-out hover:border-[var(--color-outline)] hover:bg-[var(--color-surface-hover)] hover:text-[var(--color-text-primary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-surface-container-lowest)] ${
|
||||
isMobileBrowser ? 'h-11' : 'h-8'
|
||||
} ${compact ? 'px-2' : 'px-3'} ${detailsOpen ? 'border-[var(--color-outline)] bg-[var(--color-surface-hover)] text-[var(--color-text-primary)]' : ''}`}
|
||||
className={`group grid shrink-0 place-items-center rounded-full bg-transparent text-[var(--color-text-secondary)] transition-[background-color,color] duration-150 ease-out hover:bg-[var(--color-surface-hover)] hover:text-[var(--color-text-primary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-surface-container-lowest)] ${
|
||||
isMobileBrowser ? 'h-11 w-11' : 'h-8 w-8'
|
||||
} ${detailsOpen ? 'bg-[var(--color-surface-hover)] text-[var(--color-text-primary)]' : ''}`}
|
||||
>
|
||||
<span className="relative grid h-[18px] w-[18px] shrink-0 place-items-center rounded-full">
|
||||
<span className={`relative grid shrink-0 place-items-center rounded-full ${isMobileBrowser ? 'h-[22px] w-[22px]' : 'h-5 w-5'}`}>
|
||||
{loading && !displayContext ? (
|
||||
<span className="absolute inset-[2px] rounded-full border-2 border-[var(--color-text-tertiary)] border-t-transparent motion-safe:animate-spin" />
|
||||
) : (
|
||||
<span
|
||||
className="relative grid h-[18px] w-[18px] place-items-center rounded-full"
|
||||
className={`relative grid place-items-center rounded-full ${isMobileBrowser ? 'h-[22px] w-[22px]' : 'h-5 w-5'}`}
|
||||
style={ringStyle}
|
||||
>
|
||||
<span className="absolute inset-[3px] rounded-full bg-[var(--color-surface-container-lowest)]" />
|
||||
<span className={`absolute inset-[3.5px] rounded-full transition-colors duration-150 ${
|
||||
detailsOpen
|
||||
? 'bg-[var(--color-surface-hover)]'
|
||||
: 'bg-[var(--color-surface-container-lowest)] group-hover:bg-[var(--color-surface-hover)]'
|
||||
}`} />
|
||||
<span
|
||||
className="relative h-[5px] w-[5px] rounded-full"
|
||||
className="relative h-1.5 w-1.5 rounded-full"
|
||||
style={{ backgroundColor: displayContext ? strokeColor : 'var(--color-text-tertiary)' }}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
<span className="font-mono text-[11px] font-semibold tabular-nums">
|
||||
{displayPercent}
|
||||
</span>
|
||||
<span className="sr-only">{displayPercent}</span>
|
||||
</button>
|
||||
|
||||
{!preferSheet && detailsOpen && popoverPosition && createPortal(
|
||||
|
||||
@@ -572,6 +572,54 @@ describe('Sidebar', () => {
|
||||
expect(screen.getByRole('button', { name: 'Collapse display' })).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('does not show a fold control when a project is at or below the collapse threshold', () => {
|
||||
const base = new Date('2026-05-15T10:00:00.000Z').getTime()
|
||||
useSessionStore.setState({
|
||||
sessions: [
|
||||
...Array.from({ length: 6 }, (_, index) => (
|
||||
makeSession(
|
||||
`alpha-${index + 1}`,
|
||||
`Alpha ${index + 1}`,
|
||||
'/workspace/alpha',
|
||||
new Date(base - index * 1000).toISOString(),
|
||||
)
|
||||
)),
|
||||
makeSession('beta-1', 'Beta only', '/workspace/beta', new Date(base - 7000).toISOString()),
|
||||
],
|
||||
})
|
||||
|
||||
render(<Sidebar />)
|
||||
|
||||
expect(screen.getByRole('button', { name: /Alpha 1/ })).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: /Alpha 6/ })).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: /Beta only/ })).toBeInTheDocument()
|
||||
expect(screen.queryByRole('button', { name: 'Expand display' })).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('button', { name: 'Collapse display' })).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('does not show a fold control after a short project is auto-expanded for history', () => {
|
||||
useSessionStore.setState({
|
||||
sessions: [
|
||||
makeSession('alpha-1', 'Alpha one', '/workspace/alpha', '2026-05-15T10:00:00.000Z'),
|
||||
makeSession('alpha-2', 'Alpha two', '/workspace/alpha', '2026-05-14T10:00:00.000Z'),
|
||||
],
|
||||
})
|
||||
|
||||
render(<Sidebar />)
|
||||
|
||||
const scroller = screen.getByTestId('sidebar-project-session-list-workspace-alpha')
|
||||
Object.defineProperties(scroller, {
|
||||
clientHeight: { configurable: true, value: 80 },
|
||||
scrollHeight: { configurable: true, value: 80 },
|
||||
})
|
||||
fireEvent.wheel(scroller, { deltaY: 20 })
|
||||
|
||||
expect(screen.getByRole('button', { name: /Alpha one/ })).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: /Alpha two/ })).toBeInTheDocument()
|
||||
expect(screen.queryByRole('button', { name: 'Expand display' })).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('button', { name: 'Collapse display' })).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('lets a manual session refresh supersede a stuck automatic refresh', async () => {
|
||||
fetchSessions.mockReturnValue(new Promise(() => {}))
|
||||
|
||||
|
||||
@@ -1236,6 +1236,7 @@ export function Sidebar({
|
||||
? []
|
||||
: getVisibleProjectSessions(project.sessions, sessionsExpanded, activeTabId)
|
||||
const hiddenCount = project.sessions.length - visibleItems.length
|
||||
const showSessionFoldControl = project.sessions.length > PROJECT_GROUP_VISIBLE_COUNT
|
||||
const groupIds = project.sessions.map((session) => session.id)
|
||||
const groupSelectedCount = groupIds.filter((id) => selectedSessionIds.has(id)).length
|
||||
const history = projectHistory[project.key]
|
||||
@@ -1444,7 +1445,7 @@ export function Sidebar({
|
||||
</div>
|
||||
))}
|
||||
</ProjectSessionList>
|
||||
{(hiddenCount > 0 || sessionsExpanded) && (
|
||||
{showSessionFoldControl && (
|
||||
<div className="mt-2 flex justify-start px-2.5">
|
||||
<button
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user