Never draggable elements
- Dominant language
- TypeScript
- Stars
- 17.6k
- Forks
- 924
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 2
Description
I have a table with draggable rows. Some rows might have their dragging disabled and setting `disabled` on `useDraggable` works well. It also has good a11y because the drag handle can still receive focus so the user can be informed why the row is currently not draggable. However the table also has some rows that are never draggable and in this case I do not want to have a drag handle visually and neither the main ref nor the drag handle should be able to receive focus.
Consider the following code taken from my table (reduced for brevity):
```tsx
interface RowProps {
canDrag?: 'never' | 'enabled' | 'disabled';
// ...
}
function Row({ id, canDrag, canDrop, data, children }: RowProps): JSX.Element {
const ref: Ref = useRef(null);
const { handleRef } = useDraggable({
// have to remove the element ref because when `canDrag === 'never'` the handleRef
// is not attached and then the row would be made focusable
element: canDrag === 'never' ? undefined : ref,
id,
data,
disabled: canDrag !== 'enabled',
});
useDroppable({ element: ref, id, data, disabled: !canDrop, collisionDetector });
return useMemo(
() => (
{children}
),
[id, handleRef, canDrag, children],
);
}
```
it would be very convenient to have something like an `inert` boolean on draggable to say: yeah while i set this draggable up, it can actually never be dragged and neither its element ref nor its handle ref should ever be set up with tab index or other attrs
example usage:
```tsx
interface RowProps {
canDrag?: 'never' | 'enabled' | 'disabled';
// ...
}
function Row({ id, canDrag, canDrop, data, children }: RowProps): JSX.Element {
const ref: Ref = useRef(null);
const { handleRef } = useDraggable({
element: ref,
id,
data,
disabled: canDrag !== 'enabled',
inert: canDrag === 'never', // or alternatively pass something like `always` to `disabled`
});
useDroppable({ element: ref, id, data, disabled: !canDrop, collisionDetector });
return useMemo(
() => (
{children}
),
[id, handleRef, canDrag, children],
);
}
```
Contributor guide
Research direction
Start at the useDraggable API and its existing disabled behavior, then trace how element and handle refs receive focus-related attributes. Done means an inert option or equivalent prevents both refs from being initialized with tabindex or other draggable attributes while preserving normal enabled and disabled behavior; add coverage for the never-draggable case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- accessibility, frontend
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100