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

Button: always render the Tooltip component even when a tooltip should not be shown #56490

Merged
merged 8 commits into from
Jan 24, 2024

Conversation

ciampo
Copy link
Contributor

@ciampo ciampo commented Nov 23, 2023

Fixes #56522

Requires #57202, #57878, #57975, #58125

What?

This PR tweaks the Button component so that it always renders the Tooltip component, even when a tooltip shouldn't be shown.

It also un-does the temporary fix from #56502

Why?

This change is necessary to fix the issue described in #44735, where basically the element rendered by Button would be removed and re-added to the DOM any time the Button component switches from having to show a tooltip to not having to show it, and vice-versa.

The fact that a new HTML element is re-created every time triggers a focus loss that can be very annoying, especially to assistive technology users.

How?

After some debugging, the issue seems related to the fact that React couldn't reconciliate the "with tooltip" and "without tooltip" version of the Button component without re-creating the whole button every time.

To solve this, I decided to tweak Button so that it always renders the Tooltip component.

Note: this doesn't mean that the tooltip will always be shown, though — the original user-facing behaviour should have been retained by only passing props to the Tooltip component when needed.

Testing Instructions

Testing Instructions for Keyboard

From #44735 (comment):

  • Edit a draft post and make sure it's saved so that the Save button shows the text 'Saved'.
  • Make any edit so that the button text changes to 'Save draft'.
  • Select the Save button in the dev tools inspector.
  • Right click and enable 'Break on > node removal'.
  • Click the Save button.
  • Observe the button doesn't gets removed from the DOM, and the keyboard focus stays on the button

A similar approach can also be used directly in Storybook.

Also, make sure that in general, tooltips show on Button when they are supposed to, and don't show when they are not supposed to.

@ciampo ciampo requested a review from ajitbohra as a code owner November 23, 2023 23:22
@ciampo ciampo added [Type] Bug An existing feature does not function as intended [Package] Components /packages/components labels Nov 23, 2023
@ciampo ciampo self-assigned this Nov 23, 2023
Copy link

github-actions bot commented Nov 23, 2023

Size Change: -44 B (0%)

Total Size: 1.69 MB

Filename Size Change
build/components/index.min.js 235 kB -21 B (0%)
build/editor/index.min.js 61.4 kB -23 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 955 B
build/annotations/index.min.js 2.69 kB
build/api-fetch/index.min.js 2.32 kB
build/autop/index.min.js 2.1 kB
build/blob/index.min.js 578 B
build/block-directory/index.min.js 7.22 kB
build/block-directory/style-rtl.css 1.02 kB
build/block-directory/style.css 1.02 kB
build/block-editor/content-rtl.css 4.38 kB
build/block-editor/content.css 4.38 kB
build/block-editor/default-editor-styles-rtl.css 381 B
build/block-editor/default-editor-styles.css 381 B
build/block-editor/index.min.js 249 kB
build/block-editor/style-rtl.css 15.3 kB
build/block-editor/style.css 15.3 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 126 B
build/block-library/blocks/audio/theme.css 126 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 104 B
build/block-library/blocks/avatar/style.css 104 B
build/block-library/blocks/block/editor-rtl.css 305 B
build/block-library/blocks/block/editor.css 305 B
build/block-library/blocks/button/editor-rtl.css 415 B
build/block-library/blocks/button/editor.css 414 B
build/block-library/blocks/button/style-rtl.css 627 B
build/block-library/blocks/button/style.css 626 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 239 B
build/block-library/blocks/calendar/style.css 239 B
build/block-library/blocks/categories/editor-rtl.css 113 B
build/block-library/blocks/categories/editor.css 112 B
build/block-library/blocks/categories/style-rtl.css 124 B
build/block-library/blocks/categories/style.css 124 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 421 B
build/block-library/blocks/columns/style.css 421 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 199 B
build/block-library/blocks/comment-template/style.css 198 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 647 B
build/block-library/blocks/cover/editor.css 650 B
build/block-library/blocks/cover/style-rtl.css 1.69 kB
build/block-library/blocks/cover/style.css 1.68 kB
build/block-library/blocks/details/editor-rtl.css 65 B
build/block-library/blocks/details/editor.css 65 B
build/block-library/blocks/details/style-rtl.css 98 B
build/block-library/blocks/details/style.css 98 B
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 126 B
build/block-library/blocks/embed/theme.css 126 B
build/block-library/blocks/file/editor-rtl.css 316 B
build/block-library/blocks/file/editor.css 316 B
build/block-library/blocks/file/style-rtl.css 280 B
build/block-library/blocks/file/style.css 281 B
build/block-library/blocks/file/view.min.js 316 B
build/block-library/blocks/footnotes/style-rtl.css 201 B
build/block-library/blocks/footnotes/style.css 199 B
build/block-library/blocks/form-input/editor-rtl.css 227 B
build/block-library/blocks/form-input/editor.css 227 B
build/block-library/blocks/form-input/style-rtl.css 343 B
build/block-library/blocks/form-input/style.css 343 B
build/block-library/blocks/form-submission-notification/editor-rtl.css 340 B
build/block-library/blocks/form-submission-notification/editor.css 340 B
build/block-library/blocks/form-submit-button/style-rtl.css 69 B
build/block-library/blocks/form-submit-button/style.css 69 B
build/block-library/blocks/form/view.min.js 452 B
build/block-library/blocks/freeform/editor-rtl.css 2.61 kB
build/block-library/blocks/freeform/editor.css 2.61 kB
build/block-library/blocks/gallery/editor-rtl.css 947 B
build/block-library/blocks/gallery/editor.css 952 B
build/block-library/blocks/gallery/style-rtl.css 1.72 kB
build/block-library/blocks/gallery/style.css 1.72 kB
build/block-library/blocks/gallery/theme-rtl.css 108 B
build/block-library/blocks/gallery/theme.css 108 B
build/block-library/blocks/group/editor-rtl.css 654 B
build/block-library/blocks/group/editor.css 654 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 189 B
build/block-library/blocks/heading/style.css 189 B
build/block-library/blocks/html/editor-rtl.css 336 B
build/block-library/blocks/html/editor.css 337 B
build/block-library/blocks/image/editor-rtl.css 834 B
build/block-library/blocks/image/editor.css 833 B
build/block-library/blocks/image/style-rtl.css 1.6 kB
build/block-library/blocks/image/style.css 1.59 kB
build/block-library/blocks/image/theme-rtl.css 126 B
build/block-library/blocks/image/theme.css 126 B
build/block-library/blocks/image/view.min.js 2.01 kB
build/block-library/blocks/latest-comments/style-rtl.css 357 B
build/block-library/blocks/latest-comments/style.css 357 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 478 B
build/block-library/blocks/latest-posts/style.css 478 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 505 B
build/block-library/blocks/media-text/style.css 503 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 668 B
build/block-library/blocks/navigation-link/editor.css 669 B
build/block-library/blocks/navigation-link/style-rtl.css 103 B
build/block-library/blocks/navigation-link/style.css 103 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 296 B
build/block-library/blocks/navigation-submenu/editor.css 295 B
build/block-library/blocks/navigation/editor-rtl.css 2.25 kB
build/block-library/blocks/navigation/editor.css 2.26 kB
build/block-library/blocks/navigation/style-rtl.css 2.24 kB
build/block-library/blocks/navigation/style.css 2.23 kB
build/block-library/blocks/navigation/view.min.js 1.1 kB
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 377 B
build/block-library/blocks/page-list/editor.css 377 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 235 B
build/block-library/blocks/paragraph/editor.css 235 B
build/block-library/blocks/paragraph/style-rtl.css 335 B
build/block-library/blocks/paragraph/style.css 335 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 508 B
build/block-library/blocks/post-comments-form/style.css 508 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 B
build/block-library/blocks/post-excerpt/editor-rtl.css 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 141 B
build/block-library/blocks/post-excerpt/style.css 141 B
build/block-library/blocks/post-featured-image/editor-rtl.css 666 B
build/block-library/blocks/post-featured-image/editor.css 662 B
build/block-library/blocks/post-featured-image/style-rtl.css 342 B
build/block-library/blocks/post-featured-image/style.css 342 B
build/block-library/blocks/post-navigation-link/style-rtl.css 215 B
build/block-library/blocks/post-navigation-link/style.css 214 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 409 B
build/block-library/blocks/post-template/style.css 408 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-time-to-read/style-rtl.css 69 B
build/block-library/blocks/post-time-to-read/style.css 69 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 125 B
build/block-library/blocks/preformatted/style.css 125 B
build/block-library/blocks/pullquote/editor-rtl.css 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 354 B
build/block-library/blocks/pullquote/style.css 354 B
build/block-library/blocks/pullquote/theme-rtl.css 168 B
build/block-library/blocks/pullquote/theme.css 168 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 288 B
build/block-library/blocks/query-pagination/style.css 284 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/query/editor-rtl.css 486 B
build/block-library/blocks/query/editor.css 486 B
build/block-library/blocks/query/style-rtl.css 312 B
build/block-library/blocks/query/style.css 308 B
build/block-library/blocks/query/view.min.js 642 B
build/block-library/blocks/quote/style-rtl.css 237 B
build/block-library/blocks/quote/style.css 237 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/read-more/style-rtl.css 140 B
build/block-library/blocks/read-more/style.css 140 B
build/block-library/blocks/rss/editor-rtl.css 149 B
build/block-library/blocks/rss/editor.css 149 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 184 B
build/block-library/blocks/search/editor.css 184 B
build/block-library/blocks/search/style-rtl.css 614 B
build/block-library/blocks/search/style.css 614 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/search/view.min.js 471 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 234 B
build/block-library/blocks/separator/style.css 234 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 323 B
build/block-library/blocks/shortcode/editor.css 323 B
build/block-library/blocks/site-logo/editor-rtl.css 754 B
build/block-library/blocks/site-logo/editor.css 754 B
build/block-library/blocks/site-logo/style-rtl.css 204 B
build/block-library/blocks/site-logo/style.css 204 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 682 B
build/block-library/blocks/social-links/editor.css 681 B
build/block-library/blocks/social-links/style-rtl.css 1.49 kB
build/block-library/blocks/social-links/style.css 1.49 kB
build/block-library/blocks/spacer/editor-rtl.css 348 B
build/block-library/blocks/spacer/editor.css 348 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 395 B
build/block-library/blocks/table/editor.css 395 B
build/block-library/blocks/table/style-rtl.css 639 B
build/block-library/blocks/table/style.css 639 B
build/block-library/blocks/table/theme-rtl.css 146 B
build/block-library/blocks/table/theme.css 146 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 403 B
build/block-library/blocks/template-part/editor.css 403 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/term-description/style-rtl.css 111 B
build/block-library/blocks/term-description/style.css 111 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 99 B
build/block-library/blocks/verse/style.css 99 B
build/block-library/blocks/video/editor-rtl.css 552 B
build/block-library/blocks/video/editor.css 555 B
build/block-library/blocks/video/style-rtl.css 185 B
build/block-library/blocks/video/style.css 185 B
build/block-library/blocks/video/theme-rtl.css 126 B
build/block-library/blocks/video/theme.css 126 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.1 kB
build/block-library/common.css 1.1 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 12.3 kB
build/block-library/editor.css 12.3 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/index.min.js 214 kB
build/block-library/reset-rtl.css 472 B
build/block-library/reset.css 472 B
build/block-library/style-rtl.css 14.7 kB
build/block-library/style.css 14.7 kB
build/block-library/theme-rtl.css 688 B
build/block-library/theme.css 693 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.87 kB
build/blocks/index.min.js 51.4 kB
build/commands/index.min.js 15.5 kB
build/commands/style-rtl.css 921 B
build/commands/style.css 918 B
build/components/style-rtl.css 12 kB
build/components/style.css 12.1 kB
build/compose/index.min.js 12.6 kB
build/core-commands/index.min.js 2.71 kB
build/core-data/index.min.js 72.7 kB
build/customize-widgets/index.min.js 12.1 kB
build/customize-widgets/style-rtl.css 1.34 kB
build/customize-widgets/style.css 1.33 kB
build/data-controls/index.min.js 640 B
build/data/index.min.js 8.92 kB
build/date/index.min.js 17.8 kB
build/deprecated/index.min.js 451 B
build/dom-ready/index.min.js 324 B
build/dom/index.min.js 4.65 kB
build/edit-post/classic-rtl.css 544 B
build/edit-post/classic.css 545 B
build/edit-post/index.min.js 25 kB
build/edit-post/style-rtl.css 5.62 kB
build/edit-post/style.css 5.61 kB
build/edit-site/index.min.js 195 kB
build/edit-site/style-rtl.css 15.2 kB
build/edit-site/style.css 15.2 kB
build/edit-widgets/index.min.js 17.3 kB
build/edit-widgets/style-rtl.css 4.39 kB
build/edit-widgets/style.css 4.39 kB
build/editor/style-rtl.css 5.43 kB
build/editor/style.css 5.43 kB
build/element/index.min.js 4.83 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 7.93 kB
build/format-library/style-rtl.css 478 B
build/format-library/style.css 477 B
build/hooks/index.min.js 1.55 kB
build/html-entities/index.min.js 448 B
build/i18n/index.min.js 3.58 kB
build/interactivity/file.min.js 440 B
build/interactivity/image.min.js 2.15 kB
build/interactivity/index.min.js 13.3 kB
build/interactivity/navigation.min.js 1.23 kB
build/interactivity/query.min.js 789 B
build/interactivity/search.min.js 610 B
build/is-shallow-equal/index.min.js 527 B
build/keyboard-shortcuts/index.min.js 1.74 kB
build/keycodes/index.min.js 1.46 kB
build/list-reusable-blocks/index.min.js 2.11 kB
build/list-reusable-blocks/style-rtl.css 836 B
build/list-reusable-blocks/style.css 836 B
build/media-utils/index.min.js 2.9 kB
build/modules/importmap-polyfill.min.js 12.2 kB
build/notices/index.min.js 948 B
build/nux/index.min.js 2 kB
build/nux/style-rtl.css 735 B
build/nux/style.css 732 B
build/patterns/index.min.js 5.45 kB
build/patterns/style-rtl.css 540 B
build/patterns/style.css 539 B
build/plugins/index.min.js 1.8 kB
build/preferences-persistence/index.min.js 2.07 kB
build/preferences/index.min.js 2.81 kB
build/preferences/style-rtl.css 698 B
build/preferences/style.css 700 B
build/primitives/index.min.js 975 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 1 kB
build/react-i18n/index.min.js 623 B
build/react-refresh-entry/index.min.js 9.47 kB
build/react-refresh-runtime/index.min.js 6.78 kB
build/redux-routine/index.min.js 2.7 kB
build/reusable-blocks/index.min.js 2.72 kB
build/reusable-blocks/style-rtl.css 243 B
build/reusable-blocks/style.css 243 B
build/rich-text/index.min.js 10.4 kB
build/router/index.min.js 1.79 kB
build/server-side-render/index.min.js 1.95 kB
build/shortcode/index.min.js 1.39 kB
build/style-engine/index.min.js 2.05 kB
build/token-list/index.min.js 582 B
build/url/index.min.js 3.72 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.8 kB
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 957 B
build/warning/index.min.js 249 B
build/widgets/index.min.js 7.21 kB
build/widgets/style-rtl.css 1.15 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.02 kB

