From 8773662b16dd2dc06d8ef06e4c801eca0bd70d05 Mon Sep 17 00:00:00 2001 From: Ben Senescu <44480372+bensenescu@users.noreply.github.com> Date: Tue, 12 May 2026 20:38:31 -0400 Subject: [PATCH] feat: unify multi select behavior across the app --- .../components/table/TableBulkActionBar.tsx | 129 +++++++++++++ .../features/domain/DomainOverviewPage.tsx | 1 + .../domain/components/DomainResultsCard.tsx | 79 ++++++-- .../domain/useDomainOverviewController.ts | 1 + .../page/KeywordResearchDesktopResults.tsx | 67 ++++++- .../page/KeywordResearchMobileResults.tsx | 66 ++++++- .../state/keywordControllerActions.ts | 38 ++-- .../rank-tracking/KeywordSuggestionStep.tsx | 92 ++++++++-- .../rank-tracking/RankTrackingTable.tsx | 95 +++++++--- .../rank-tracking/RankTrackingTableParts.tsx | 2 +- .../SavedKeywordsBulkActionBar.tsx | 171 +++++------------- 11 files changed, 530 insertions(+), 211 deletions(-) create mode 100644 src/client/components/table/TableBulkActionBar.tsx diff --git a/src/client/components/table/TableBulkActionBar.tsx b/src/client/components/table/TableBulkActionBar.tsx new file mode 100644 index 0000000..2890d0e --- /dev/null +++ b/src/client/components/table/TableBulkActionBar.tsx @@ -0,0 +1,129 @@ +import { ChevronDown, Download, Loader2, X } from "lucide-react"; +import type { ReactNode } from "react"; + +export function TableBulkActionBar({ + selectedCount, + selectedLabel = "selected", + actions, + onClear, + placement = "fixed", +}: { + selectedCount: number; + selectedLabel?: string; + actions: ReactNode; + onClear: () => void; + placement?: "fixed" | "inline"; +}) { + if (selectedCount === 0) return null; + + const wrapperClass = + placement === "fixed" + ? "pointer-events-none fixed inset-x-0 bottom-6 z-30 flex justify-center px-4" + : "flex justify-center"; + const toolbarClass = + placement === "fixed" + ? "pointer-events-auto flex items-stretch overflow-visible rounded-xl border border-base-content/15 bg-base-300/85 shadow-2xl backdrop-blur" + : "flex items-stretch overflow-visible rounded-xl border border-base-content/15 bg-base-200"; + + return ( +