Skip to content
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

fix: Fix tab focus when other elements are displayed next to text that are within a focus trap #5281

Merged
merged 1 commit into from
Jan 29, 2024

Conversation

juliusknorr
Copy link
Member

@juliusknorr juliusknorr commented Jan 18, 2024

Instead of manually messing with the focus trap which breaks the focus order when trying to tab out of the editor into the sidebar next to the viewer, we can just use the default viewer handling and instead prevent event propagation for cases where the Tab key issues a command within the editor.

Additional fix for https://github.com/nextcloud/andy/issues/8

@juliusknorr
Copy link
Member Author

Additional related question that came up while testing: Do we need a active focus indicator for the actual content editable? Currently that does not have any indicator except for the cursor position

Something like this would be easy to achieve but I'm unsure as this is quite a visual design change cc @nextcloud/designers

Screenshot 2024-01-18 at 16 38 25

@juliusknorr juliusknorr requested a review from mejo- January 18, 2024 15:39
@juliusknorr juliusknorr added this to the Nextcloud 29 milestone Jan 18, 2024
@juliusknorr
Copy link
Member Author

Checking the cypress failure

@JuliaKirschenheuter
Copy link
Contributor

Thank you @juliushaertl for taking over!

No, we don't need an active focus indicator for the actual content editable.

Just tested (i don't know if this PR is ready) but there seems to be 2 invisible focus stops between content editable and sidebar elements: same behavior for forward and backward navigation

@juliusknorr
Copy link
Member Author

Just tested (i don't know if this PR is ready) but there seems to be 2 invisible focus stops between content editable and sidebar elements: same behavior for forward and backward navigation

Which browser did you try there? I haven't seen that happening yesterday.

@juliusknorr juliusknorr force-pushed the fix/sidebar-focustrap branch from b4f7e90 to 5dbd121 Compare January 19, 2024 10:05
@JuliaKirschenheuter
Copy link
Contributor

tested again, but still can reproduce in Chrome ;(

@juliusknorr
Copy link
Member Author

Ok, this turns out more tricky. Apparently we cannot just prevent the focus trap event listener form triggering as it is registered with https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#capture false so it will be executed even before we ever reach the event listeners from text.

pause/unpause of the focus trap could work but seems not very clean

Maybe we need to create our own trap for the content editable so we can control if and how it would be exited - just assuming for now that the parent trap would then just be picked up properly, but needs more work and investigation.

@juliusknorr
Copy link
Member Author

https://github.com/focus-trap/focus-trap/blob/master/docs/js/nested.js is probably a good sample for this if we handle the activation once the editor gets focus and the deactivation on the Tab/Shift-Tab keypress (if no native editor function like list indent is feasible)

@max-nextcloud
Copy link
Collaborator

max-nextcloud commented Jan 23, 2024

@juliushaertl sounds like this still needs some work, right? Turning into 2. developing and a draft and will review once it's ready.

@max-nextcloud max-nextcloud marked this pull request as draft January 23, 2024 13:59
@juliusknorr juliusknorr force-pushed the fix/sidebar-focustrap branch 2 times, most recently from 7059511 to 95fe30c Compare January 25, 2024 17:52
@juliusknorr
Copy link
Member Author

All right, I went for a slightly different approach.

The viewer focus trap needs to be paused on the fly in order to properly handle tab commands in the editor, as we have no control over if a tab key event is reaching the editor otherwise. This is because the focus trap registers a capture listener (https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#capture), so whenever we reach a tab command in the editor the focus trap will already have captured the event.

We also cannot work around this by pushing our own focus trap to the stack, as the focus trap package does not offer any reliable way to programmatically focus the next element of the parent trap if we allow tabbing out of the editor.

Therefore a new tiptap extension now pauses the focus trap whenever the tab key should be catched by editor actions (indent lists, navigate to the next table cell) and otherwise unpauses so that the actual next tabbable element in the trap containers is getting its focus.

@ShGKme Would appreciate your feedback here since you likely have better knowledge of focus trap handling. Does that approach make sense? At least function wise this seems to be the only way to achieve consistent tab handling I could find.

@ShGKme
Copy link
Contributor

ShGKme commented Jan 25, 2024

@juliushaertl I have been just working on fixing the conflict between NcActions and focus-trap.

Maybe that's what you need?

nextcloud-libraries/nextcloud-vue#4953

focus trap needs to be paused on the fly

This is exactly what I have done. I'm pausing the focus trap stack and unpausing it back.

@juliusknorr
Copy link
Member Author

Ok, similar approach then. The fix here is unrelated to actions so we still need our own implementation, but then I'd set this back to review state

@juliusknorr juliusknorr marked this pull request as ready for review January 26, 2024 08:18
@juliusknorr
Copy link
Member Author

Ah just tests need some fixes

Copy link
Member

@mejo- mejo- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for working on this! I tested this with my link bubble PR (#5158) and it fixs the tab navigation behaviour there ❤️

const trapStack = window._nc_focus_trap ?? []
const activeTrap = trapStack[trapStack.length - 1]

const possibleEditorTabCommand = editor.can().sinkListItem('listItem')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will throw an exception when listItem is not a registered node type:

Error: There is no node type named 'listItem'. Maybe you forgot to add the extension?

We probably either have to catch the exception or check if the node type exists first.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed by only using it for the rich text editing. Plaintext has a different problem, but I'll address that separately.

@mejo-
Copy link
Member

mejo- commented Jan 26, 2024

Thanks a lot for working on this! I tested this with my link bubble PR (#5158) and it fixs the tab navigation behaviour there ❤️

In fact it also makes the Cypress tests for #5158 much more reliable 🙏

…t are within a focus trap

Signed-off-by: Julius Härtl <jus@bitgrid.net>
@juliusknorr juliusknorr force-pushed the fix/sidebar-focustrap branch from 95fe30c to 2c9e7a0 Compare January 26, 2024 14:16
@juliusknorr juliusknorr requested a review from mejo- January 26, 2024 14:43
@juliusknorr juliusknorr merged commit cd2f39c into main Jan 29, 2024
53 checks passed
@juliusknorr juliusknorr deleted the fix/sidebar-focustrap branch January 29, 2024 07:37
@juliusknorr
Copy link
Member Author

/backport to stable28

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants