mirror of
https://github.com/desktop/desktop
synced 2024-09-18 07:32:01 +00:00
Use heuristics to detect when rows obtained focus due to keyboard interactions
This commit is contained in:
parent
490a9c00ea
commit
ae2d1baeee
|
@ -54,6 +54,14 @@ interface IListRowProps {
|
|||
e: React.KeyboardEvent<any>
|
||||
) => void
|
||||
|
||||
/** called when the row (or any of its descendants) receives focus due to a
|
||||
* keyboard event
|
||||
*/
|
||||
readonly onRowKeyboardFocus?: (
|
||||
index: RowIndexPath,
|
||||
e: React.KeyboardEvent<any>
|
||||
) => void
|
||||
|
||||
/** called when the row (or any of its descendants) receives focus */
|
||||
readonly onRowFocus?: (
|
||||
index: RowIndexPath,
|
||||
|
@ -93,6 +101,14 @@ interface IListRowProps {
|
|||
}
|
||||
|
||||
export class ListRow extends React.Component<IListRowProps, {}> {
|
||||
// Since there is no way of knowing when a row has been focused via keyboard
|
||||
// or mouse interaction, we will use the keyDown and keyUp events to track
|
||||
// what the user did to get the row in a focused state.
|
||||
// The heuristic is that we should receive a focus event followed by a keyUp
|
||||
// event, with no keyDown events (since that keyDown event should've happened
|
||||
// in the component that previously had focus).
|
||||
private keyboardFocusDetectionState: 'ready' | 'failed' | 'focused' = 'ready'
|
||||
|
||||
private onRef = (elem: HTMLDivElement | null) => {
|
||||
this.props.onRowRef?.(this.props.rowIndex, elem)
|
||||
}
|
||||
|
@ -115,13 +131,27 @@ export class ListRow extends React.Component<IListRowProps, {}> {
|
|||
|
||||
private onRowKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
this.props.onRowKeyDown(this.props.rowIndex, e)
|
||||
this.keyboardFocusDetectionState = 'failed'
|
||||
}
|
||||
|
||||
private onRowKeyUp = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
this.props.onRowKeyDown(this.props.rowIndex, e)
|
||||
|
||||
if (this.keyboardFocusDetectionState === 'focused') {
|
||||
this.props.onRowKeyboardFocus?.(this.props.rowIndex, e)
|
||||
}
|
||||
this.keyboardFocusDetectionState = 'ready'
|
||||
}
|
||||
|
||||
private onFocus = (e: React.FocusEvent<HTMLDivElement>) => {
|
||||
this.props.onRowFocus?.(this.props.rowIndex, e)
|
||||
if (this.keyboardFocusDetectionState === 'ready') {
|
||||
this.keyboardFocusDetectionState = 'focused'
|
||||
}
|
||||
}
|
||||
|
||||
private onBlur = (e: React.FocusEvent<HTMLDivElement>) => {
|
||||
this.keyboardFocusDetectionState = 'ready'
|
||||
this.props.onRowBlur?.(this.props.rowIndex, e)
|
||||
}
|
||||
|
||||
|
@ -187,6 +217,7 @@ export class ListRow extends React.Component<IListRowProps, {}> {
|
|||
onClick={this.onRowClick}
|
||||
onDoubleClick={this.onRowDoubleClick}
|
||||
onKeyDown={this.onRowKeyDown}
|
||||
onKeyUp={this.onRowKeyUp}
|
||||
style={fullWidthStyle}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
|
|
|
@ -116,6 +116,7 @@ interface IListProps {
|
|||
readonly onRowClick?: (row: number, source: ClickSource) => void
|
||||
|
||||
readonly onRowDoubleClick?: (row: number, source: IMouseClickSource) => void
|
||||
|
||||
readonly onRowFocus?: (
|
||||
row: number,
|
||||
event: React.FocusEvent<HTMLDivElement>
|
||||
|
@ -125,6 +126,11 @@ interface IListProps {
|
|||
event: React.FocusEvent<HTMLDivElement>
|
||||
) => void
|
||||
|
||||
readonly onRowKeyboardFocus?: (
|
||||
row: number,
|
||||
e: React.KeyboardEvent<any>
|
||||
) => void
|
||||
|
||||
/**
|
||||
* This prop defines the behaviour of the selection of items within this list.
|
||||
* - 'single' : (default) single list-item selection. [shift] and [ctrl] have
|
||||
|
@ -671,6 +677,14 @@ export class List extends React.Component<IListProps, IListState> {
|
|||
this.props.onRowFocus?.(indexPath.row, e)
|
||||
}
|
||||
|
||||
private onRowKeyboardFocus = (
|
||||
indexPath: RowIndexPath,
|
||||
e: React.KeyboardEvent<HTMLDivElement>
|
||||
) => {
|
||||
this.focusRow = indexPath.row
|
||||
this.props.onRowKeyboardFocus?.(indexPath.row, e)
|
||||
}
|
||||
|
||||
private onRowBlur = (
|
||||
indexPath: RowIndexPath,
|
||||
e: React.FocusEvent<HTMLDivElement>
|
||||
|
@ -987,6 +1001,7 @@ export class List extends React.Component<IListProps, IListState> {
|
|||
onRowMouseDown={this.onRowMouseDown}
|
||||
onRowMouseUp={this.onRowMouseUp}
|
||||
onRowFocus={this.onRowFocus}
|
||||
onRowKeyboardFocus={this.onRowKeyboardFocus}
|
||||
onRowBlur={this.onRowBlur}
|
||||
onContextMenu={this.onRowContextMenu}
|
||||
style={params.style}
|
||||
|
|
Loading…
Reference in a new issue