From f00dd0fdf6f39a3a4605100193d08dfdccae160b Mon Sep 17 00:00:00 2001 From: Matthew Meszaros Date: Sat, 12 Sep 2026 07:15:59 -0700 Subject: [PATCH] feat: stop the contacts and campaign-leads table widening past its panel when a long company name arrives, by moving it off auto table layout, where one cell's nowrap text sets its column's min-content and pushes a horizontal scrollbar under the whole list, onto table-fixed with a declared width per column and clipping in every cell, Name the one auto column so it takes all the slack, each free-text column truncating into a native tooltip that only appears where the text was actually cut off, and the column set restaged per breakpoint so the sized columns never sum past the content panel at any width (#461) --- .../app/contacts/CategoryPicker.tsx | 15 +- .../components/app/contacts/ContactsTable.tsx | 143 +++++++++++------- web/src/lib/helper/titleWhenClipped.test.ts | 55 +++++++ web/src/lib/helper/titleWhenClipped.ts | 27 ++++ 4 files changed, 186 insertions(+), 54 deletions(-) create mode 100644 web/src/lib/helper/titleWhenClipped.test.ts create mode 100644 web/src/lib/helper/titleWhenClipped.ts diff --git a/web/src/components/app/contacts/CategoryPicker.tsx b/web/src/components/app/contacts/CategoryPicker.tsx index db44f6b2..1106a0d8 100644 --- a/web/src/components/app/contacts/CategoryPicker.tsx +++ b/web/src/components/app/contacts/CategoryPicker.tsx @@ -22,6 +22,7 @@ import toast from "react-hot-toast"; import { useUserProfile } from "@/hooks/context/user"; import useClickOutside from "@/hooks/useClickOutside"; import useFlipPlacement from "@/hooks/useFlipPlacement"; +import clippedTitle from "@/lib/helper/titleWhenClipped"; import useCreateCategory from "@/lib/api/hooks/app/categories/useCreateCategory"; import type Category from "@/lib/api/models/app/Category"; @@ -218,14 +219,19 @@ export function CategoryChip({ category, onRemove, compact, + clamp, }: { category: { id: string; title: string; color: string }; onRemove?: () => void; compact?: boolean; + // For a chip sharing a line with text that has to stay readable (a contact's + // name in the list): hold the label to one width at every breakpoint, and + // hand the rest to a tooltip. + clamp?: boolean; }) { return ( - {category.title} + + {category.title} + {onRemove && (