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

Make SaveButton extensible #56807

Open
wants to merge 7 commits into
base: trunk
Choose a base branch
from
Open

Make SaveButton extensible #56807

wants to merge 7 commits into from

Conversation

okmttdhr
Copy link
Contributor

@okmttdhr okmttdhr commented Dec 6, 2023

What?

This Pull Request introduces enhancements to the SaveButton component, aimed at adding its extensibility within client applications of Gutenberg. Key improvements include the button label, and the action triggered when the button is clicked.

Why?

The primary goal of these enhancements is to improve the adaptability of the SaveButton within client applications, particularly in scenarios where user interaction necessitates a context-specific response.

Example

An example of the necessity for these enhancements can be seen on WordPress.com. Say a user is previewing a block theme; if the user does not have the required plan for the previewing theme, SaveButton needs to do more than just save changes. In this case, the button should redirect the user to the plan checkout page (c.f., Automattic/wp-calypso#79223).

This example underlines the need for a SaveButton that is not only context-aware but also capable of performing the actions based on the requirements of the client application. By implementing these, we enable a more responsive UX, tailored to the specific conditions of the user's interaction within the client application.

How?

The approach taken to enable these enhancements is minimalist, utilizing the existing getSettings() store.
Update: The approach is done by using applyFilters in @wordpress/hooks.

The Slot/Fill approach was considered but not used. The rationale behind this is that Slot/Fill, while appropriate for replacing entire UI elements, would be an overextension for the future use case. Our aim was to enhance, not replace, the existing SaveButton UI.

Another considered approach was dynamically adding event listeners to the button (in this case, we don't change anything on the Gutenberg side). However, this was deemed less ideal compared to having a dedicated customization point within the SaveButton itself.

Testing Instructions

  • Go to Appearance > Editor
  • Edit your content
  • Click the customized "SaveButton"
  • See the custom action and label
Screen.Recording.2023-12-08.at.16.53.33.2.mov

Copy link

github-actions bot commented Dec 6, 2023

Size Change: +157 B (0%)

Total Size: 1.71 MB

Filename Size Change
build/edit-site/index.min.js 194 kB +157 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 964 B
build/annotations/index.min.js 2.71 kB
build/api-fetch/index.min.js 2.29 kB
build/autop/index.min.js 2.11 kB
build/blob/index.min.js 590 B
build/block-directory/index.min.js 7.25 kB
build/block-directory/style-rtl.css 1.04 kB
build/block-directory/style.css 1.04 kB
build/block-editor/content-rtl.css 4.29 kB
build/block-editor/content.css 4.28 kB
build/block-editor/default-editor-styles-rtl.css 403 B
build/block-editor/default-editor-styles.css 403 B
build/block-editor/index.min.js 247 kB
build/block-editor/style-rtl.css 15.4 kB
build/block-editor/style.css 15.4 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 138 B
build/block-library/blocks/audio/theme.css 138 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 587 B
build/block-library/blocks/button/editor.css 587 B
build/block-library/blocks/button/style-rtl.css 633 B
build/block-library/blocks/button/style.css 632 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.7 kB
build/block-library/blocks/cover/style.css 1.69 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 138 B
build/block-library/blocks/embed/theme.css 138 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 322 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 229 B
build/block-library/blocks/form-input/editor.css 228 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 343 B
build/block-library/blocks/form-submission-notification/editor.css 342 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 957 B
build/block-library/blocks/gallery/editor.css 962 B
build/block-library/blocks/gallery/style-rtl.css 1.75 kB
build/block-library/blocks/gallery/style.css 1.75 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 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 340 B
build/block-library/blocks/html/editor.css 341 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.61 kB
build/block-library/blocks/image/style.css 1.6 kB
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/image/view.min.js 2.02 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 671 B
build/block-library/blocks/navigation-link/editor.css 672 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 299 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation/editor-rtl.css 2.26 kB
build/block-library/blocks/navigation/editor.css 2.26 kB
build/block-library/blocks/navigation/style-rtl.css 2.27 kB
build/block-library/blocks/navigation/style.css 2.26 kB
build/block-library/blocks/navigation/view.min.js 1.04 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 401 B
build/block-library/blocks/page-list/editor.css 401 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 345 B
build/block-library/blocks/post-featured-image/style.css 345 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 335 B
build/block-library/blocks/pullquote/style.css 335 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 647 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 613 B
build/block-library/blocks/search/style.css 613 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 475 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 329 B
build/block-library/blocks/shortcode/editor.css 329 B
build/block-library/blocks/site-logo/editor-rtl.css 760 B
build/block-library/blocks/site-logo/editor.css 760 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 359 B
build/block-library/blocks/spacer/editor.css 359 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 432 B
build/block-library/blocks/table/editor.css 432 B
build/block-library/blocks/table/style-rtl.css 646 B
build/block-library/blocks/table/style.css 645 B
build/block-library/blocks/table/theme-rtl.css 157 B
build/block-library/blocks/table/theme.css 157 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 191 B
build/block-library/blocks/video/style.css 191 B
build/block-library/blocks/video/theme-rtl.css 139 B
build/block-library/blocks/video/theme.css 139 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.11 kB
build/block-library/common.css 1.11 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.5 kB
build/block-library/editor.css 12.4 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/index.min.js 213 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 700 B
build/block-library/theme.css 705 B
build/block-serialization-default-parser/index.min.js 1.13 kB
build/block-serialization-spec-parser/index.min.js 2.87 kB
build/blocks/index.min.js 51.3 kB
build/commands/index.min.js 15.5 kB
build/commands/style-rtl.css 947 B
build/commands/style.css 942 B
build/components/index.min.js 257 kB
build/components/style-rtl.css 12.1 kB
build/components/style.css 12.1 kB
build/compose/index.min.js 12.8 kB
build/core-commands/index.min.js 2.73 kB
build/core-data/index.min.js 72.6 kB
build/customize-widgets/index.min.js 12.1 kB
build/customize-widgets/style-rtl.css 1.36 kB
build/customize-widgets/style.css 1.36 kB
build/data-controls/index.min.js 651 B
build/data/index.min.js 8.87 kB
build/date/index.min.js 17.9 kB
build/deprecated/index.min.js 462 B
build/dom-ready/index.min.js 336 B
build/dom/index.min.js 4.68 kB
build/edit-post/classic-rtl.css 571 B
build/edit-post/classic.css 571 B
build/edit-post/index.min.js 32.8 kB
build/edit-post/style-rtl.css 7.44 kB
build/edit-post/style.css 7.43 kB
build/edit-site/style-rtl.css 14.5 kB
build/edit-site/style.css 14.6 kB
build/edit-widgets/index.min.js 17.3 kB
build/edit-widgets/style-rtl.css 4.71 kB
build/edit-widgets/style.css 4.71 kB
build/editor/index.min.js 52.4 kB
build/editor/style-rtl.css 4.32 kB
build/editor/style.css 4.32 kB
build/element/index.min.js 4.87 kB
build/escape-html/index.min.js 548 B
build/format-library/index.min.js 7.76 kB
build/format-library/style-rtl.css 577 B
build/format-library/style.css 577 B
build/hooks/index.min.js 1.57 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.61 kB
build/interactivity/file.min.js 442 B
build/interactivity/image.min.js 2.15 kB
build/interactivity/index.min.js 12.5 kB
build/interactivity/navigation.min.js 1.16 kB
build/interactivity/query.min.js 791 B
build/interactivity/search.min.js 610 B
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.76 kB
build/keycodes/index.min.js 1.49 kB
build/list-reusable-blocks/index.min.js 2.11 kB
build/list-reusable-blocks/style-rtl.css 865 B
build/list-reusable-blocks/style.css 865 B
build/media-utils/index.min.js 2.92 kB
build/modules/importmap-polyfill.min.js 12.2 kB
build/notices/index.min.js 964 B
build/nux/index.min.js 2.01 kB
build/nux/style-rtl.css 775 B
build/nux/style.css 771 B
build/patterns/index.min.js 5.28 kB
build/patterns/style-rtl.css 564 B
build/patterns/style.css 564 B
build/plugins/index.min.js 1.81 kB
build/preferences-persistence/index.min.js 1.85 kB
build/preferences/index.min.js 1.26 kB
build/primitives/index.min.js 994 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 994 B
build/react-i18n/index.min.js 631 B
build/react-refresh-entry/index.min.js 9.46 kB
build/react-refresh-runtime/index.min.js 6.78 kB
build/redux-routine/index.min.js 2.71 kB
build/reusable-blocks/index.min.js 2.74 kB
build/reusable-blocks/style-rtl.css 265 B
build/reusable-blocks/style.css 265 B
build/rich-text/index.min.js 10.5 kB
build/router/index.min.js 1.79 kB
build/server-side-render/index.min.js 1.96 kB
build/shortcode/index.min.js 1.4 kB
build/style-engine/index.min.js 1.98 kB
build/token-list/index.min.js 587 B
build/url/index.min.js 3.83 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 967 B
build/warning/index.min.js 259 B
build/widgets/index.min.js 7.18 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.18 kB
build/wordcount/index.min.js 1.03 kB

compressed-size-action

Copy link

github-actions bot commented Dec 6, 2023

Flaky tests detected in 055dcaf.
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/7138758765
📝 Reported issues:

@okmttdhr okmttdhr changed the title Make SaveButton extensible Make SaveButton extensible Dec 6, 2023
@okmttdhr okmttdhr marked this pull request as ready for review December 6, 2023 05:52
Comment on lines 79 to 88
// For testing
const { updateSettings } = useDispatch( editSiteStore );
useEffect( () => {
updateSettings( {
__experimentalSaveButtonAction: () =>
// eslint-disable-next-line no-console
console.log( 'Customized Action' ),
__experimentalSaveButtonLabel: 'Customized Action',
} );
}, [ updateSettings ] );
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll revert this diff after testing. 9929ca0

Copy link
Contributor

Choose a reason for hiding this comment

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

Don't forget to do this!

@scruffian
Copy link
Contributor

Are you sure this is going to be sufficient? There are more buttons and actions behind this one:

Screenshot 2023-12-06 at 11 59 44 Screenshot 2023-12-06 at 12 04 47

Will it also be necessary to modify these?

Also is there a way for the client to control whether or not the default actions also happen?

@okmttdhr
Copy link
Contributor Author

okmttdhr commented Dec 7, 2023

Are you sure this is going to be sufficient? There are more buttons and actions behind this one:

Screenshot 2023-12-06 at 11 59 44 Screenshot 2023-12-06 at 12 04 47
Will it also be necessary to modify these?

In the context of WordPress.com's needs, the current focus is specifically on customizing the behavior in such a way that the SavePanel (the above UI) does not need to be displayed at all. Therefore, there isn't a requirement to modify other elements like SavePanel in this particular instance.

Also is there a way for the client to control whether or not the default actions also happen?

The current implementation is like a "full customization with full responsibility" approach. This means there's no way to run default actions alongside custom ones. However, in scenarios where such a need arises, clients have the flexibility to invoke setIsSaveViewOpened within their customizedSaveButtonAction. This provides a workaround to trigger specific default behaviors if needed.

Looking ahead, considering potential future complexities with SaveButton, a more flexible implementation might be as follows;

const onClick = () => {
  if (customizedSaveButtonActionBefore) {
    customizedSaveButtonActionBefore();
  }
  if (!skipOriginal) {
    setIsSaveViewOpened(true);
  }
  if (customizedSaveButtonActionAfter) {
    customizedSaveButtonActionAfter();
  }
};

I'm not yet sure if SaveButton needs this flexibility. In my opinion, keeping the current approach and seeing how it adapts to future use cases seems to be okay. What do you think?

alexstine

This comment was marked as resolved.

@okmttdhr

This comment was marked as resolved.

Copy link
Contributor

@arthur791004 arthur791004 left a comment

Choose a reason for hiding this comment

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

Instead of using settings, would it be better to use applyFilters to allow clients to customize the behavior?

For example,

const label = applyFilters( 'edit-site.SaveButton.label', getLabel(), { isPreviewingTheme, isSaving, ... } );

const onClick = applyFilters(
  'edit-site.SaveButton.onClick', 
  () => setIsSaveViewOpened( true ),
  options,
);

Additionally, we can add comments to describe we only want to focus on the SaveButton, and we will provide the customization to the other entry points (e.g.: SavePanel, SaveHub, EntitiesSavedStatesExtensible) in the future if needed.

packages/edit-site/src/components/save-button/index.js Outdated Show resolved Hide resolved
@okmttdhr
Copy link
Contributor Author

okmttdhr commented Dec 8, 2023

Thank you for your review, @arthur791004!

Instead of using settings, would it be better to use applyFilters to allow clients to customize the behavior?

I did not know that, and it looks much better to me in this case!

@okmttdhr okmttdhr force-pushed the add/save-button-customize branch from 7f288c7 to 6c185c6 Compare December 8, 2023 07:35
@okmttdhr okmttdhr force-pushed the add/save-button-customize branch from 6c185c6 to 6951167 Compare December 8, 2023 07:38
@okmttdhr okmttdhr force-pushed the add/save-button-customize branch from 6951167 to f01589b Compare December 8, 2023 07:39
@okmttdhr
Copy link
Contributor Author

okmttdhr commented Dec 8, 2023

Instead of using settings, would it be better to use applyFilters to allow clients to customize the behavior?

I changed to use applyFilters. Could you take a look again? 🙏 @arthur791004

@okmttdhr okmttdhr requested a review from arthur791004 December 8, 2023 07:58
Copy link
Contributor

@arthur791004 arthur791004 left a comment

Choose a reason for hiding this comment

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

Looks good 🎉

const callback = applyFilters( 'edit-site.SaveButton.onClick', () =>
setIsSaveViewOpened( true )
);
callback();
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can just return the function but it's optional 🙂

Copy link
Contributor

Choose a reason for hiding this comment

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

I like this idea too.

return applyFilters( 'edit-site.SaveButton.label', getLabel(), {
isSaving,
disabled,
isPreviewingTheme,
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be better to add it to the deps as well even if it won't be changed.

But the naming is still confusing as people may not notice it's a function instead of the boolean value. However, it's out of the scope of this PR 🙂

setIsSaveViewOpened( true )
);
callback();
}, [ setIsSaveViewOpened ] );
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we also add the dependencies here. Did you get a warning? See #24914

Copy link
Contributor

@scruffian scruffian left a comment

Choose a reason for hiding this comment

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

Great work on the filter. LGTM

const callback = applyFilters( 'edit-site.SaveButton.onClick', () =>
setIsSaveViewOpened( true )
);
callback();
Copy link
Contributor

Choose a reason for hiding this comment

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

I like this idea too.

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

I think we should avoid adding a filter for now. We're still working on unifying the experience between post and site editors and both have different flows, different UIs and different actions. This is going to prevent us from doing this kind of improvement in the future and kind of "freeze" the work.

@scruffian
Copy link
Contributor

@youknowriad what do you think about the previous approach, using the editor settings?

@draganescu
Copy link
Contributor

I don't have enough arguments to block this but it's a bit weird to add these filters, because why not filter every single button to have a different event handler and label. Then maybe filter all the other possible handlers :) All filters once they land are there, as we know, forever.

