fix(workspace-cleanup): make the filter panel scrollable

The height cap sat on the ScrollArea Root, but the Radix viewport inside is
h-full — under an indefinite root height that collapses to auto, so the
viewport grew to full content height with nothing to scroll while the root
clipped at 420px. The last facet groups (Archived, and the tail of Workspace
status) were unreachable behind the footer.

Move the cap to the viewport, which is what the ScrollArea wrapper's
viewportClassName exists for. Adds a regression test that pins the cap to the
viewport; it fails against the previous markup.
This commit is contained in:
Brennan Benson
2026-08-14 15:51:43 -07:00
parent 9bb8836bb6
commit 676433c684
2 changed files with 51 additions and 31 deletions
@@ -6,39 +6,55 @@ import { WorkspaceCleanupFilterBar } from './workspace-cleanup-filter-bar'
afterEach(cleanup)
function renderFilterBar(facetPanelOpen = false): void {
render(
<WorkspaceCleanupFilterBar
facetProps={{
filters: createDefaultWorkspaceCleanupFilterState(),
counts: {
activity: 0,
size: 0,
status: 0,
agent: 0,
git: 0,
review: 0,
ticket: 0,
context: 0,
location: 0,
safety: 0
},
totalCount: 100,
options: { workspaceStatuses: [], hostIds: [], repos: [], reviewProviders: [] },
onPatch: vi.fn()
}}
facetPanelOpen={facetPanelOpen}
onFacetPanelOpenChange={vi.fn()}
activeFacetGroupCount={0}
matchedCount={100}
hasActiveFilters={false}
gitEvidence={{ pendingCount: 0, totalCount: 0 }}
onQueryChange={vi.fn()}
onClearFilters={vi.fn()}
/>
)
}
describe('WorkspaceCleanupFilterBar', () => {
it('keeps size measurement out of the browse controls', () => {
render(
<WorkspaceCleanupFilterBar
facetProps={{
filters: createDefaultWorkspaceCleanupFilterState(),
counts: {
activity: 0,
size: 0,
status: 0,
agent: 0,
git: 0,
review: 0,
ticket: 0,
context: 0,
location: 0,
safety: 0
},
totalCount: 100,
options: { workspaceStatuses: [], hostIds: [], repos: [], reviewProviders: [] },
onPatch: vi.fn()
}}
facetPanelOpen={false}
onFacetPanelOpenChange={vi.fn()}
activeFacetGroupCount={0}
matchedCount={100}
hasActiveFilters={false}
gitEvidence={{ pendingCount: 0, totalCount: 0 }}
onQueryChange={vi.fn()}
onClearFilters={vi.fn()}
/>
)
renderFilterBar()
expect(screen.queryByRole('button', { name: 'Scan' })).toBeNull()
})
it('caps the facet panel height on the scroll viewport so it stays scrollable', () => {
renderFilterBar(true)
// Why: on the ScrollArea Root the cap only clips — the h-full viewport
// collapses under an indefinite height and the last facet groups become
// unreachable behind the footer.
const viewport = document.querySelector('[data-slot="scroll-area-viewport"]')
const root = document.querySelector('[data-slot="scroll-area"]')
expect(viewport?.className).toContain('max-h-[420px]')
expect(root?.className).not.toContain('max-h-')
})
})
@@ -68,7 +68,11 @@ export function WorkspaceCleanupFilterBar({
</Button>
</PopoverTrigger>
<PopoverContent align="end" sideOffset={6} className="w-[320px] p-0">
<ScrollArea className="max-h-[420px]">
{/* Why: the cap must sit on the scroll viewport. On the Root it only
clips — the viewport is h-full, which collapses to auto under an
indefinite height, so the panel grew past the cap unscrollably and
hid the last facet groups behind the footer. */}
<ScrollArea viewportClassName="max-h-[420px]">
<WorkspaceCleanupLifecycleFacets {...facetProps} />
<WorkspaceCleanupGitReviewFacets {...facetProps} />
</ScrollArea>