Init Repo
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
# Shot Delete Event Bubbling - Final Fix
|
||||
|
||||
## Issue Description
|
||||
|
||||
The shot detail panel was still being triggered when performing delete shot actions, despite previous attempts to fix event bubbling. This was happening because the event prevention logic in the `handleRowClick` function was not comprehensive enough to catch all interactive elements within the dropdown menu.
|
||||
|
||||
## Root Cause Analysis
|
||||
|
||||
The issue occurred in the `ShotsDataTable.vue` component where the `handleRowClick` function was not properly detecting all types of interactive elements that should prevent row click events. Specifically:
|
||||
|
||||
1. **Incomplete Element Detection**: The original selector list was missing some Radix UI specific attributes and SVG icons
|
||||
2. **Missing Parent Element Traversal**: The function wasn't checking parent elements for event handlers
|
||||
3. **Icon Click Events**: SVG icons within buttons were not being properly detected
|
||||
4. **Radix UI Elements**: Some Radix UI dropdown elements have dynamic attributes that weren't being caught
|
||||
|
||||
## Solution Implementation
|
||||
|
||||
### 1. Enhanced Interactive Element Detection
|
||||
|
||||
Updated the `handleRowClick` function in `ShotsDataTable.vue` to include a more comprehensive list of selectors:
|
||||
|
||||
```typescript
|
||||
const isInteractiveElement = target.closest([
|
||||
'button',
|
||||
'[role="menuitem"]',
|
||||
'[role="menu"]',
|
||||
'[data-radix-collection-item]',
|
||||
'[data-radix-dropdown-menu-trigger]',
|
||||
'[data-radix-dropdown-menu-content]',
|
||||
'[data-radix-dropdown-menu-item]',
|
||||
'[data-state]', // Radix UI elements often have data-state
|
||||
'.dropdown-menu',
|
||||
'.dropdown-trigger',
|
||||
'input',
|
||||
'select',
|
||||
'textarea',
|
||||
'a[href]',
|
||||
'[tabindex]:not([tabindex="-1"])',
|
||||
'[onclick]',
|
||||
'svg', // Icons within buttons
|
||||
'.lucide' // Lucide icons specifically
|
||||
].join(', '))
|
||||
```
|
||||
|
||||
### 2. Parent Element Traversal
|
||||
|
||||
Added logic to traverse up the DOM tree to check for elements with event handlers:
|
||||
|
||||
```typescript
|
||||
let currentElement: HTMLElement | null = target
|
||||
while (currentElement && currentElement !== event.currentTarget) {
|
||||
if (
|
||||
currentElement.onclick ||
|
||||
currentElement.getAttribute('role') === 'button' ||
|
||||
currentElement.tagName === 'BUTTON' ||
|
||||
(currentElement.classList.contains('cursor-pointer') &&
|
||||
currentElement !== event.currentTarget)
|
||||
) {
|
||||
return // Don't emit row-click
|
||||
}
|
||||
currentElement = currentElement.parentElement
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Enhanced Event Prevention in Columns
|
||||
|
||||
The `columns.ts` file was already enhanced by the IDE autofix to include `onMouseDown` event handlers on all dropdown elements:
|
||||
|
||||
```typescript
|
||||
// Dropdown trigger
|
||||
h(DropdownMenuTrigger, {
|
||||
asChild: true,
|
||||
onMouseDown: (e: Event) => {
|
||||
e.stopPropagation()
|
||||
},
|
||||
onClick: (e: Event) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
})
|
||||
|
||||
// Dropdown content and items
|
||||
h(DropdownMenuContent, {
|
||||
align: 'end',
|
||||
onMouseDown: (e: Event) => {
|
||||
e.stopPropagation()
|
||||
},
|
||||
onClick: (e: Event) => {
|
||||
e.stopPropagation()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Files Modified
|
||||
|
||||
### 1. `frontend/src/components/shot/ShotsDataTable.vue`
|
||||
- Enhanced `handleRowClick` function with comprehensive interactive element detection
|
||||
- Added parent element traversal logic
|
||||
- Fixed TypeScript typing for element traversal
|
||||
- Removed unused `computed` import
|
||||
|
||||
### 2. `frontend/src/components/shot/columns.ts` (Enhanced by IDE autofix)
|
||||
- Added `onMouseDown` event handlers to all dropdown elements
|
||||
- Enhanced event prevention with both `stopPropagation()` and `preventDefault()`
|
||||
- Improved event handling for all dropdown menu items
|
||||
|
||||
## Testing
|
||||
|
||||
### Test File Created
|
||||
- `frontend/test-shot-delete-event-bubbling-final-fix.html` - Comprehensive test interface
|
||||
|
||||
### Test Scenarios Covered
|
||||
1. **Row Click Test**: Clicking on non-interactive areas should trigger row click
|
||||
2. **Dropdown Button Test**: Clicking the three-dot menu button should NOT trigger row click
|
||||
3. **Menu Item Test**: Clicking "Edit Shot" or "View Tasks" should NOT trigger row click
|
||||
4. **Delete Test**: Clicking "Delete Shot" should NOT trigger row click (main issue)
|
||||
5. **Icon Test**: Clicking directly on SVG icons within buttons should NOT trigger row click
|
||||
|
||||
### Expected Results
|
||||
- ✅ Row clicks work on non-interactive areas
|
||||
- ✅ Dropdown button clicks don't trigger row click
|
||||
- ✅ Menu item clicks don't trigger row click
|
||||
- ✅ Delete button clicks don't trigger row click
|
||||
- ✅ Shot detail panel doesn't open during delete operations
|
||||
|
||||
## Technical Details
|
||||
|
||||
### Event Flow
|
||||
1. User clicks delete button in dropdown menu
|
||||
2. `onMouseDown` handler on dropdown elements prevents initial bubbling
|
||||
3. `onClick` handler on menu item executes delete action
|
||||
4. Enhanced `handleRowClick` function detects interactive element and prevents row click emission
|
||||
5. Shot detail panel remains closed during delete operation
|
||||
|
||||
### Browser Compatibility
|
||||
- Uses standard DOM traversal methods (`closest`, `parentElement`)
|
||||
- Compatible with all modern browsers
|
||||
- Handles both mouse and touch events
|
||||
|
||||
### Performance Impact
|
||||
- Minimal performance impact due to efficient DOM traversal
|
||||
- Event prevention happens early in the event chain
|
||||
- No unnecessary event listeners or watchers added
|
||||
|
||||
## Prevention Measures
|
||||
|
||||
To prevent similar issues in the future:
|
||||
|
||||
1. **Comprehensive Testing**: Always test interactive elements within table rows
|
||||
2. **Event Handler Documentation**: Document all event prevention strategies
|
||||
3. **Radix UI Awareness**: Be aware of Radix UI's dynamic attributes and event handling
|
||||
4. **Icon Handling**: Remember that SVG icons can be click targets within buttons
|
||||
5. **Parent Traversal**: Consider parent element event handlers when preventing bubbling
|
||||
|
||||
## Verification
|
||||
|
||||
The fix can be verified by:
|
||||
1. Opening the shot table in the application
|
||||
2. Clicking the three-dot menu on any shot row
|
||||
3. Clicking "Delete Shot" option
|
||||
4. Confirming that the shot detail panel does NOT open
|
||||
5. Confirming that the delete confirmation dialog opens instead
|
||||
|
||||
## Related Issues
|
||||
|
||||
This fix resolves the core issue where delete actions were inadvertently opening the shot detail panel, improving the user experience and preventing confusion during delete operations.
|
||||
Reference in New Issue
Block a user