Skip to content

Commit e14a3a5

Browse files
waleedlatif1claude
andauthored
fix(tables): suppress phantom rows on sort, center gutter numbers, stop select-all viewport jump (#4445)
* fix(tables): suppress phantom rows on sort, center gutter numbers, stop select-all viewport jump * fix(tables): suppress scroll on Ctrl+A select-all Cmd/Ctrl+A duplicates the select-all logic but missed the suppressFocusScrollRef flag, so the keyboard path still triggered the viewport jump. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 51addc5 commit e14a3a5

1 file changed

Lines changed: 40 additions & 26 deletions

File tree

  • apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table

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

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ export function Table({
173173
const containerRef = useRef<HTMLDivElement>(null)
174174
const scrollRef = useRef<HTMLDivElement>(null)
175175
const isDraggingRef = useRef(false)
176+
const suppressFocusScrollRef = useRef(false)
176177

177178
const {
178179
tableData,
@@ -796,6 +797,7 @@ export function Table({
796797
if (rws.length === 0 || currentCols.length === 0) return
797798
setEditingCell(null)
798799
setCheckedRows((prev) => (prev.size === 0 ? prev : EMPTY_CHECKED_ROWS))
800+
suppressFocusScrollRef.current = true
799801
setSelectionAnchor({ rowIndex: 0, colIndex: 0 })
800802
setSelectionFocus({
801803
rowIndex: maxPositionRef.current,
@@ -1155,6 +1157,10 @@ export function Table({
11551157

11561158
useEffect(() => {
11571159
if (isColumnSelection) return
1160+
if (suppressFocusScrollRef.current) {
1161+
suppressFocusScrollRef.current = false
1162+
return
1163+
}
11581164
const target = selectionFocus ?? selectionAnchor
11591165
if (!target) return
11601166
const { rowIndex, colIndex } = target
@@ -1296,6 +1302,7 @@ export function Table({
12961302
const rws = rowsRef.current
12971303
const currentCols = columnsRef.current
12981304
if (rws.length > 0 && currentCols.length > 0) {
1305+
suppressFocusScrollRef.current = true
12991306
setEditingCell(null)
13001307
setCheckedRows((prev) => (prev.size === 0 ? prev : EMPTY_CHECKED_ROWS))
13011308
setSelectionAnchor({ rowIndex: 0, colIndex: 0 })
@@ -2685,7 +2692,10 @@ export function Table({
26852692
<>
26862693
{rows.map((row, index) => {
26872694
const prevPosition = index > 0 ? rows[index - 1].position : -1
2688-
const gapCount = queryOptions.filter ? 0 : row.position - prevPosition - 1
2695+
const gapCount =
2696+
queryOptions.filter || queryOptions.sort
2697+
? 0
2698+
: row.position - prevPosition - 1
26892699
return (
26902700
<React.Fragment key={row.id}>
26912701
{gapCount > 0 && (
@@ -2938,7 +2948,7 @@ export function Table({
29382948
}
29392949

29402950
const GAP_ROW_LIMIT = 200
2941-
const GAP_CHECKBOX_CLASS = cn(CELL_CHECKBOX, 'group/checkbox cursor-pointer text-center')
2951+
const GAP_CHECKBOX_CLASS = cn(CELL_CHECKBOX, 'cursor-pointer')
29422952

29432953
interface PositionGapRowsProps {
29442954
count: number
@@ -2975,28 +2985,32 @@ const PositionGapRows = React.memo(
29752985
const isGapChecked = checkedRows.has(position)
29762986
return (
29772987
<tr key={`gap-${position}`}>
2978-
<td
2979-
className={GAP_CHECKBOX_CLASS}
2980-
onMouseDown={(e) => {
2981-
if (e.button !== 0) return
2982-
onRowToggle(position, e.shiftKey)
2983-
}}
2984-
>
2985-
<span
2986-
className={cn(
2987-
'text-[var(--text-tertiary)] text-xs tabular-nums',
2988-
isGapChecked ? 'hidden' : 'block group-hover/checkbox:hidden'
2989-
)}
2990-
>
2991-
{position + 1}
2992-
</span>
2993-
<div
2994-
className={cn(
2995-
'items-center justify-center',
2996-
isGapChecked ? 'flex' : 'hidden group-hover/checkbox:flex'
2997-
)}
2998-
>
2999-
<Checkbox size='sm' checked={isGapChecked} className='pointer-events-none' />
2988+
<td className={GAP_CHECKBOX_CLASS}>
2989+
<div className='flex items-center justify-center gap-1'>
2990+
<div
2991+
className='group/checkbox flex h-[20px] w-[24px] shrink-0 items-center justify-center'
2992+
onMouseDown={(e) => {
2993+
if (e.button !== 0) return
2994+
onRowToggle(position, e.shiftKey)
2995+
}}
2996+
>
2997+
<span
2998+
className={cn(
2999+
'text-[var(--text-tertiary)] text-xs tabular-nums',
3000+
isGapChecked ? 'hidden' : 'block group-hover/checkbox:hidden'
3001+
)}
3002+
>
3003+
{position + 1}
3004+
</span>
3005+
<div
3006+
className={cn(
3007+
'items-center justify-center',
3008+
isGapChecked ? 'flex' : 'hidden group-hover/checkbox:flex'
3009+
)}
3010+
>
3011+
<Checkbox size='sm' checked={isGapChecked} className='pointer-events-none' />
3012+
</div>
3013+
</div>
30003014
</div>
30013015
</td>
30023016
{columns.map((col, colIndex) => {
@@ -3238,7 +3252,7 @@ const DataRow = React.memo(function DataRow({
32383252
return (
32393253
<tr onContextMenu={(e) => onContextMenu(e, row)}>
32403254
<td className={cn(CELL_CHECKBOX, 'cursor-pointer')}>
3241-
<div className='flex items-center justify-between gap-1'>
3255+
<div className='flex items-center justify-center gap-1'>
32423256
<div
32433257
className='group/checkbox flex h-[20px] w-[24px] shrink-0 items-center justify-center'
32443258
onMouseDown={(e) => {
@@ -3268,7 +3282,7 @@ const DataRow = React.memo(function DataRow({
32683282
type='button'
32693283
aria-label={runningCount > 0 ? `Stop ${runningCount} running` : 'Run row'}
32703284
title={runningCount > 0 ? `Stop ${runningCount} running` : 'Run row'}
3271-
className='flex h-[20px] w-[20px] shrink-0 items-center justify-center rounded text-[var(--text-primary)] transition-colors hover-hover:bg-[var(--surface-2)]'
3285+
className='ml-auto flex h-[20px] w-[20px] shrink-0 items-center justify-center rounded text-[var(--text-primary)] transition-colors hover-hover:bg-[var(--surface-2)]'
32723286
onClick={() => {
32733287
if (runningCount > 0) {
32743288
onStopRow(row.id)

0 commit comments

Comments
 (0)