compressed-size-action

Copy link
Contributor

@afercia afercia left a comment

Choose a reason for hiding this comment

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

Thanks @ciampo for working on this 🙏
I can confirm that with this PR the focus loss doesn't occur any longer.

@ciampo ciampo requested a review from tyxla November 24, 2023 10:07
@ciampo
Copy link
Contributor Author

ciampo commented Nov 24, 2023

It looks like some Tooltip unit tests are failing, I'll look into it.

@ciampo
Copy link
Contributor Author

ciampo commented Nov 24, 2023

After taking a look, failures seem related to the fact that Tooltip tests use Button internally. Swapping the Button component with the button HTML element causes the tests to pass correctly.

With the changes from this PR, since Button always internally renders a Tooltip, rendering <Tooltip><Button /></Tooltip> effectively results in two Tooltip components being nested: <Tooltip><Tooltip>{/* button contents */}</Tooltip></Tooltip>.

I would argue that this scenario has been around on trunk for a while and that the changes from this PR have only made it easier to spot. At the same time, this PR would, unfortunately, introduce a regression to any consumer that is rendering <Tooltip><Button /></Tooltip>.

We have two main approaches that we could take:

  • we can argue that Button was never meant to be rendered inside a Tooltip, since it already comes with Tooltip functionality. We tweak Tooltip unit tests to render an HTML button, and we merge this PR (knowing that it could introduce regressions for folks rendering Button inside a Tooltip.
  • or we take a more conservative approach and avoid "amplifying" this regression (which is already on trunk, but harder to trigger). This means that we'll have to find an alternative approach to this fix. A short-term solution could be to render a Tooltip around the Button for the save button (to be tested).

What do folks think?

@ciampo
Copy link
Contributor Author

ciampo commented Nov 24, 2023

  • A short-term solution could be to render a Tooltip around the Button for the save button (to be tested).

Alternative solution (specific to the save button) in #56502

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.

This is a fair compromise IMHO 👍

This PR would, unfortunately, introduce a regression to any consumer that is rendering <Tooltip><Button /></Tooltip>

Is it even possible that there is such an instance existing and it's not broken in the same way as the test breaks?

packages/components/src/button/index.tsx Outdated Show resolved Hide resolved
packages/components/src/button/index.tsx Outdated Show resolved Hide resolved
packages/editor/src/components/post-saved-state/index.js Outdated Show resolved Hide resolved
@ciampo
Copy link
Contributor Author

ciampo commented Nov 24, 2023

Is it even possible that there is such an instance existing and it's not broken in the same way as the test breaks?

Right now, a consumer may render <Tooltip><Button /></Tooltip> without issues, in case the Button doesn't also internally render a Tooltip. With the changes from this PR, Button would always render a Tooltip, which causes the <Tooltip><Button /></Tooltip> pattern to never work.


This is a fair compromise IMHO 👍

I will also try one more approach using the key prop to force the hand with React's reconciliation, although I'm not sure if it will work.

@ciampo
Copy link
Contributor Author

ciampo commented Nov 25, 2023

I will also try one more approach using the key prop to force the hand with React's reconciliation, although I'm not sure if it will work.

Opened #56527, although I'm not managing to fix the issue.

We may have to resort to using the fix proposed in this PR. In order to mitigate the disruption, one potential fix may be to add some logic to the Tooltip component so that, if an instance of Tooltip detects being rendered inside another Tooltip, it will "disable" its tooltip functionality — so that only the topmost Tooltip actually renders a tooltip. We could also render a warning to the console letting devs know that a tooltip was suppressed because it was nested in another tooltip.

Let me know if this sounds like a good ide.

@tyxla
Copy link
Member

tyxla commented Nov 27, 2023

Right now, a consumer may render <Tooltip><Button /></Tooltip> without issues, in case the Button doesn't also internally render a Tooltip. With the changes from this PR, Button would always render a Tooltip, which causes the <Tooltip><Button /></Tooltip> pattern to never work.

This is definitely not great and could potentially break existing usages.

We may have to resort to using the fix proposed in this PR. In order to mitigate the disruption, one potential fix may be to add some logic to the Tooltip component so that, if an instance of Tooltip detects being rendered inside another Tooltip, it will "disable" its tooltip functionality — so that only the topmost Tooltip actually renders a tooltip. We could also render a warning to the console letting devs know that a tooltip was suppressed because it was nested in another tooltip.

I think this sounds like a good compromise. Do we have any usages in the Gutenberg core that will be affected?

Comment on lines +198 to +200
( ( showTooltip && !! label ) ||
// There's a shortcut or...
shortcut ||
!! shortcut ||
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Making sure that shouldShowTooltip is an actual boolean

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changes in this file mostly undo the temporary fix from #56502

@ciampo
Copy link
Contributor Author

ciampo commented Dec 19, 2023

Update:

  • I opened a PR with changes to support nested Tooltip components (ie. only the outer Tooltip component displays a tooltip)
  • While testing changes, I noticed a regression related to the tooltip not hiding when the anchor is blurred. I opened an issue and a PR with a potential fix

Until #57202 (or any alternative solution) is merged, this PR will stay on hold.

@ciampo ciampo force-pushed the fix/button-tooltip-re-render branch from 1e657eb to 95824d5 Compare January 11, 2024 16:57
@ciampo
Copy link
Contributor Author

ciampo commented Jan 11, 2024

Rebased to include changes from #57202. Will look into unit test failures — there may be some extra unintended consequences when nesting tooltips in Button (ie. class names being overwritten)

@ciampo
Copy link
Contributor Author

ciampo commented Jan 16, 2024

Rebased to include changes from #57202. Will look into unit test failures — there may be some extra unintended consequences when nesting tooltips in Button (ie. class names being overwritten)

There was indeed an issue with how props were forwarded / merged / passed to the children of the inner Tooltip components. The issue was investigated and discussed in this conversation, and I've now opened a separate PR to test it and merge it in isolation.

I will rebase this PR on top of trunk once #57878 is merged

@ciampo ciampo force-pushed the fix/button-tooltip-re-render branch from e66abe6 to ad3b6f5 Compare January 23, 2024 14:58
@ciampo ciampo requested review from afercia and tyxla January 23, 2024 15:25
@ciampo ciampo force-pushed the fix/button-tooltip-re-render branch from 6c052b7 to 250350c Compare January 23, 2024 15:27
@ciampo
Copy link
Contributor Author

ciampo commented Jan 23, 2024

With #57878, #57975 and #58125 merged, we should be finally ready for a final round of reviews.

I've also added a unit test which should fail on trunk and pass on this PR.

@ciampo ciampo requested a review from mirka January 23, 2024 15:27
@ciampo ciampo force-pushed the fix/button-tooltip-re-render branch from 250350c to 03404d4 Compare January 23, 2024 15:53
Copy link
Member

@mirka mirka left a comment

Choose a reason for hiding this comment

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

Code looks good, and is testing well 🚀

Comment on lines -253 to -257
let computedPlacement;
// if `tooltipPosition` is defined, compute value to `placement`
if ( tooltipPosition !== undefined ) {
computedPlacement = positionToPlacement( tooltipPosition );
}
Copy link
Member

Choose a reason for hiding this comment

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

Nice simplification here 👍

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.

Works well in my testing. Thanks @ciampo 🚀

packages/components/src/button/test/index.tsx Show resolved Hide resolved
@ciampo ciampo force-pushed the fix/button-tooltip-re-render branch from 03404d4 to 36fea4d Compare January 24, 2024 13:17
@ciampo ciampo enabled auto-merge (squash) January 24, 2024 13:18
@ciampo ciampo merged commit c87e338 into trunk Jan 24, 2024
57 checks passed
@ciampo ciampo deleted the fix/button-tooltip-re-render branch January 24, 2024 13:59
@github-actions github-actions bot added this to the Gutenberg 17.6 milestone Jan 24, 2024
@ellatrix
Copy link
Member

ellatrix commented Nov 6, 2024

@ciampo Why would a button switch from having a tooltip to not having a tooltip while it's rendered in the DOM? What's the use case?

Edit: I read the testing instructions, so the save button :)

@ellatrix
Copy link
Member

ellatrix commented Nov 6, 2024

This is causing so much work to be done for buttons that never even show a tooltip. More often than not, buttons never have a tooltip. Why is this there even a tooltip option for a button, why is this not an optional wrapper component?

@mirka
Copy link
Member

mirka commented Nov 12, 2024

More often than not, buttons never have a tooltip. Why is this there even a tooltip option for a button, why is this not an optional wrapper component?

FWIW, I would definitely not include a tooltip (and its floating-ui dependencies) if we were to design a Button component from scratch. Maybe in a v2!

@ciampo
Copy link
Contributor Author

ciampo commented Nov 26, 2024

This is causing so much work to be done for buttons that never even show a tooltip. More often than not, buttons never have a tooltip. Why is this there even a tooltip option for a button, why is this not an optional wrapper component?

@ellatrix These are all correct questions that we also asked ourselves. Unfortunately the decision to include the Tooltip component inside the Button component was made before I started working on Gutenberg; and the backwards compat policy forces us to keep around.

I agree with your observations and, as also Lena said, if we were to build a Button component from scratch, we would keep the component very focused on button functionality —Tooltip functionality would be delegated to a separate Tooltip component.

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.

Button creates new HTML elements every time it internally flips between showing tooltips or not
6 participants