Skip to content

Commit 837f035

Browse files
committed
fix(table): fix table boolean, add dynamic row number col size, fix style for search and replace
1 parent 6cb7796 commit 837f035

8 files changed

Lines changed: 86 additions & 86 deletions

File tree

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/column-config-sidebar/column-config-sidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ function ColumnConfigBody({
153153

154154
return (
155155
<div className='flex h-full flex-col'>
156-
<div className='flex items-center justify-between border-[var(--border)] border-b px-3 py-2'>
156+
<div className='flex items-center justify-between border-[var(--border)] border-b px-3 py-[8.5px]'>
157157
<h2 className='font-medium text-[var(--text-primary)] text-small'>Configure column</h2>
158158
<Button
159159
variant='ghost'

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/cells/cell-render.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,11 @@ export function CellRender({ kind, isEditing }: CellRenderProps): React.ReactEle
204204
case 'boolean':
205205
return (
206206
<div
207-
className={cn('flex min-h-[20px] items-center justify-center', isEditing && 'invisible')}
207+
data-boolean-cell-toggle
208+
className={cn(
209+
'flex min-h-[20px] w-full items-center justify-center',
210+
isEditing && 'invisible'
211+
)}
208212
>
209213
<Checkbox size='sm' checked={kind.checked} className='pointer-events-none' />
210214
</div>

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/table-grid.tsx

Lines changed: 41 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -92,25 +92,18 @@ function rowSelectionCoversAll(sel: RowSelection, rows: TableRowType[]): boolean
9292

9393
const COL_WIDTH_MIN = 80
9494
const COL_WIDTH_AUTO_FIT_MAX = 1000
95-
// Wide enough to host the row-number + per-row run button side by side.
96-
// Single-digit row numbers (rows 1–9) and multi-digit need to render with
97-
// the play button at the same x-position so the column doesn't reflow
98-
// row-by-row.
99-
//
100-
// Bucketed by the table's plan-derived `maxRows`, not the live count: a small
101-
// table sized for ≤9,999 always renders the narrow gutter; an enterprise
102-
// table sized up to 9,999,999 always renders the wide one. The gutter never
103-
// changes width as rows are added.
104-
//
105-
// Tables without workflow columns drop the per-row run button (~28px), so
106-
// the gutter shrinks accordingly.
107-
const CHECKBOX_COL_WIDTH_SMALL_WITH_RUN = 48
108-
const CHECKBOX_COL_WIDTH_SMALL_NUMBER_ONLY = 32
109-
const CHECKBOX_COL_WIDTH_LARGE_WITH_RUN = 68
110-
const CHECKBOX_COL_WIDTH_LARGE_NUMBER_ONLY = 52
111-
/** Bucket boundary: tables sized for >9,999 rows get the wide gutter. */
112-
const LARGE_ROW_NUMBER_THRESHOLD = 10000
11395
const ADD_COL_WIDTH = 120
96+
97+
/** Returns sticky row-number column dimensions sized to the digit count of `maxRows`. */
98+
function checkboxColLayout(
99+
maxRows: number,
100+
hasWorkflowCols: boolean
101+
): { colWidth: number; numDivWidth: number } {
102+
const digits = maxRows > 0 ? Math.floor(Math.log10(maxRows)) + 1 : 1
103+
const numDivWidth = Math.max(20, digits * 8 + 4)
104+
const colWidth = Math.max(32, numDivWidth + 8) + (hasWorkflowCols ? 16 : 0)
105+
return { colWidth, numDivWidth }
106+
}
114107
const SKELETON_COL_COUNT = 4
115108
const SKELETON_ROW_COUNT = 10
116109
const ROW_HEIGHT_ESTIMATE = 35
@@ -128,7 +121,7 @@ const CELL_HEADER_CHECKBOX =
128121
const CELL_CONTENT =
129122
'relative flex h-[22px] min-w-0 items-center overflow-clip text-ellipsis whitespace-nowrap text-small'
130123
const SELECTION_OVERLAY =
131-
'pointer-events-none absolute -top-px -right-px -bottom-px -left-px z-[5] border-[2px] border-[var(--selection)]'
124+
'pointer-events-none absolute -top-px -right-px -bottom-px z-[5] border-[2px] border-[var(--selection)]'
132125

133126
/**
134127
* Snapshot of grid selection state the wrapper needs to render `<TableActionBar>`.
@@ -452,22 +445,10 @@ export function TableGrid({
452445
}, [columns, columnOrder, tableWorkflowGroups])
453446

454447
const hasWorkflowColumns = columns.some((c) => !!c.workflowGroupId)
455-
/**
456-
* The sticky left column hosts the row number / checkbox always, plus a
457-
* per-row run button only when the table has workflow columns. Width is
458-
* picked from the table's plan-derived `maxRows` so a free-tier table
459-
* (≤9,999) gets the narrow gutter and an enterprise table (up to
460-
* 9,999,999) gets the wide one. Bucketed, not continuous, so the gutter
461-
* never reflows as rows are added.
462-
*/
463-
const isLargeRowCountTable = (tableData?.maxRows ?? 0) >= LARGE_ROW_NUMBER_THRESHOLD
464-
const checkboxColWidth = isLargeRowCountTable
465-
? hasWorkflowColumns
466-
? CHECKBOX_COL_WIDTH_LARGE_WITH_RUN
467-
: CHECKBOX_COL_WIDTH_LARGE_NUMBER_ONLY
468-
: hasWorkflowColumns
469-
? CHECKBOX_COL_WIDTH_SMALL_WITH_RUN
470-
: CHECKBOX_COL_WIDTH_SMALL_NUMBER_ONLY
448+
const { colWidth: checkboxColWidth, numDivWidth } = checkboxColLayout(
449+
tableData?.maxRows ?? 0,
450+
hasWorkflowColumns
451+
)
471452

472453
const headerGroups = useMemo(
473454
() => buildHeaderGroups(displayColumns, tableWorkflowGroups),
@@ -3053,7 +3034,7 @@ export function TableGrid({
30533034
onRowToggle={handleRowToggle}
30543035
runningCount={runningByRowId.get(row.id) ?? 0}
30553036
hasWorkflowColumns={hasWorkflowColumns}
3056-
isLargeRowCountTable={isLargeRowCountTable}
3037+
numDivWidth={numDivWidth}
30573038
onStopRow={onStopRow}
30583039
onRunRow={handleRunRow}
30593040
workflowGroups={tableWorkflowGroups}
@@ -3178,8 +3159,8 @@ interface DataRowProps {
31783159
runningCount: number
31793160
/** Whether the table has at least one workflow column — controls whether a run/stop icon is rendered. */
31803161
hasWorkflowColumns: boolean
3181-
/** True for tables sized for >9,999 rows; widens the row-number slot to fit 5–7 digit numbers. */
3182-
isLargeRowCountTable: boolean
3162+
/** Width of the row-number inner div in px, derived from the table's maxRows digit count. */
3163+
numDivWidth: number
31833164
onStopRow: (rowId: string) => void
31843165
onRunRow: (rowId: string) => void
31853166
/**
@@ -3239,7 +3220,7 @@ function dataRowPropsAreEqual(prev: DataRowProps, next: DataRowProps): boolean {
32393220
prev.onRowToggle !== next.onRowToggle ||
32403221
prev.runningCount !== next.runningCount ||
32413222
prev.hasWorkflowColumns !== next.hasWorkflowColumns ||
3242-
prev.isLargeRowCountTable !== next.isLargeRowCountTable ||
3223+
prev.numDivWidth !== next.numDivWidth ||
32433224
prev.onStopRow !== next.onStopRow ||
32443225
prev.onRunRow !== next.onRunRow ||
32453226
prev.workflowGroups !== next.workflowGroups
@@ -3281,7 +3262,7 @@ const DataRow = React.memo(function DataRow({
32813262
onRowToggle,
32823263
runningCount,
32833264
hasWorkflowColumns,
3284-
isLargeRowCountTable,
3265+
numDivWidth,
32853266
onStopRow,
32863267
onRunRow,
32873268
workflowGroups,
@@ -3313,20 +3294,23 @@ const DataRow = React.memo(function DataRow({
33133294
return (
33143295
<tr onContextMenu={(e) => onContextMenu(e, row)}>
33153296
<td className={cn(CELL_CHECKBOX, 'cursor-pointer')}>
3316-
<div className='flex items-center justify-between gap-1'>
3297+
<div
3298+
className={cn(
3299+
'flex items-center gap-1',
3300+
hasWorkflowColumns ? 'justify-between' : 'justify-center'
3301+
)}
3302+
>
33173303
<div
3318-
className={cn(
3319-
'group/checkbox flex h-[20px] shrink-0 items-center justify-end',
3320-
isLargeRowCountTable ? 'w-[40px]' : 'w-[20px]'
3321-
)}
3304+
className='group/checkbox flex h-[20px] shrink-0 items-center justify-center'
3305+
style={{ width: numDivWidth }}
33223306
onMouseDown={(e) => {
33233307
if (e.button !== 0) return
33243308
onRowToggle(rowIndex, e.shiftKey)
33253309
}}
33263310
>
33273311
<span
33283312
className={cn(
3329-
'text-right text-[var(--text-tertiary)] text-xs tabular-nums',
3313+
'text-center text-[var(--text-tertiary)] text-xs tabular-nums',
33303314
isRowSelected ? 'hidden' : 'block group-hover/checkbox:hidden'
33313315
)}
33323316
>
@@ -3409,7 +3393,8 @@ const DataRow = React.memo(function DataRow({
34093393
{isHighlighted && (isMultiCell || isRowChecked) && (
34103394
<div
34113395
className={cn(
3412-
'-top-px -right-px -bottom-px -left-px pointer-events-none absolute z-[4]',
3396+
'-top-px -right-px -bottom-px pointer-events-none absolute z-[4]',
3397+
colIndex === 0 ? 'left-0' : '-left-px',
34133398
SELECTION_TINT_BG,
34143399
isFirstRow && isTopEdge && 'top-0',
34153400
isTopEdge && 'border-t border-t-[var(--selection)]',
@@ -3419,7 +3404,15 @@ const DataRow = React.memo(function DataRow({
34193404
)}
34203405
/>
34213406
)}
3422-
{isAnchor && <div className={cn(SELECTION_OVERLAY, isFirstRow && 'top-0')} />}
3407+
{isAnchor && (
3408+
<div
3409+
className={cn(
3410+
SELECTION_OVERLAY,
3411+
colIndex === 0 ? 'left-0' : '-left-px',
3412+
isFirstRow && 'top-0'
3413+
)}
3414+
/>
3415+
)}
34233416
<div className={CELL_CONTENT}>
34243417
<CellContent
34253418
value={

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/workflow-sidebar/workflow-sidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ function WorkflowSidebarBody({
678678

679679
return (
680680
<div className='flex h-full flex-col'>
681-
<div className='flex items-center justify-between border-[var(--border)] border-b px-3 py-2'>
681+
<div className='flex items-center justify-between border-[var(--border)] border-b px-3 py-[8.5px]'>
682682
<h2 className='font-medium text-[var(--text-primary)] text-small'>
683683
{titleByMode[config.mode]}
684684
</h2>

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ const FOLDER_OVERRIDES: SelectorOverrides = {
7272
},
7373
}
7474

75-
const WORKFLOW_SEARCH_CURRENT_MATCH_CLASS = 'rounded-md bg-orange-400 px-1 py-0.5'
75+
const WORKFLOW_SEARCH_HIGHLIGHT_CLASS =
76+
'rounded-sm bg-orange-400 shadow-[3px_0_0_#fb923c,-3px_0_0_#fb923c]'
7677

7778
/**
7879
* Interface for wand control handlers exposed by sub-block inputs
@@ -253,7 +254,7 @@ const renderLabel = (
253254
<div className='flex items-center justify-between gap-1.5 pl-0.5'>
254255
<Label className='flex items-baseline gap-1.5 whitespace-nowrap'>
255256
{isSearchHighlighted ? (
256-
<mark className={WORKFLOW_SEARCH_CURRENT_MATCH_CLASS}>{config.title}</mark>
257+
<mark className={WORKFLOW_SEARCH_HIGHLIGHT_CLASS}>{config.title}</mark>
257258
) : (
258259
config.title
259260
)}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/subflow-editor/subflow-editor.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import type { ConnectedBlock } from '../../hooks/use-block-connections'
1111
import { useSubflowEditor } from '../../hooks/use-subflow-editor'
1212
import { ConnectionBlocks } from '../connection-blocks'
1313

14-
const WORKFLOW_SEARCH_CURRENT_MATCH_CLASS = 'rounded-md bg-orange-400 px-1 py-0.5'
14+
const WORKFLOW_SEARCH_HIGHLIGHT_CLASS =
15+
'rounded-sm bg-orange-400 shadow-[3px_0_0_#fb923c,-3px_0_0_#fb923c]'
1516

1617
interface SubflowEditorProps {
1718
currentBlock: BlockState
@@ -93,7 +94,7 @@ export function SubflowEditor({
9394
>
9495
<Label className='mb-[6.5px] block pl-0.5 font-medium text-[var(--text-primary)] text-small'>
9596
{isTypeHighlighted ? (
96-
<mark className={WORKFLOW_SEARCH_CURRENT_MATCH_CLASS}>
97+
<mark className={WORKFLOW_SEARCH_HIGHLIGHT_CLASS}>
9798
{currentBlock.type === 'loop' ? 'Loop Type' : 'Parallel Type'}
9899
</mark>
99100
) : currentBlock.type === 'loop' ? (
@@ -128,7 +129,7 @@ export function SubflowEditor({
128129
>
129130
<Label className='mb-[6.5px] block pl-0.5 font-medium text-[var(--text-primary)] text-small'>
130131
{isConfigHighlighted ? (
131-
<mark className={WORKFLOW_SEARCH_CURRENT_MATCH_CLASS}>
132+
<mark className={WORKFLOW_SEARCH_HIGHLIGHT_CLASS}>
132133
{isCountMode
133134
? `${currentBlock.type === 'loop' ? 'Loop' : 'Parallel'} Iterations`
134135
: isConditionMode

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/search-replace/replacement-controls.tsx

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,30 +32,28 @@ export function ReplacementControls({
3232
}: ReplacementControlsProps) {
3333
return (
3434
<div className='space-y-2'>
35-
<div className='space-y-1.5'>
36-
{usesResourceReplacement ? (
37-
<Combobox
38-
options={compatibleResourceOptions.map((option) => ({
39-
label: option.label,
40-
value: option.value,
41-
}))}
42-
value={replacement}
43-
onChange={onReplacementChange}
44-
placeholder='Choose replacement...'
45-
searchable
46-
searchPlaceholder='Search resources...'
47-
emptyMessage='No valid replacements available'
48-
disabled={disabled || compatibleResourceOptions.length === 0}
49-
/>
50-
) : (
51-
<Input
52-
value={replacement}
53-
placeholder='Replace'
54-
disabled={disabled}
55-
onChange={(event) => onReplacementChange(event.target.value)}
56-
/>
57-
)}
58-
</div>
35+
{usesResourceReplacement ? (
36+
<Combobox
37+
options={compatibleResourceOptions.map((option) => ({
38+
label: option.label,
39+
value: option.value,
40+
}))}
41+
value={replacement}
42+
onChange={onReplacementChange}
43+
placeholder='Choose replacement...'
44+
searchable
45+
searchPlaceholder='Search resources...'
46+
emptyMessage='No valid replacements available'
47+
disabled={disabled || compatibleResourceOptions.length === 0}
48+
/>
49+
) : (
50+
<Input
51+
value={replacement}
52+
placeholder='Replace'
53+
disabled={disabled}
54+
onChange={(event) => onReplacementChange(event.target.value)}
55+
/>
56+
)}
5957

6058
<div className='flex items-center justify-between gap-2'>
6159
<span className='text-[var(--text-muted)] text-xs'>

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/search-replace/workflow-search-replace.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ export function WorkflowSearchReplace() {
481481
onMouseDown={handleMouseDown}
482482
>
483483
<div className='flex min-w-0 items-center'>
484-
<span className='truncate font-medium text-[var(--text-primary)] text-sm'>
484+
<span className='truncate font-medium text-[13px] text-[var(--text-primary)]'>
485485
Search and replace
486486
</span>
487487
</div>
@@ -490,8 +490,8 @@ export function WorkflowSearchReplace() {
490490
onMouseDown={(event) => event.stopPropagation()}
491491
>
492492
<span className='text-[var(--text-muted)] text-xs'>{matchCountLabel}</span>
493-
<Button variant='ghost' className='!p-1.5 -m-1.5' onClick={close}>
494-
<X className='h-[16px] w-[16px]' />
493+
<Button variant='ghost' className='h-[26px] w-[26px] p-0' onClick={close}>
494+
<X className='h-[14px] w-[14px]' />
495495
</Button>
496496
</div>
497497
</div>
@@ -504,7 +504,10 @@ export function WorkflowSearchReplace() {
504504
onClick={() => setIsReplaceExpanded((expanded) => !expanded)}
505505
>
506506
<ChevronRight
507-
className={cn('h-4 w-4 transition-transform', isReplaceExpanded && 'rotate-90')}
507+
className={cn(
508+
'h-[14px] w-[14px] text-[var(--text-icon)] transition-transform',
509+
isReplaceExpanded && 'rotate-90'
510+
)}
508511
/>
509512
</Button>
510513
<Input
@@ -524,15 +527,15 @@ export function WorkflowSearchReplace() {
524527
disabled={hydratedMatches.length === 0}
525528
onClick={() => handleMoveActiveMatch(-1)}
526529
>
527-
<ChevronUp className='h-4 w-4' />
530+
<ChevronUp className='h-[14px] w-[14px] text-[var(--text-icon)]' />
528531
</Button>
529532
<Button
530533
variant='ghost'
531534
className='h-8 w-8 p-0'
532535
disabled={hydratedMatches.length === 0}
533536
onClick={() => handleMoveActiveMatch(1)}
534537
>
535-
<ChevronDown className='h-4 w-4' />
538+
<ChevronDown className='h-[14px] w-[14px] text-[var(--text-icon)]' />
536539
</Button>
537540

538541
{isReplaceExpanded && (

0 commit comments

Comments
 (0)