From ebfec0df36033914faeae789bfeb3d2ecec8b10b Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Thu, 14 May 2026 22:31:40 +0800 Subject: [PATCH] Improve click targets on property actions (#45936) ## Context When opening the logs detail panel, some of the fields can be clicked to add them as a filter. However the existing UX is that the clickable part is just the text which makes it target small image Am opting the following: - Make the whole row clickable - Make all rows clickable with the main action being "Copy {column}" - Only filterable columns will have the option to "Add as filter" ### After image image ## Summary by CodeRabbit * **New Features** * Row actions now consistently wrap rows and show a filter icon next to the label when a resolved filter is available; copy menu displays "Copy {label}". * **Style** * Standardized icon sizes and adjusted dropdown/row spacing; simplified text wrap/truncate behavior for field values; minor status text color refinement. * **Bug Fixes** * Dropdown row-action rendering made more robust to ensure menu wrappers render reliably. [![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45936) --- .../components/shared/DetailRow.tsx | 64 ++++++------------- .../components/shared/FieldValue.tsx | 3 +- .../components/DataTableSheetContent.tsx | 1 + .../ui/DataTable/DataTable.utils.ts | 4 +- .../DataTableColumnStatusCode.tsx | 1 - .../ui/DataTable/DataTableSheetRowAction.tsx | 44 +++++++------ 6 files changed, 48 insertions(+), 69 deletions(-) diff --git a/apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/shared/DetailRow.tsx b/apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/shared/DetailRow.tsx index 0802d7abec..4a651e4abc 100644 --- a/apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/shared/DetailRow.tsx +++ b/apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/shared/DetailRow.tsx @@ -1,4 +1,5 @@ import { Table } from '@tanstack/react-table' +import { Filter } from 'lucide-react' import { ReactNode } from 'react' import { cn, Skeleton } from 'ui' @@ -11,7 +12,7 @@ interface DetailRowProps { filterId?: string filterValue?: string | number // eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches ServiceFlow types convention - filterFields?: DataTableFilterField[] + filterFields: DataTableFilterField[] // eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches ServiceFlow types convention table?: Table isLoading?: boolean @@ -61,58 +62,31 @@ export const DetailRow = ({ ) : isEmpty ? ( - ) : typeof value === 'string' || typeof value === 'number' ? ( - - {value} - ) : ( value ) const rowClass = cn( - 'flex items-start justify-between gap-3 px-4', + 'flex items-start justify-between gap-x-10 px-4', wrap ? 'min-h-9 py-2' : 'h-9 items-center' ) - const isStringValue = typeof value === 'string' || typeof value === 'number' - - if (isFilterable && resolvedFilterValue !== undefined && isStringValue) { - return ( - - {labelEl} - {valueEl} - - ) - } - return ( -
- {labelEl} - {isFilterable && resolvedFilterValue !== undefined && !isStringValue ? ( - - {valueEl} - - ) : ( - valueEl - )} -
+ +
+ {labelEl} + {isFilterable && resolvedFilterValue !== undefined && ( + + )} +
+ {valueEl} +
) } diff --git a/apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/shared/FieldValue.tsx b/apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/shared/FieldValue.tsx index d2d695a5e0..6d0b0c2b0d 100644 --- a/apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/shared/FieldValue.tsx +++ b/apps/studio/components/interfaces/UnifiedLogs/ServiceFlow/components/shared/FieldValue.tsx @@ -29,8 +29,7 @@ export const FieldValue = ({ config, value, wrap }: FieldValueProps): ReactNode {value} diff --git a/apps/studio/components/interfaces/UnifiedLogs/components/DataTableSheetContent.tsx b/apps/studio/components/interfaces/UnifiedLogs/components/DataTableSheetContent.tsx index 2e66d00ef2..6d80888fbe 100644 --- a/apps/studio/components/interfaces/UnifiedLogs/components/DataTableSheetContent.tsx +++ b/apps/studio/components/interfaces/UnifiedLogs/components/DataTableSheetContent.tsx @@ -85,6 +85,7 @@ export function DataTableSheetContent({ 'flex gap-4 my-1 py-1 text-sm justify-between items-center w-full', field.className )} + label={field.label} >
{field.label}
diff --git a/apps/studio/components/ui/DataTable/DataTable.utils.ts b/apps/studio/components/ui/DataTable/DataTable.utils.ts index 804e3b6dbf..deec18fab9 100644 --- a/apps/studio/components/ui/DataTable/DataTable.utils.ts +++ b/apps/studio/components/ui/DataTable/DataTable.utils.ts @@ -99,7 +99,7 @@ export function getStatusColor(value?: number | string): Record<'text' | 'bg' | case '2': case 'success': return { - text: 'text-foreground-lighter', + text: 'text-foreground', bg: '', border: 'border-green-200 dark:border-green-800', } @@ -120,7 +120,7 @@ export function getStatusColor(value?: number | string): Record<'text' | 'bg' | } default: return { - text: 'text-foreground-lighter', + text: 'text-foreground', bg: '', border: '', } diff --git a/apps/studio/components/ui/DataTable/DataTableColumn/DataTableColumnStatusCode.tsx b/apps/studio/components/ui/DataTable/DataTableColumn/DataTableColumnStatusCode.tsx index badd8d7d4b..6fdcbf4a67 100644 --- a/apps/studio/components/ui/DataTable/DataTableColumn/DataTableColumnStatusCode.tsx +++ b/apps/studio/components/ui/DataTable/DataTableColumn/DataTableColumnStatusCode.tsx @@ -21,7 +21,6 @@ export const DataTableColumnStatusCode = ({
, > extends ComponentPropsWithRef { - fieldValue: TFields['value'] + fieldValue?: TFields['value'] filterFields: TFields[] value: string | number table: Table + label?: string } export function DataTableSheetRowAction>({ @@ -41,14 +42,13 @@ export function DataTableSheetRowAction) { const { copy, isCopied } = useCopyToClipboard() - const field = filterFields.find((field) => field.value === fieldValue) - const column = table.getColumn(fieldValue.toString()) - - if (!field || !column) return null + const field = !!fieldValue ? filterFields.find((f) => f.value === fieldValue) : undefined + const column = !!fieldValue ? table.getColumn(fieldValue.toString()) : undefined function renderOptions() { if (!field) return null @@ -66,7 +66,7 @@ export function DataTableSheetRowAction - + Add as filter for {column?.id} ) @@ -76,7 +76,7 @@ export function DataTableSheetRowAction column?.setFilterValue(value)} className="flex items-center gap-2" > - + Add as filter for {column?.id} ) @@ -88,7 +88,7 @@ export function DataTableSheetRowAction {/* FIXME: change icon as it is not clear */} - + Less or equal than {/* FIXME: change icon as it is not clear */} - + Greater or equal than column?.setFilterValue([value])} className="flex items-center gap-2" > - + Equal to @@ -116,7 +116,7 @@ export function DataTableSheetRowAction column?.setFilterValue([date])} className="flex items-center gap-2" > - + Exact timestamp - + Same hour - + Same day @@ -174,15 +174,21 @@ export function DataTableSheetRowAction ) : null} - - {renderOptions()} - + + + {!!field && !!column && ( + <> + {renderOptions()} + + + )} + copy(String(value), { timeout: 1000 })} className="flex items-center gap-2" > - - Copy value + + Copy {label}