feat: drop down keyboard navigation#1985
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
| } | ||
| }; | ||
|
|
||
| const contextValue = { |
There was a problem hiding this comment.
Should be memoized to prevent React doing extra context updates.
There was a problem hiding this comment.
I am not sure how to do this. Wrapping contextValue in useMemo with all its entries as dependencies doesnt make sense? Updates won't be reduced this way?
Anyway, I have moved the highlightedItem out of the contextValue object, and call the focus method from the parent instead of the within the item component, this should reduce the extra renders triggered by change in the highlighted item.
There was a problem hiding this comment.
@ivan-ngchakming - useMemo will preserve the same object reference which means that Context.Provider will see as the same exact value and won't trigger further re-renders when that is the case.
Without useMemo, every time this components rerenders you're essentially generating a brand new object/value.
|
I think when the drop-down is open, pressing |
Is that correct? I'm not sure. @a11yHolli can your clarify the correct behavior for us here? Would love to get this one updated and merged. @ivan-ngchakming |
I believe this would be consistent with the native select. I am currently working on my finals, will work on this in a few days as soon as I am free. |
acywatson
left a comment
There was a problem hiding this comment.
This looks good to me now - thanks!
| } | ||
|
|
||
| // $FlowFixMe: I am not sure why this is wrong | ||
| highlightedItem?.current?.focus(); |
There was a problem hiding this comment.
We typically avoid optional chaining - I don't think we have the transpilation in place necessary to support various targets we support.
Does it work if you do something likee:
if (highlightedItem !== null && highlightedItem.current instanceof HTMLElement) {
highlightedItem.current.focus();
}
There was a problem hiding this comment.
What if you did:
const highlightedItemElem: null | HTMLElement = highlightedItem.current
if (highlightedItemElem !== null) {
highlightedItemElem.focus();
}
There was a problem hiding this comment.
I tried out a few ways
// works
if (highlightedItem && highlightedItem.current instanceof HTMLElement) {
highlightedItem.current.focus();
}
// also works, since highlightedItem.current is either `HTMLElement` or `null`
if (highlightedItem && highlightedItem.current) {
highlightedItem.current.focus();
}
// type error: highlightedItem is possibly 'undefined' in `highlightedItem.current instanceof HTMLElement`
if (highlightedItem !== null && highlightedItem.current instanceof HTMLElement) {
highlightedItem.current.focus();
}
// type error: highlightedItem is possibly 'undefined'
const highlightedItemElem: null | HTMLElement = highlightedItem.current
if (highlightedItemElem !== null) {
highlightedItemElem.focus();
}If its all the same, I will go with the second option as its more concise, but still satisfying all the type checks.
if (highlightedItem && highlightedItem.current) {
highlightedItem.current.focus();
}
It was behaving like this before this PR if I remember correctly. I am guessing the style that should be applied on it is missing, maybe there should be some kind of icon or indicator to show the style applied on the selected text? But the non-active buttons not being full width issue would still needs to be fixed. |


Added keyboard navigation feature to drop down UI component
TabArrowUp,ArrowDown)Escapeand return focus to the drop down buttoncloses #1923
Screens