Issues with keyboard navigation on KDropdownMenu
Product
Noted in Studio, and in the KDS Docs on the last example of KListWithOverflow.
Expected behavior
Two things are not working very well right now:
- When the list has dividers, the keyboard navigation should ignore them and focus on the next or previous item in the list.
- In the
optionslist, We can include dividers with a{ type: "Divider" }object.
- In the
- When the user presses
taboresc, we should return the focus to the last element focused before KDropdownMenu was active. This can be done by saving thedocument.activeElementbefore focusing the first option of the dropdown menu.
Actual behavior
- Right now, the focus doesn't change when there are dividers and we want to focus the next item, and we can't jump the dividers.
- As KDropdownMenu is rendered in the body element, when
escortabis pressed, the focus returns to the first focusable element on the document after a second. But before the focus returns to the body, the next option in the menu is focused, and after a second, the menu closes, which is a bit misleading since, at first, it seems that we could navigate through the menu with a tab.
Steps to reproduce the issue
- Go to the KListWithOverflow documentation.
- Click on the box of the last list example.
- Navigate with the keyboard through the dropdown menu and note the issues described above.
Additional information
https://github.com/learningequality/kolibri-design-system/assets/51239030/427bdbd5-b02b-4b73-bec1-d54299940b50
Can I get this assigned?
Hi @galovdev, thank you for volunteering, I will assign you
Hello @galovdev, are you still interested in contributing on this issue? If not, we will reassign it.
Hello @galovdev, are you still interested in contributing on this issue? If not, we will reassign it.
Hi, please give me this weekend, Im working on the other issue
Thank you @galovdev - no problem. Please reach out if you have any questions.
Hi @galovdev, are you still planning to work on this?
Hey @AlexVelezLl may I work on this issue?
Hey @Sahil-Sinha-11! Yes, for sure! You are welcome! I will assign this issue to you! :)
Hey @AlexVelezLl I am a bit lost in the code can you please guide me a bit.. π . I tried using handlekeyNavigation and event listeners on keydown but did not get any progress.
Hey @Sahil-Sinha-11. For sure! For number 1 we should be able to focus the next element even if there is a Divider. For this we should be looking at how we query our next and previous siblings here, and ignore the dividers.
For number 2, we can see how KModal handles the lastFocus element https://github.com/learningequality/kolibri-design-system/blob/ea611a50f17d3760b2bfb9fb4d4ae67921ee288f/lib/KModal.vue#L254 and how they return the focus once the component is destroyed https://github.com/learningequality/kolibri-design-system/blob/ea611a50f17d3760b2bfb9fb4d4ae67921ee288f/lib/KModal.vue#L287. Probably with the dropdown a destroyed hook wouldnt work because I think it doesnt get destroyed but just hidden, so we will need to figure out a way of notifying when the dropdown is hidden and then return the focus when that happens.
Hope this helps :), let me know if you need more guidance.
https://github.com/user-attachments/assets/549e99bb-8a8c-414f-9dd7-414fde337327
Hey @AlexVelezLl Thanks a lot for the help. Should this be the expected behavior for issue 1?
I tried to make some changes in kmodel tracking dropdown and resetting focus but I was not able to produce the expected results. Can you please give me some more guidance.
Hey @Sahil-Sinha-11, yes that is the expected behaviour π.
I tried to make some changes in kmodel tracking dropdown and resetting focus but I was not able to produce the expected results. Can you please give me some more guidance.
Could you open a PR with your code, please?, so we can discuss better there π€
Sure @AlexVelezLl , I opened PR#818. π
Thanks @Sahil-Sinha-11! I will take a look
Thanks @Sahil-Sinha-11 and @AlexVelezLl.
I tried to make some changes in kmodel tracking dropdown and resetting focus but I was not able to produce the expected results. Can you please give me some more guidance.
@Sahil-Sinha-11 Generally, it would be helpful to mention in your PR what approaches you tried or do some debugging and describe what you're observing exactly. We're happy to provide guidance and support, however that will be rather in the form of giving direction and answering concrete questions, rather than resolving the issue in question.
Thank you for the suggestion! I realize I should have shared my approach as well, my apologies. Hereβs how Iβve been tackling it so far...@MisRob @AlexVelezLl ,
I added a variable to track dropdown,
when the dropdown closes it calls the resetfocus function to return to last focused element,
and this is the function to where it returns the focus
I tried using this but it didn't work..π
.
Thanks @Sahil-Sinha-11, this is helpful. Overall looks like a good direction. Some first suggestions:
(1) Where is the place where the previously focused element gets saved to lastFocus? Ssimilarly to https://github.com/learningequality/kolibri-design-system/blob/ea611a50f17d3760b2bfb9fb4d4ae67921ee288f/lib/KModal.vue#L254? Is it implemented and you just didn't take a screenshot or is it not there yet?
(2) If (1) is satisfied, I'd recommend next steps would be to debug, e.g. console log the active element and lastFocus value, and track the place where exactly the intended logic is breaking. You will probably spot some mismatch between what you wanted to happen. A soon as you are a bit closer what place is causing the issue, let @AlexVelezLl or me know and we can chat about the approach to resolve that.
Hey @Sahil-Sinha-11! I think there has been a misunderstanding here π
. The change isnt needed in KModal, but in KDropdownMenu. We need to replicate in KDropdownMenu the lastFocus behaviour that KModal has, but the change needs to be done in KDropdownMenu. The challenge is that, unlike KModal, we cant rely on the mounted hook to know where the last focus was, because KDropdownMenu is always mounted, its not mounted/unmounted each time we open/close it.
So when we open it, we need to store the element that is focused before any of the items in the menu gets the focus. And when we close the dropdown, we need to return the focus to the element that was focused before we open the dropdown.
Hope this helps clarifying what is needed π€.
Thanks @Sahil-Sinha-11, this is helpful. Overall looks like a good direction. Some first suggestions:
(1) Where is the place where the previously focused element gets saved to
lastFocus? Ssimilarly tokolibri-design-system/lib/KModal.vue
Line 254 in ea611a5
this.lastFocus = document.activeElement;? Is it implemented and you just didn't take a screenshot or is it not there yet? (2) If (1) is satisfied, I'd recommend next steps would be to debug, e.g. console log the active element and
lastFocusvalue, and track the place where exactly the intended logic is breaking. You will probably spot some mismatch between what you wanted to happen. A soon as you are a bit closer what place is causing the issue, let @AlexVelezLl or me know and we can chat about the approach to resolve that.
Hey @MisRob, Its in the before mount
But, Now as @AlexVelezLl suggested, I would try to implement the storage of last focus element in the KDropdownMenu, I am on it.π§π»βπ»
@Sahil-Sinha-11 Wonderful, thanks. Yes, KModal is just an example for you to take an inspiration from. KDropdownMenu can be used from many more places, not just from within modals, so it needs to be implemented within the menu itself.
Closed by #818