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
[Table] Edit focused cells on f2 #1729
Conversation
Edit focused cells on f2Preview: documentation | table |
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.
Seems like a reasonable approach overall! A few things.
packages/table/src/cell/cell.tsx
Outdated
tabIndex?: number; | ||
|
||
/** | ||
* Callback to be called when cell is focused and key is pressed down. |
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.
Articles or no articles? That is the question. Whether 'tis nobler in (the?) mind to suffer...
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.
You should probably add to this comment whether or not these callbacks are called while the cell is being edited.
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.
They are... but since you're in a text field they're ignored. These are used by the hotkeys -- i.e. this is the hack, passing the props down to the actual dom element.
packages/table/src/cell/cell.tsx
Outdated
onKeyDown?: React.KeyboardEventHandler<HTMLElement>; | ||
|
||
/** | ||
* Callback to be called when cell is focused and key is released. |
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.
No articles
onKeyUp?: React.KeyboardEventHandler<HTMLElement>; | ||
|
||
/** | ||
* A ref handle to capture the outer div of this cell. Used internally. |
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.
Articles
|
||
import * as Classes from "../common/classes"; | ||
import { Draggable } from "../interactions/draggable"; | ||
import { Cell, ICellProps } from "./cell"; | ||
|
||
export interface IEditableCellProps extends ICellProps { | ||
/** | ||
* Whether or not the given cell is the current active/focused cell. |
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.
Do we need the or not
?
https://english.stackexchange.com/questions/3382/whether-or-not-vs-whether
<Hotkeys> | ||
<Hotkey | ||
key="edit-cell" | ||
label="Edit the currely focused cell" |
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.
typo currely
=> currently
} | ||
} | ||
|
||
private handleCellRef = (cellRef: HTMLElement) => { |
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.
Our convention for ref handlers is:
private cellRef: HTMLElement;
// ...
private refHandlers = {
cell: (ref: HTMLElement) => this.cellRef = ref;
};
@@ -24,6 +25,11 @@ export interface ITableBodyCellsProps extends IRowIndices, IColumnIndices, IProp | |||
cellRenderer: ICellRenderer; | |||
|
|||
/** | |||
* The location of the focused cell, for setting the "focused" property on cells |
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.
- Better phrasing: "The coordinates of the currently focused cell" or "The currently focused cell"? No need to explain why it's needed IMO. Or, since this is just a codebase-internal component, we can explicitly say "..., for setting the 'isFocused' prop on cells."
- Need trailing period.
@@ -187,7 +193,8 @@ export class TableBodyCells extends React.Component<ITableBodyCellsProps, {}> { | |||
const cellLoading = baseCell.props.loading != null ? baseCell.props.loading : loading; | |||
|
|||
const style = { ...baseCell.props.style, ...Rect.style(rect) }; | |||
return React.cloneElement(baseCell, { className, key, loading: cellLoading, style }); | |||
const isFocused = focusedCell != null && focusedCell.row === rowIndex && focusedCell.col === columnIndex; |
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.
Can we add a CellUtils.cellsEqual
utility function? (in common/internal/cellUtils
+ a few quick unit tests). This check seems like something that could pop up again.
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.
Don't we have something like this for regions?
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.
We do.
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.
I'm... not sure how cellsEqual or anything of the like would make sense here. I'm comparing a focused coordinates with two numbers passed into the function. If I made a cellsEqual, what would I be passing it as arguments, exactly?
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.
Ah, didn't look closely at the comparison values. You're right.
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.
This seems fine. Proposal for additional hotkey rejiggering:
- press
enter
orf2
, get into append edit mode, nothing is selected, cursor at the end - press any key that inserts a char, get into replace edit mode directly
Also, not sure what hackery you were referring to with hotkeys
|
||
&:focus { | ||
// disable focus outline on cells; we already have the focus border | ||
outline: none; |
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.
does this rule affect accessibility? I'm not sure how accessibility features in browsers deal with focus style overrides. maybe it doesn't matter?
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.
This only affects visuals, not interactivity
packages/table/src/cell/cell.tsx
Outdated
tabIndex?: number; | ||
|
||
/** | ||
* Callback to be called when cell is focused and key is pressed down. |
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.
You should probably add to this comment whether or not these callbacks are called while the cell is being edited.
@@ -132,7 +165,15 @@ export class Cell extends React.Component<ICellProps, {}> { | |||
const content = <div className={textClasses}>{modifiedChildren}</div>; | |||
|
|||
return ( |
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.
I've started using destructuring assignment in bp-chart for cases like this. e.g.:
{...{ style, tooltip, tabIndex, onKeyDown, onKeyUp }}
@@ -187,7 +193,8 @@ export class TableBodyCells extends React.Component<ITableBodyCellsProps, {}> { | |||
const cellLoading = baseCell.props.loading != null ? baseCell.props.loading : loading; | |||
|
|||
const style = { ...baseCell.props.style, ...Rect.style(rect) }; | |||
return React.cloneElement(baseCell, { className, key, loading: cellLoading, style }); | |||
const isFocused = focusedCell != null && focusedCell.row === rowIndex && focusedCell.col === columnIndex; |
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.
Don't we have something like this for regions?
@themadcreator I think we can do the different and additonal hotkeys stuff in a later commit, yes? Unless you all think it'd be better if it happened now, in this commit. Also the hackery is in Cell.tsx -- hotkeys passes down a tabIndex and onKeyDown/Up props -- which if the child is not a DOM element (such as in this case) they are ignored. So I added them as props to the Cell and pass them along manually. @giladgray how exactly are you surfacing that? |
032ab32
to
8fa7b3c
Compare
Add tab/enter nav while editing, address commentsPreview: documentation | table |
packages/table/src/cell/cell.tsx
Outdated
tabIndex?: number; | ||
|
||
/** | ||
* Callback to be called when the cell is focused and a key is pressed down. |
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.
nit: Callback invoked
is more concise
packages/table/src/cell/cell.tsx
Outdated
onKeyDown?: React.KeyboardEventHandler<HTMLElement>; | ||
|
||
/** | ||
* Callback to be called when the cell is focused and a key is released. |
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.
Same
private refHandlers = { | ||
cell: (ref: HTMLElement) => { | ||
this.cellRef = ref; | ||
}, |
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.
nit: Change this to a one-liner:
cell: (ref: HTMLElement) => this.cellRef = ref,
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.
Prettier does this. Or at least, adds parens if I don't use curlies, which is honestly silly.
@gscshoyru feel free to address the nits if you want, then merge (or LMK if you want me to merge). |
NitsPreview: documentation | table |
Changes proposed in this pull request:
Editable cells can be edited when focused by pressing
f2
-- so one can edit editable tables merely withf2
,enter
, and the arrow keys -- no mouse required!This is done by making cells able to be browser-focused, and having them focus themselves whenever, well, they become focused. This also lets the focus stay on the table when you're done editing a cell.
Reviewers should focus on:
There's... a bit of a horrible hack to allow the hotkeys to... pass through to the div beneath. I'm not sure if we should keep this or if there's a better way, or what? We could make some sort of slightly better version of cells having these endpoints, and make it less of a hack, maybe? Or fix hotkeys to find the DOM element underneath using
ReactDOM.findDOMNode
?This doesn't work as well with the cell render batching if you're far down and to the right enough -- you can press f2 before the rendering is caught up and be editing the wrong cell for a short period of time before the rendering catches up and snaps it away. I'm... not sure what to do about this.
Screenshot