From 4ac2c4323cb0469fa286dee0be003d7f29df0219 Mon Sep 17 00:00:00 2001 From: Arunavo Ray Date: Tue, 1 Sep 2026 10:07:35 +0530 Subject: [PATCH] fix(ui): hand over to the compact toolbar at lg, and let lists size themselves All three list pages switched from the compact toolbar to the full one at sm (640px), so a tablet in portrait got the desktop row with six controls and the search box squeezed down to its icon. The compact layout already carries every filter in its drawer, so the handover moves to lg (1024px) and tablets get a usable search box. Lists also sized themselves off the viewport with hard-coded pixel offsets - max-h-[calc(100dvh-231px)] and -276px. Those went stale the moment a toolbar changed height, which is what put a second scrollbar on the page next to the table's own. Both now flex into the space the toolbar leaves, so the visible row count follows the window instead of a fixed guess: the repository table shows 13 rows at 800px and 23 at 1400px, where it used to stop at the same count either way. Also drops the bottom status bar from both lists. Its count moves up into the empty left half of the filter row, and its live indicator was saying what the header's LIVE button already says. Claude-Session: https://claude.ai/code/session_01QRhZnpehnrVtnPRqJYDdVQ --- .../activity/ActivityNameCombobox.tsx | 54 ++++++--- src/components/organizations/Organization.tsx | 6 +- src/components/repositories/Repository.tsx | 11 +- .../repositories/RepositoryComboboxes.tsx | 2 +- .../repositories/RepositoryTable.tsx | 105 +++++------------- 5 files changed, 78 insertions(+), 100 deletions(-) diff --git a/src/components/activity/ActivityNameCombobox.tsx b/src/components/activity/ActivityNameCombobox.tsx index 77d24f2..01e2eaa 100644 --- a/src/components/activity/ActivityNameCombobox.tsx +++ b/src/components/activity/ActivityNameCombobox.tsx @@ -1,6 +1,5 @@ import * as React from "react"; -import { ChevronsUpDown, Check } from "lucide-react"; -import { Button } from "@/components/ui/button"; +import { ChevronDown, Check } from "lucide-react"; import { Command, CommandEmpty, @@ -14,15 +13,25 @@ import { PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; +import { selectTriggerClassName } from "@/components/ui/select"; import { cn } from "@/lib/utils"; type ActivityNameComboboxProps = { activities: any[]; value: string; onChange: (value: string) => void; + className?: string; }; -export function ActivityNameCombobox({ activities, value, onChange }: ActivityNameComboboxProps) { +/** Stays a combobox rather than a Select because the name list grows with the + * activity log and needs the search box. The trigger borrows the Select + * styling so it reads as the same control as the status and type dropdowns. */ +export function ActivityNameCombobox({ + activities, + value, + onChange, + className, +}: ActivityNameComboboxProps) { // Collect unique names from repositoryName and organizationName const names = React.useMemo(() => { const set = new Set(); @@ -34,25 +43,30 @@ export function ActivityNameCombobox({ activities, value, onChange }: ActivityNa }, [activities]); const [open, setOpen] = React.useState(false); + return ( + {/* The button stays inline: PopoverTrigger asChild clones its child to + attach the click handler and ref, which a wrapper component would + swallow unless it forwarded both. */} - + + - + @@ -66,7 +80,12 @@ export function ActivityNameCombobox({ activities, value, onChange }: ActivityNa setOpen(false); }} > - + All names {names.map((name) => ( @@ -78,7 +97,12 @@ export function ActivityNameCombobox({ activities, value, onChange }: ActivityNa setOpen(false); }} > - + {name} ))} diff --git a/src/components/organizations/Organization.tsx b/src/components/organizations/Organization.tsx index 12c15e3..ce23411 100644 --- a/src/components/organizations/Organization.tsx +++ b/src/components/organizations/Organization.tsx @@ -490,9 +490,9 @@ export function Organization() { return (
{/* Search and filters */} -
+
{/* Mobile: Search bar with filter button */} -
+
{/* Desktop: Original layout */} -
+
+
{/* Search and filters */}
{/* Mobile: Search bar with filter button */} -
+
{/* Desktop: Original layout */} -
+
0 && ( -
+
{selectedRepoIds.size} selected @@ -1430,7 +1430,7 @@ export default function Repository() { {/* Action buttons for mobile - only show when items are selected */} {selectedRepoIds.size > 0 && ( -
+
{selectedRepoIds.size} selected @@ -1552,7 +1552,6 @@ export default function Repository() { {value || emptyLabel} diff --git a/src/components/repositories/RepositoryTable.tsx b/src/components/repositories/RepositoryTable.tsx index f577157..868581a 100644 --- a/src/components/repositories/RepositoryTable.tsx +++ b/src/components/repositories/RepositoryTable.tsx @@ -65,7 +65,6 @@ export const REPOSITORY_SORT_OPTIONS = [ interface RepositoryTableProps { repositories: Repository[]; isLoading: boolean; - isLiveActive?: boolean; filter: FilterParams; setFilter: (filter: FilterParams) => void; onMirror: ({ repoId }: { repoId: string }) => Promise; @@ -108,7 +107,6 @@ function getTableSorting(sortOrder: string | undefined): SortingState { export default function RepositoryTable({ repositories, isLoading, - isLiveActive = false, filter, setFilter, onMirror, @@ -684,38 +682,35 @@ export default function RepositoryTable({ /* Sits above the table in both the loading and loaded states so the controls do not appear and disappear as data arrives. */ const filterRow = ( -
+
+ + {hasAnyFilter + ? `Showing ${visibleRepositories.length} of ${repositories.length} repositories` + : `${repositories.length} ${ + repositories.length === 1 ? "repository" : "repositories" + }`} + {hasAnyFilter && ( - <> - - Showing {visibleRepositories.length} of {repositories.length} repositories - - - + )}
-
+