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

Tabs: update indicator more reactively #66207

Merged
merged 6 commits into from
Oct 18, 2024
Merged

Conversation

ciampo
Copy link
Contributor

@ciampo ciampo commented Oct 17, 2024

What?

Fixes #65576

Improve how Tabs reacts to changes to tabs in the tablist other than resizing

Why?

Fixes a bug

How?

So far, we were re-measuring the indicator position only when the tab's dimensions change (via a `ResizeObserver), but this was not enough. For example, a tab item could be swapped with another one, or one or more tab items could be added/removed to the tablist.

The changes in this PR introduce a way to add a dependency array to the hook in charge of measuring the indicator size, so that we can arbitrarily recalculate. For now, Tabs is using the index of the selected tab item as the dependency, but in the future we may want to add more as needed (even use a MutationObserver).

Testing Instructions

The bug flagged in #65576 should be gone.

Screenshots or screencast

Before (trunk) After (this PR)
Kapture.2024-10-17.at.16.12.26.mp4
Kapture.2024-10-17.at.16.11.48.mp4

@ciampo ciampo self-assigned this Oct 17, 2024
@ciampo ciampo requested a review from a team October 17, 2024 14:02
@ciampo ciampo added [Type] Bug An existing feature does not function as intended [Package] Components /packages/components labels Oct 17, 2024
Comment on lines +145 to +147
// Check that the targetElement is still attached to the DOM, in case
// it was removed since the last `measure` call.
if ( targetElement && targetElement.isConnected ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a separate fix for a bug that I discovered while working on this PR. Basically, the measure function could go on an infinite loop in case the targetElement was holding a reference to an old node that in the meantime was removed from the DOM. The isConnected check makes sure that we can detect that edge case and act correctly.

An example of this:

  • in dev mode, react renders twice for the first render
  • this was causing the instanceId of the whole Tabs to update, causing also the individual Tabs.Tab buttons to update.
  • therefore, this measure function would loop indefinitely on first render

@ciampo ciampo marked this pull request as ready for review October 17, 2024 14:13
@ciampo ciampo requested a review from ajitbohra as a code owner October 17, 2024 14:13
Copy link

github-actions bot commented Oct 17, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: ciampo <[email protected]>
Co-authored-by: tyxla <[email protected]>
Co-authored-by: DaniGuardiola <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link

Flaky tests detected in 6794d66.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/11386549804
📝 Reported issues:

Copy link
Member

@tyxla tyxla left a comment

Choose a reason for hiding this comment

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

Makes sense and tests well, thanks 👍 🚀

measure();
// `measure` is a stable function, so it's safe to omit it from the deps array.
// deps can't be statically analyzed by ESLint
// eslint-disable-next-line react-hooks/exhaustive-deps
Copy link
Member

Choose a reason for hiding this comment

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

ESLint disabling is a problem for React Compiler.

I'd prefer if we leave the warning in place. There are plenty of those warnings across the codebase already. Yes, we'll have to deal with them, but that can be separately addressed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As discussed, we will address this at a later point, so that we can work across the whole reporsitory

Copy link
Member

Choose a reason for hiding this comment

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

Tackling this in #66324.

@ciampo ciampo force-pushed the fix/tabs-removal-indicator-sync branch from 6794d66 to 0c27a3f Compare October 18, 2024 11:32
@ciampo ciampo enabled auto-merge (squash) October 18, 2024 11:41
@ciampo ciampo merged commit fa12080 into trunk Oct 18, 2024
65 checks passed
@ciampo ciampo deleted the fix/tabs-removal-indicator-sync branch October 18, 2024 12:17
@github-actions github-actions bot added this to the Gutenberg 19.6 milestone Oct 18, 2024
karthick-murugan pushed a commit to karthick-murugan/gutenberg that referenced this pull request Nov 13, 2024
Co-authored-by: ciampo <[email protected]>
Co-authored-by: tyxla <[email protected]>
Co-authored-by: DaniGuardiola <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Tabs: select tab id and visual highlight are out of sync when removing tab
2 participants