I also don't want to bring the filters are expensive argument 'cause I am not sure this is always true.

However, I do wonder if implementers hitting issues like the one described in the PR's description should hook into and filter core, or instead implement a recomposed experience? And if this is impossible the question is why, and where do our components come short in terms of allowing 3rd parties to re-compose different experiences with the same foundation?

It feels like the front end is in less need of filters more in need of easy composability ...

@okmttdhr
Copy link
Contributor Author

I think we should avoid adding a filter for now. We're still working on unifying the experience between post and site editors and both have different flows, different UIs and different actions. This is going to prevent us from doing this kind of improvement in the future and kind of "freeze" the work.

Thanks for your feedback, @youknowriad. I understand the concern about potentially hindering future unification efforts.
I'd appreciate it if you provide your thoughts about the previous approach (as @scruffian said) or an alternative approach. 🙂

However, I do wonder if implementers hitting issues like the one described in the PR's description should hook into and filter core, or instead implement a recomposed experience? And if this is impossible the question is why, and where do our components come short in terms of allowing 3rd parties to re-compose different experiences with the same foundation?

Thank you for your insights, @draganescu. 🙂

Could you please elaborate on how you envision "re-compose different experiences"?

Currently, without changing the Gutenberg side, the lack of customizability would force implementers to resort to fragile methods like dynamically adding event handlers. I thought that providing a more 'official' to customize components in Gutenberg could improve maintainability and flexibility for developers.
So, I would very much appreciate it if we had other robust solutions!

