Fix focus issues#3505
Conversation
Codecov Report
@@ Coverage Diff @@
## master #3505 +/- ##
==========================================
+ Coverage 54.35% 54.44% +0.08%
==========================================
Files 119 119
Lines 4660 4662 +2
Branches 962 962
==========================================
+ Hits 2533 2538 +5
+ Misses 2127 2124 -3
Continue to review full report at Codecov.
|
codehag
left a comment
There was a problem hiding this comment.
Great work, I like this pattern, using refs instead of using componentDidMount + reactDom.findDOMNode for associating a node to the component. I think we should use it elsewhere too!
A couple of comments, and can you also add the test from the issue?
| static defaultProps: Object; | ||
|
|
||
| componentDidMount() { | ||
| this.input.focus(); |
|
|
||
| componentDidMount() { | ||
| this.input.focus(); | ||
| this.input.select(); |
There was a problem hiding this comment.
In the old code, we used setSelectionRange -- was this to move the cursor to the end of the input? I also noticed that in both cases we only fire select when the component is opened, and in that case it is empty. perhaps we don't need this?
There was a problem hiding this comment.
We were using it but we were making a selection of the end to the end? So I wasn't sure what exactly that was achieving. I don't think it nor .select() make a ton of sense so I don't care for keeping them.
Sure! I forgot that the issue had a test associated. Thanks @codehag |
48855cb to
0904bd0
Compare
| pressKey(dbg, "sourceSearch"); | ||
| yield waitForElement(dbg, "input"); | ||
| findElementWithSelector(dbg, "input").focus(); | ||
| ok( |
There was a problem hiding this comment.
Correct me if I'm wrong but this is the way to assert in mochitest?
jasonLaster
left a comment
There was a problem hiding this comment.
couple of comments, but overall this is great!
| value: query, | ||
| spellCheck: false, | ||
| ref: "input" | ||
| ref: c => (this.input = c) |
There was a problem hiding this comment.
is this the preferred style?
perhaps? ref: c => (this.$input = c)
it's funny, i prefer refs because their namespaced, but i'll support anything.
Also this style is fine w/ me too
https://github.com/devtools-html/debugger.html/blob/master/src/components/shared/Autocomplete.js#L51-L53
| if ( | ||
| this.refs.searchInput && | ||
| this.refs.searchInput.input && | ||
| this.props.enabled |
There was a problem hiding this comment.
nit: but lets put this.props.enabled first
|
|
||
| if (selectedSource && enabled) { | ||
| modalEnabled = true; | ||
| } |
There was a problem hiding this comment.
we might be playing too much of a dance w/ enabled, perhaps a new method is in order:
- we dont need enabled prop
- we can consolidate logic
isEnabled() {
const {activeSearch, selectedSource} = this.props
return activeSearch === "symbol" && selectedSource
}There was a problem hiding this comment.
So enabled is also used for whether to update the results or not. I figured that I could instead modify the value we get in the connect call.
export default connect(
state => {
const source = getSelectedSource(state);
return {
enabled: getActiveSearchState(state) === "symbol" && source,
symbolType: getSymbolSearchType(state),
symbols: _getFormattedSymbols(state, source)
};
},
dispatch => bindActionCreators(actions, dispatch)
)(SymbolModal);| pressKey(dbg, "sourceSearch"); | ||
| yield waitForElement(dbg, "input"); | ||
| findElementWithSelector(dbg, "input").focus(); | ||
| ok( |
There was a problem hiding this comment.
yep, that will work!
i guess i was assuming it because the next action is typing... and it will work or fail based on that, but i don't care. this is nice to have.
jasonLaster
left a comment
There was a problem hiding this comment.
couple of comments, but overall this is great!
| value: query, | ||
| spellCheck: false, | ||
| ref: "input" | ||
| ref: c => (this.input = c) |
There was a problem hiding this comment.
is this the preferred style?
perhaps? ref: c => (this.$input = c)
it's funny, i prefer refs because their namespaced, but i'll support anything.
Also this style is fine w/ me too
https://github.com/devtools-html/debugger.html/blob/master/src/components/shared/Autocomplete.js#L51-L53
There was a problem hiding this comment.
Are you suggesting that we use the $ to prefix it as a ref?
There was a problem hiding this comment.
i prefer $ if we do the property style. I still like ReactDOM.findNode or this.ref as well.
There was a problem hiding this comment.
Oh I could put the ref into the refs object as well by changing the line to this.refs.input = c
There was a problem hiding this comment.
Correction. Seems like you can't add the property to the refs object via a function ref.
| if ( | ||
| this.refs.searchInput && | ||
| this.refs.searchInput.input && | ||
| this.props.enabled |
There was a problem hiding this comment.
nit: but lets put this.props.enabled first
|
|
||
| if (selectedSource && enabled) { | ||
| modalEnabled = true; | ||
| } |
There was a problem hiding this comment.
we might be playing too much of a dance w/ enabled, perhaps a new method is in order:
- we dont need enabled prop
- we can consolidate logic
isEnabled() {
const {activeSearch, selectedSource} = this.props
return activeSearch === "symbol" && selectedSource
}| pressKey(dbg, "sourceSearch"); | ||
| yield waitForElement(dbg, "input"); | ||
| findElementWithSelector(dbg, "input").focus(); | ||
| ok( |
There was a problem hiding this comment.
yep, that will work!
i guess i was assuming it because the next action is typing... and it will work or fail based on that, but i don't care. this is nice to have.
0904bd0 to
6c7daac
Compare
|
|
||
| componentDidUpdate() { | ||
| const shortcuts = this.context.shortcuts; | ||
| if (this.props.enabled) { |
There was a problem hiding this comment.
hmm, this worries me because we might be doing too many on calls.
Should we add a check in here like !props.enabled && nextProps.enabled?
There was a problem hiding this comment.
I tried this and it wouldn't work after the first time you toggled on.
6c7daac to
6a09000
Compare
6a09000 to
e69461a
Compare
|
Rebased |
|
Not sure what is happening with the tests; they pass on master and locally. looks like the problem is again with pretty print: |
codehag
left a comment
There was a problem hiding this comment.
I noticed a bit of an issue with a parent component controlling a child components behavior -- i think we should change that but overall it looks good
| const shortcuts = this.context.shortcuts; | ||
| if (this.refs.searchInput) { | ||
| this.refs.searchInput.refs.input.focus(); | ||
| this.refs.searchInput.$input.focus(); |
There was a problem hiding this comment.
hmm this looks like it might give us trouble later on -- we are controlling a child component from a parent component; this makes it difficult to separate them -- we probably want searchInput to do this, rather than doing it here.
| static defaultProps: Object; | ||
|
|
||
| componentDidMount() { | ||
| this.$input.focus(); |
There was a problem hiding this comment.
this should be enough... was it not working with this ?
There was a problem hiding this comment.
Because the modal is mounted the symbol modal needs to have that if block to focus the input. I'll research further to see if there's a solution that's cleaner but this gets the focus events working on all the search dialogs and ensures we have no regressions on the shortcuts.
800073e to
f68c3fb
Compare
| "wasmparser": "^0.4.10" | ||
| }, | ||
| "files": ["src", "assets"], | ||
| "files": [ |
There was a problem hiding this comment.
I think yarn reformats this file when you use yarn add 🤷♂️
| } | ||
|
|
||
| .theme-dark .symbol-modal { | ||
| box-shadow: 2px 4px 6px var(--popup-shadow-color); |
There was a problem hiding this comment.
Redundant rule? It's on the modal itself just above.
f7c39fe to
672a559
Compare
| componentDidMount() { | ||
| const shortcuts = this.context.shortcuts; | ||
| shortcuts.on(L10N.getStr("symbolSearch.search.key2"), this.openSymbolModal); | ||
| shortcuts.on("Escape", this.closeModal); |
There was a problem hiding this comment.
It was problematic adding shortcuts to the modal itself and would leave the shortcut disabled on its dismount. Letting the consumer's handle it seems like a simpler API.
| return Transition({ | ||
| in: inProp, | ||
| timeout: 175, | ||
| appear: true, |
There was a problem hiding this comment.
Normally a component is not transitioned if it shown when the component mounts. If you want to transition on the first mount set appear to true, and the component will transition in as soon as the mounts.
This prop is awesome but sadly there doesn't seem to be a leave that is the equivalent. I've opened an issue on react-transition-group requesting one to see what they recommend.
|
So now the two assertions I added to the mochitests fail but from testing all three search inputs get focus when you open them. 🙁 Edit: Ran locally and they passed. |
3aa564f to
1e118e5
Compare
1e118e5 to
cc6f822
Compare
cc6f822 to
6628741
Compare
6628741 to
2188a50
Compare
Associated Issue: #3495
Summary of Changes
Test Plan
Example test plan: