-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Maintain focus when moving between lists #449
Changes from 1 commit
61778c2
7254b05
b702f48
63f0c41
e02fc79
da31bf6
8166325
842dfa9
d81b7aa
011bf84
b72ef06
aec9d2f
c8e21ef
f44925f
8a0ebac
66580b3
e5df5e6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
// @flow | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rather than repeating these everywhere i pulled them out |
||
export const prefix: string = 'data-react-beautiful-dnd'; | ||
export const dragHandle: string = `${prefix}-drag-handle`; | ||
export const draggable: string = `${prefix}-draggable`; | ||
export const droppable: string = `${prefix}-droppable`; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Flow question, do these need to be typed as string or can the type be inferred from the assignment since they are constants? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i generally type every variable even if it can be inferred |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ import type { | |
import DraggableDimensionPublisher from '../draggable-dimension-publisher/'; | ||
import Moveable from '../moveable/'; | ||
import DragHandle from '../drag-handle'; | ||
import focusOnDragHandle from './focus-on-drag-handle'; | ||
import getViewport from '../window/get-viewport'; | ||
// eslint-disable-next-line no-duplicate-imports | ||
import type { | ||
|
@@ -53,7 +54,7 @@ export default class Draggable extends Component<Props> { | |
/* eslint-disable react/sort-comp */ | ||
callbacks: DragHandleCallbacks | ||
styleContext: string | ||
isFocused: boolean = false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. now handled by the drag handle |
||
isDragHandleFocused: boolean = false | ||
ref: ?HTMLElement = null | ||
|
||
// Need to declare contextTypes without flow | ||
|
@@ -98,8 +99,8 @@ export default class Draggable extends Component<Props> { | |
return; | ||
} | ||
|
||
// This draggable was previously focused - give it focus! | ||
this.ref.focus(); | ||
// This drag handle was previously focused - give it focus! | ||
focusOnDragHandle(this.ref); | ||
} | ||
|
||
componentWillUnmount() { | ||
|
@@ -145,13 +146,13 @@ export default class Draggable extends Component<Props> { | |
} | ||
|
||
onFocus = () => { | ||
this.isFocused = true; | ||
this.isDragHandleFocused = true; | ||
// Record that this was the last focused draggable | ||
lastFocused = this.props.draggableId; | ||
} | ||
|
||
onBlur = () => { | ||
this.isFocused = false; | ||
this.isDragHandleFocused = false; | ||
// On blur we can clear our last focused | ||
lastFocused = null; | ||
} | ||
|
@@ -223,8 +224,8 @@ export default class Draggable extends Component<Props> { | |
// After a ref change we might need to manually force focus onto the ref. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. focus retention logic is now controlled by the component that has focus: the drag handle |
||
// When moving something into or out of a portal the element looses focus | ||
// https://github.com/facebook/react/issues/12454 | ||
if (this.ref && this.isFocused) { | ||
this.ref.focus(); | ||
if (this.ref && this.isDragHandleFocused) { | ||
focusOnDragHandle(this.ref); | ||
} | ||
}) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// @flow | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A new file to help us to get the draggable ref which is currently not provided by consumers |
||
import { dragHandle } from '../data-attributes'; | ||
|
||
const selector: string = `[${dragHandle}]`; | ||
|
||
const getDragHandleRef = (draggableRef: HTMLElement): ?HTMLElement => { | ||
if (draggableRef.hasAttribute(dragHandle)) { | ||
return draggableRef; | ||
} | ||
|
||
// find the first nested drag handle | ||
const el: ?HTMLElement = draggableRef.querySelector(selector); | ||
|
||
if (!el) { | ||
return null; | ||
} | ||
|
||
return el; | ||
}; | ||
|
||
const focusOnDragHandle = (draggableRef: HTMLElement) => { | ||
const dragHandleRef: ?HTMLElement = getDragHandleRef(draggableRef); | ||
if (!dragHandleRef) { | ||
console.error('Draggable cannot focus on the drag handle as it cannot be found'); | ||
return; | ||
} | ||
dragHandleRef.focus(); | ||
}; | ||
|
||
export default focusOnDragHandle; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/loose/lose