@draganescu
Copy link
Contributor

draganescu commented Dec 13, 2023

Could you please elaborate on how you envision "re-compose different experiences"?

@okmttdhr I don't really have a vision more like a hope. Briefly put if the experience in core differs from implementation needs, in the browser we should be able to recompose a new preview "screen" based on the same components in core, except the save button.

I don't know that this is feasible or possible right away today without automatically creating technical debt in the implementation by diverging from core but it's good I think to aim for this. Ideally, in the client we can repurpose the components that build the client experience.

Coming back to this particular problem I wonder if it's not safer to make the whole save button swappable rather than filtering bits of it? This is more inline with the idea of composability. In other words,

The Slot/Fill approach [was considered but not used. The rationale behind this is that Slot/Fill, while appropriate for replacing entire UI elements, would be an overextension for the future use case. Our aim was to enhance, not replace, the existing SaveButton UI].

... is to me more correct from a birds eye perspective. I am not sure what "overextension for the future use case" means?

@okmttdhr
Copy link
Contributor Author

okmttdhr commented Dec 14, 2023

I am not sure what "overextension for the future use case" means?

I thought, within Gutenberg, that maintaining a consistent user experience is crucial even if implementers want to change some behavior. The SaveButton, as a primary action within the Site Editor, plays a key role in this experience. So, my idea was that limiting the customizability of key UI would contribute to keeping the "quality" of Gutenberg, rather than allowing them to add any kind of UI. 😃

Also, I can imagine scenarios where the behavior of the SaveButton is changed, such as displaying confetti-like UI or providing guidance after a save action. However, I'm unsure whether there is a use case for completely replacing the UI of the main action button. (In this instance, introducing the Slot/Fill method for adding supplementary UI elements, like those positioned above the SaveButton, might seem appropriate. But using it to completely replace the button might not look ideal to me.)

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

I have been thinking about this and the truth is, I don't have a better alternative to offer, so I'm removing my blocking review. That said, I think there's a couple of things we need to do first:

  • applyFilters is not reactive, I think we should build a useFilters hook that works similarly to withFilters HoC and reacts to filters being removed and added.
  • I believe to start we should limit these filters to the "Gutenberg plugin" usage only to prevent them to leak to WordPress Core until we decide that this approach is ok to move forward with and support forever.

@youknowriad youknowriad dismissed their stale review December 15, 2023 15:07

No alternative, see previous comment for remaining concerns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants