LinkDesk/frontend/docs/shift-click-selection-fix.md

132 lines
4.3 KiB
Markdown

# Shift+Click Selection Visual Feedback Fix
**Date:** 2025-11-26
**Issue:** When using Shift+click for range selection and select-all checkbox, selected rows were not showing the visual highlight (background color change)
## Problem
The TasksDataTable component's selection state was not properly synchronized with TanStack Table's internal state, causing `row.getIsSelected()` to return incorrect values and preventing the visual feedback (`bg-muted/50` class) from being applied.
## Root Cause
The issue was with how TanStack Table's state management works. The table needs to read selection state from a reactive source. The configuration uses a getter:
```typescript
state: {
get rowSelection() {
return rowSelection.value
}
}
```
This getter ensures that whenever `rowSelection.value` changes, the table's internal state updates and `row.getIsSelected()` returns the correct value. The key is that we must update `rowSelection.value` directly, not try to use non-existent table methods.
## Solution
The correct approach is to update `rowSelection.value` directly. The table configuration's `state.rowSelection` getter ensures the table reads from our reactive ref:
### 1. Shift+Click Range Selection
```typescript
// CORRECT - Update ref directly
const newSelection: Record<string, boolean> = {}
for (let i = start; i <= end; i++) {
const id = String(props.tasks[i].id)
newSelection[id] = true
}
rowSelection.value = newSelection
```
### 2. Ctrl+Click Toggle
```typescript
// CORRECT - Update ref directly
const newSelection = { ...rowSelection.value }
if (newSelection[taskId]) {
delete newSelection[taskId]
} else {
newSelection[taskId] = true
}
rowSelection.value = newSelection
```
### 3. Single Click
```typescript
// CORRECT - Update ref directly
rowSelection.value = { [taskId]: true }
```
### 4. Context Menu
```typescript
// CORRECT - Update ref directly
if (!rowSelection.value[taskId]) {
const newSelection = { ...rowSelection.value }
newSelection[taskId] = true
rowSelection.value = newSelection
}
```
## Changes Made
**File:** `frontend/src/components/task/TasksDataTable.vue`
1. **handleRowClick function:**
- All selection updates now directly modify `rowSelection.value`
- Shift+click: Creates new selection object and assigns to `rowSelection.value`
- Ctrl+click: Creates new selection object with toggle logic and assigns to `rowSelection.value`
- Single click: Assigns new object with single selection to `rowSelection.value`
2. **handleContextMenu function:**
- Checks `rowSelection.value[taskId]` directly instead of using table methods
- Updates `rowSelection.value` directly when adding unselected task
## How It Works
The table configuration includes a reactive getter:
```typescript
state: {
get rowSelection() {
return rowSelection.value
}
}
```
This means:
1. When we update `rowSelection.value`, Vue's reactivity triggers
2. The table's state getter reads the new value
3. The table's internal state updates
4. `row.getIsSelected()` returns the correct value
5. The template re-renders with correct CSS classes
## Benefits
1. **Proper State Synchronization:** Table state automatically syncs with our ref through the getter
2. **Visual Feedback Works:** The `row.getIsSelected()` method correctly reflects selection state
3. **Simple and Direct:** No need for complex table methods, just update the ref
4. **Vue Reactivity:** Leverages Vue's reactivity system properly
## Testing
To verify the fix:
1. Navigate to a project's Tasks view
2. Click on Task 1
3. Hold Shift and click on Task 5
4. **Expected:** All tasks from 1-5 should show the selected background color (`bg-muted/50`)
5. **Expected:** Selection count should show "5 tasks selected"
### Additional Test Cases
- **Backward range:** Click Task 5, Shift+click Task 1 → Tasks 1-5 selected with visual feedback
- **Ctrl+click after range:** Select range, then Ctrl+click to toggle individual tasks → Visual feedback updates correctly
- **Context menu:** Right-click unselected task → Task gets added to selection with visual feedback
## Related Requirements
- **Requirement 3.3:** Shift+click range selection
- **Requirement 6.1:** Selected rows have distinct background color
- **Requirement 6.2:** Hover state is distinct from selection
## Status
**Fixed** - Shift+click range selection now properly updates visual feedback