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

Add paste styles to the block settings #45477

Merged
merged 9 commits into from
Jan 9, 2023
Merged

Conversation

kevin940726
Copy link
Member

What?

A partial solution to #44418. Allow pasting styles of the copied blocks to the selected blocks.

Why?

See #44418.

How?

I don't think we need a separate "Copy styles" action since that the copied blocks should already contain that information. Instead, we can only provide a separate "Paste styles" action to selectively paste/apply only the styles to the selected blocks.

Which attributes should be considered "styles attributes" is debatable. This PR mark all attributes as styles attributes except for the ones that have __experimentalRole of content. We can discuss it and further refine this logic though. One possible idea is to assign __experimentalRole: "style" to the attributes.

pasteStyles() will recursively handle the inner blocks but it won't check for block names. That is, the common styles will be applied if the copied blocks are different from the target blocks. This decision is made because most blocks have many common attributes like padding/margin or text color. We can discuss it further and decide if we want to only allow pasting styles to the same block type, though.

If there's only one (top-level) copied block, all the selected blocks will be applied to the same styles. Else if there are multiple copied blocks, only the minimum common blocks will be applied to the styles. This could be kind of confusing sometimes, but I think it matches what the users expect most of the time.

Worth noting that for security reasons, reading from the clipboard requires additional permissions. If permission is denied, we'll show a warning snackbar to notify the user. Different browsers have different ways to ask for permissions natively.

Testing Instructions

  1. Open a post or page.
  2. Insert some blocks and apply some styles to them.
  3. Copy the block(s).
  4. Create some more blocks.
  5. Select them and paste the styles.
  6. Try different combinations (inner blocks, multiple copied blocks, multiple selected blocks).

Screenshots or screencast

Kapture.2022-11-02.at.14.19.50.mp4

@kevin940726 kevin940726 added the [Type] Enhancement A suggestion for improvement. label Nov 2, 2022
@codesandbox
Copy link

codesandbox bot commented Nov 2, 2022

CodeSandbox logoCodeSandbox logo  Open in CodeSandbox Web Editor | VS Code | VS Code Insiders

@github-actions
Copy link

github-actions bot commented Nov 2, 2022

Size Change: +960 B (0%)

Total Size: 1.32 MB

Filename Size Change
build/block-editor/index.min.js 183 kB +960 B (+1%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 993 B
build/annotations/index.min.js 2.78 kB
build/api-fetch/index.min.js 2.27 kB
build/autop/index.min.js 2.15 kB
build/blob/index.min.js 487 B
build/block-directory/index.min.js 7.16 kB
build/block-directory/style-rtl.css 1.04 kB
build/block-directory/style.css 1.04 kB
build/block-editor/content-rtl.css 2.71 kB
build/block-editor/content.css 2.71 kB
build/block-editor/default-editor-styles-rtl.css 403 B
build/block-editor/default-editor-styles.css 403 B
build/block-editor/style-rtl.css 14.8 kB
build/block-editor/style.css 14.8 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 84 B
build/block-library/blocks/avatar/style.css 84 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 485 B
build/block-library/blocks/button/editor.css 485 B
build/block-library/blocks/button/style-rtl.css 532 B
build/block-library/blocks/button/style.css 532 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 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 100 B
build/block-library/blocks/categories/style.css 100 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 406 B
build/block-library/blocks/columns/style.css 406 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 612 B
build/block-library/blocks/cover/editor.css 613 B
build/block-library/blocks/cover/style-rtl.css 1.57 kB
build/block-library/blocks/cover/style.css 1.56 kB
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 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 253 B
build/block-library/blocks/file/style.css 254 B
build/block-library/blocks/file/view.min.js 353 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 984 B
build/block-library/blocks/gallery/editor.css 988 B
build/block-library/blocks/gallery/style-rtl.css 1.55 kB
build/block-library/blocks/gallery/style.css 1.55 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 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/html/editor-rtl.css 332 B
build/block-library/blocks/html/editor.css 333 B
build/block-library/blocks/image/editor-rtl.css 829 B
build/block-library/blocks/image/editor.css 828 B
build/block-library/blocks/image/style-rtl.css 627 B
build/block-library/blocks/image/style.css 630 B
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/latest-comments/style-rtl.css 298 B
build/block-library/blocks/latest-comments/style.css 298 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 507 B
build/block-library/blocks/media-text/style.css 505 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 716 B
build/block-library/blocks/navigation-link/editor.css 715 B
build/block-library/blocks/navigation-link/style-rtl.css 115 B
build/block-library/blocks/navigation-link/style.css 115 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.13 kB
build/block-library/blocks/navigation/editor.css 2.14 kB
build/block-library/blocks/navigation/style-rtl.css 2.22 kB
build/block-library/blocks/navigation/style.css 2.2 kB
build/block-library/blocks/navigation/view-modal.min.js 2.81 kB
build/block-library/blocks/navigation/view.min.js 447 B
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 376 B
build/block-library/blocks/page-list/editor.css 376 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 174 B
build/block-library/blocks/paragraph/editor.css 174 B
build/block-library/blocks/paragraph/style-rtl.css 279 B
build/block-library/blocks/paragraph/style.css 281 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 501 B
build/block-library/blocks/post-comments-form/style.css 501 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 73 B
build/block-library/blocks/post-excerpt/editor.css 73 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B
build/block-library/blocks/post-excerpt/style.css 69 B
build/block-library/blocks/post-featured-image/editor-rtl.css 586 B
build/block-library/blocks/post-featured-image/editor.css 584 B
build/block-library/blocks/post-featured-image/style-rtl.css 318 B
build/block-library/blocks/post-featured-image/style.css 318 B
build/block-library/blocks/post-navigation-link/style-rtl.css 153 B
build/block-library/blocks/post-navigation-link/style.css 153 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 282 B
build/block-library/blocks/post-template/style.css 282 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-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 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 326 B
build/block-library/blocks/pullquote/style.css 325 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 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 440 B
build/block-library/blocks/query/editor.css 440 B
build/block-library/blocks/quote/style-rtl.css 213 B
build/block-library/blocks/quote/style.css 213 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 132 B
build/block-library/blocks/read-more/style.css 132 B
build/block-library/blocks/rss/editor-rtl.css 202 B
build/block-library/blocks/rss/editor.css 204 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 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 409 B
build/block-library/blocks/search/style.css 406 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 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 474 B
build/block-library/blocks/shortcode/editor.css 474 B
build/block-library/blocks/site-logo/editor-rtl.css 490 B
build/block-library/blocks/site-logo/editor.css 490 B
build/block-library/blocks/site-logo/style-rtl.css 203 B
build/block-library/blocks/site-logo/style.css 203 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 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.4 kB
build/block-library/blocks/social-links/style.css 1.39 kB
build/block-library/blocks/spacer/editor-rtl.css 332 B
build/block-library/blocks/spacer/editor.css 332 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 457 B
build/block-library/blocks/table/editor.css 457 B
build/block-library/blocks/table/style-rtl.css 651 B
build/block-library/blocks/table/style.css 650 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 404 B
build/block-library/blocks/template-part/editor.css 404 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/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 691 B
build/block-library/blocks/video/editor.css 694 B
build/block-library/blocks/video/style-rtl.css 179 B
build/block-library/blocks/video/style.css 179 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 162 B
build/block-library/classic.css 162 B
build/block-library/common-rtl.css 1.05 kB
build/block-library/common.css 1.05 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 11.7 kB
build/block-library/editor.css 11.7 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/index.min.js 198 kB
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/style-rtl.css 12.4 kB
build/block-library/style.css 12.4 kB
build/block-library/theme-rtl.css 698 B
build/block-library/theme.css 703 B
build/block-serialization-default-parser/index.min.js 1.13 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/blocks/index.min.js 50.4 kB
build/components/index.min.js 203 kB
build/components/style-rtl.css 11.6 kB
build/components/style.css 11.6 kB
build/compose/index.min.js 12.3 kB
build/core-data/index.min.js 15.9 kB
build/customize-widgets/index.min.js 11.7 kB
build/customize-widgets/style-rtl.css 1.41 kB
build/customize-widgets/style.css 1.41 kB
build/data-controls/index.min.js 663 B
build/data/index.min.js 7.69 kB
build/date/index.min.js 32.1 kB
build/deprecated/index.min.js 518 B
build/dom-ready/index.min.js 336 B
build/dom/index.min.js 4.71 kB
build/edit-navigation/index.min.js 16.2 kB
build/edit-navigation/style-rtl.css 4.12 kB
build/edit-navigation/style.css 4.13 kB
build/edit-post/classic-rtl.css 571 B
build/edit-post/classic.css 571 B
build/edit-post/index.min.js 34.6 kB
build/edit-post/style-rtl.css 7.45 kB
build/edit-post/style.css 7.44 kB
build/edit-site/index.min.js 64.9 kB
build/edit-site/style-rtl.css 9.08 kB
build/edit-site/style.css 9.08 kB
build/edit-widgets/index.min.js 16.8 kB
build/edit-widgets/style-rtl.css 4.46 kB
build/edit-widgets/style.css 4.47 kB
build/editor/index.min.js 44.1 kB
build/editor/style-rtl.css 3.69 kB
build/editor/style.css 3.68 kB
build/element/index.min.js 4.93 kB
build/escape-html/index.min.js 548 B
build/experiments/index.min.js 882 B
build/format-library/index.min.js 7.2 kB
build/format-library/style-rtl.css 598 B
build/format-library/style.css 597 B
build/hooks/index.min.js 1.66 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.79 kB
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.79 kB
build/keycodes/index.min.js 1.88 kB
build/list-reusable-blocks/index.min.js 2.13 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.94 kB
build/notices/index.min.js 977 B
build/plugins/index.min.js 1.95 kB
build/preferences-persistence/index.min.js 2.23 kB
build/preferences/index.min.js 1.35 kB
build/primitives/index.min.js 960 B
build/priority-queue/index.min.js 1.59 kB
build/react-i18n/index.min.js 702 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.75 kB
build/reusable-blocks/index.min.js 2.26 kB
build/reusable-blocks/style-rtl.css 283 B
build/reusable-blocks/style.css 283 B
build/rich-text/index.min.js 10.8 kB
build/server-side-render/index.min.js 2.09 kB
build/shortcode/index.min.js 1.52 kB
build/style-engine/index.min.js 1.53 kB
build/token-list/index.min.js 650 B
build/url/index.min.js 3.7 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 1.09 kB
build/warning/index.min.js 280 B
build/widgets/index.min.js 7.31 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.18 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

@javierarce
Copy link
Contributor

Maybe I'm doing something wrong, but I've tried this with three different browsers and none of them ask me to give them clipboard access, so when I click the paste option I get the Permission denied: Unable to read from clipboard snackbar message.

@kevin940726
Copy link
Member Author

kevin940726 commented Nov 2, 2022

I've tried this with three different browsers and none of them ask me to give them clipboard access, so when I click the paste option I get the Permission denied: Unable to read from clipboard snackbar message.

Oops, I guess it's because the API requires secure context (https) to work. I should update the error message in that situation. An exception is if you're browsing the page in localhost.

@priethor priethor linked an issue Nov 2, 2022 that may be closed by this pull request
@kevin940726 kevin940726 self-assigned this Nov 2, 2022
@aaronrobertshaw
Copy link
Contributor

I've given this a bit of a run. It's testing well so far nice work @kevin940726 👍

Not receiving the request for clipboard access initially caught me out as well.

I don't think we need a separate "Copy styles" action since that the copied blocks should already contain that information.

While the ability to avoid a "Copy Styles" button is much cleaner. I wonder if that makes this more of a power user only feature? Is there a way we could assist the average user to discover this easier?

 We can discuss it and further refine this logic though. One possible idea is to assign __experimentalRole: "style" to the attributes.

If we can't rely on attributes being style attributes if they don't have the content role, instead of the new prop value could we define a centralised list of what we accept as a style property to avoid updating all blocks. It might help for 3rd party blocks that opt into our block supports as well.

That is, the common styles will be applied if the copied blocks are different from the target blocks

This sounds like a good starting point.

This could be kind of confusing sometimes, but I think it matches what the users expect most of the time.

This matched my expectations. It would be a tricky one to give any kind of visual prompt or feedback around though.

@kevin940726
Copy link
Member Author

kevin940726 commented Nov 3, 2022

Here's what it looks like when pasting styles from a pattern.

Kapture.2022-11-03.at.18.24.00.mp4

@annezazu annezazu mentioned this pull request Nov 7, 2022
57 tasks
Copy link
Contributor

@talldan talldan left a comment

Choose a reason for hiding this comment

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

It works really well for me, but I think it just needs some more thought around what attributes are copied. I left a comment about using __experimentalRole: 'style' (which was also mentioned in the PR description)? It would be good to get thoughts from other @WordPress/gutenberg-core contributors on this.

May also need design feedback on the PR as this implementation deviates from the proposal in the issue.

@talldan talldan added the Needs Design Feedback Needs general design feedback. label Nov 22, 2022
@jasmussen
Copy link
Contributor

Took it for a quick spin, in this GIF I get a clipboard error message:

copy

I do appreciate the idea of unifying "copy styles" into the "copy block" option for simplicity. It opens a few questions:

  • Should it be renamed "Copy block and styles"?
  • Can "Paste styles" be present only if you actually have a block in your clipboard? Or could it be grayed unless you have one in your clipboard?
  • If we have a "Paste block styles" should there also be "Paste block"?

Item 3 might necessitate a dropdown menu flyout, so we can provide additional context which otherwise would take up too many slots in the menu perhaps. Here's what Figma does, which feels like a useful pattern to draw inspiration from:

Screenshot 2022-11-22 at 09 55 47

CC: @javierarce in case you have input.

@kevin940726
Copy link
Member Author

@jasmussen The clipboard API requires secure context (https) or localhost, are you using a custom domain without https?

Should it be renamed "Copy block and styles"?

I figured a block should already contain the information about the style so the "and styles" feels a bit redundant to me. But of course that can go either way.

Can "Paste styles" be present only if you actually have a block in your clipboard? Or could it be grayed unless you have one in your clipboard?

No, we can only read clipboard data (or request permission) on user interaction. It's a privacy issue on the web and I'm afraid there's nothing we can do about it. (We could simulate the clipboard API using JavaScript but that only works in the same tab, it might be confusing for data copied from other tabs/apps.)

If we have a "Paste block styles" should there also be "Paste block"?

I'm wondering if we should rename "Paste style" to "Paste style only", as I think a "block" should actually be "block content" + "block style". This might be less confusing let's say when we decide to add a "Paste content only" button as seen in many other apps.

@jasmussen
Copy link
Contributor

The clipboard API requires secure context (https) or localhost, are you using a custom domain without https?

Ah, I'm using Local to test, so that's why it doesn't work. I wonder if it's better to hide or gray the option, if https isn't available? Probably not, but maybe we can simplify the snackbar to say something simpler, such as "Pasting styles requires a secure domain (HTTPS)" ?

I figured a block should already contain the information about the style so the "and styles" feels a bit redundant to me. But of course that can go either way.

Main reason I'm waffling on it is, there's a "Paste styles", but no "Copy styles" option. I'm wondering if it may still be simpler to have a separate and additional "Copy styles" just for this 🤔

No, we can only read clipboard data (or request permission) on user interaction. It's a privacy issue on the web and I'm afraid there's nothing we can do about it.

👍 👍 — to me that mainly says that it would be all the more helpful to have the nested dropdown flyout menu.

I'm wondering if we should rename "Paste style" to "Paste style only", as I think a "block" should actually be "block content" + "block style". This might be less confusing let's say when we decide to add a "Paste content only" button as seen in many other apps.

Copying a block should definitely also paste the styles. But pasting styles should not necessarily paste the block.

So in that light, maybe we should add separation and do it like this mockup after all, and keep "copy block" and "copy styles" separate after all. It may be a better starting point and then we can come back to it when we have nested dropdown menus. Curious what you think?

@kevin940726
Copy link
Member Author

maybe we can simplify the snackbar to say something simpler, such as "Pasting styles requires a secure domain (HTTPS)" ?

Sure! Welcome to tweak the wording in this PR!

there's a "Paste styles", but no "Copy styles" option. I'm wondering if it may still be simpler to have a separate and additional "Copy styles" just for this

I don't think it's weird though, it's how Google Sheets does it too. If we convey clearly that "blocks" contain both "contents" and "styles" then I think it makes total sense to only have the "Copy block" action.

If we add a "Copy style" action then it's gonna behave exactly the same as the "Copy block" action which is a trade-off we would need to take. Since clipboard on the web is linear, we also need to decide what happens when we paste the copied styles to other apps. In contrast, I think the single "Copy block" action is a lot more straightforward. The downside, however, is that it's probably not easily discoverable for users who are intentionally looking for the "Copy style" action, because they see the "Paste style" action. I think tweaking the wording to "Paste block style only" would help, but it'll be best if we can do some real user research on this.

Copy link
Contributor

@talldan talldan left a comment

Choose a reason for hiding this comment

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

Unfortunately it doesn't seem to be working as expected for me:

Kapture.2022-12-08.at.11.15.35.mp4

This is copying a heading with background and text color, and pasting styles to another heading.

The code looks pretty good though, I left some feedback about reorganising the hook functions, and possibly those new functions could also be used in those hooks files when there's a manual hasBlockSupports check (e.g. https://github.com/WordPress/gutenberg/blob/trunk/packages/block-editor/src/hooks/align.js#L96). Updating that could also be a follow-up if you want to keep things atomic.

I realise there might still be some design iteration to go here, is there a clear direction for that?

packages/block-editor/src/hooks/supports.js Show resolved Hide resolved
@kevin940726
Copy link
Member Author

kevin940726 commented Dec 12, 2022

I realise there might still be some design iteration to go here, is there a clear direction for that?

I don't think there is! I guess we have both voiced our opinions on this, so we might just need a decision-maker to chime in and make the call. We can always experiment with other alternatives in future iterations.

@talldan
Copy link
Contributor

talldan commented Dec 13, 2022

Testing again, and it works very well now since that last commit fixed the earlier issue.

I guess this just needs some final direction on the design, since it seems this implementation is quite different to the original mockup. There do seem to be a lot of technical constraints which need to be taken into account. It might be worth summarising what those are @kevin940726.

@kevin940726
Copy link
Member Author

Agreed! We want to make a decision about the final design (of this PR) of the user interface.

We currently have two primary options for displaying the actions:

Separated actions (Original) Single action (This PR)
image image

I've summarized an overview of the pros and cons in a comment here: #45477 (comment).

there's a "Paste styles", but no "Copy styles" option. I'm wondering if it may still be simpler to have a separate and additional "Copy styles" just for this

I don't think it's weird though, it's how Google Sheets does it too. If we convey clearly that "blocks" contain both "contents" and "styles" then I think it makes total sense to only have the "Copy block" action.

If we add a "Copy style" action then it's gonna behave exactly the same as the "Copy block" action which is a trade-off we would need to take. Since clipboard on the web is linear, we also need to decide what happens when we paste the copied styles to other apps. In contrast, I think the single "Copy block" action is a lot more straightforward. The downside, however, is that it's probably not easily discoverable for users who are intentionally looking for the "Copy style" action when they see the "Paste style" action. I think tweaking the wording to "Paste block style only" would help, but it'll be best if we can do some real user research on this.

I'm open to either decision! Another note is that if we choose the separated actions approach, do we want to only copy the style or should we also copy the block content when users click on "Copy style"? The latter will behave exactly the same as the "Copy block" action, while we can disallow anything from pasting to other apps with the former approach.

@talldan
Copy link
Contributor

talldan commented Dec 15, 2022

Another note is that if we choose the separated actions approach, do we want to only copy the style or should we also copy the block content when users click on "Copy style"?

I did a bit of research, and it seems like the clipboard write (https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/write) API supports copying multiple types of data (so I think you could copy styles data as one type of ClipboardItem and blocks data as another type), but it seems to not be supported well in Firefox.

I think it could be unusual to have 'Copy block' and 'Copy style' do the same thing (but maybe users would never notice?). It would probably still be preferable to have 'Copy style' followed by a 'Paste' output some weird json data. The alternative is to not use the clipboard API, which disallows pasting across tabs or browser instances, but it maybe it's an ok trade-off if it results in the rest of the experience being better.

Are there any other trade-offs of not using the clipboard API?

@kevin940726
Copy link
Member Author

so I think you could copy styles data as one type of ClipboardItem and blocks data as another type

AFAIK, Chrome currently only supports three MIME types: text/html, text/plain, and image/png, so writing custom data types is not supported. Chrome currently also doesn't support writing multiple ClipboardItems either. I also thought that it was possible but obviously there are security and privacy concerns 🤔.

Are there any other trade-offs of not using the clipboard API?

I think ultimately we would want to enable this feature from different tabs, like copying styles from wp.org/patterns for instance. Limiting this only inside the same browsing context would probably confuse the users. It's still an option to mimic the clipboard API in JS, but I'd say it's not worth it to do this rather than going for the "Single action" option in this case.

@jasmussen
Copy link
Contributor

Agreed! We want to make a decision about the final design (of this PR) of the user interface.
We currently have two primary options for displaying the actions:

With an eye towards potential flyouts in the future (#44418), of those two options I would go with the left one. Outside of clarity, what if I copy the wrong style? I would have to paste it first in order to be able to copy a new one, with the right side.

@kevin940726
Copy link
Member Author

what if I copy the wrong style? I would have to paste it first in order to be able to copy a new one, with the right side.

I think there's a misunderstanding. You don't need to paste it first to copy a new one. You can just copy a new one and it will override the existing copied data in the clipboard.

In short, what the right side (or this PR) does is to automatically extract the styles from any given copied block data, so that we don't have to add a separate action. This means if you already have some blocks copied, you can paste their styles to other blocks without having to copied their styles separately. This works across browsing-context or apps too, so if we ever want to allow copying styles from wp.org/patterns, we can already do that with this approach with no changes required. While for the left one, we would want to introduce a separate "Copy pattern styles" action there to enable the same functionality.

@jasmussen
Copy link
Contributor

In short, what the right side (or this PR) does is to automatically extract the styles from any given copied block data, so that we don't have to add a separate action. This means if you already have some blocks copied, you can paste their styles to other blocks without having to copied their styles separately. This works across browsing-context or apps too, so if we ever want to allow copying styles from wp.org/patterns, we can already do that with this approach with no changes required.

Ah, right. I'm still leaning towards keeping these actions separate. It's not an incredibly strong opinion, but the feeling is that we're being too smart for the sake of saving some space, which ultimately I think we can address with a flyout in the future. For some additional takes, CC: @WordPress/gutenberg-design

@kevin940726
Copy link
Member Author

but the feeling is that we're being too smart for the sake of saving some space, which ultimately I think we can address with a flyout in the future.

FWIW, the goal is never to save some space, and the part that's "smart" is quite essential for this feature and has to be implemented one way or another for the "Separated actions" approach anyway. The motivation is to avoid confusion when we want to allow pasting styles from other browsing-context in the future. It's the same idea as shown in Google Sheets' "Paste special" > "Format only" action.

Google Sheets' action

They also only have a single "Copy" action and people seem to be pretty used to it too. As you can see, we might also add other pasting actions like "content only" in the future, where a flyout/nested dropdown would be valuable.

@github-actions
Copy link

github-actions bot commented Jan 9, 2023

Flaky tests detected in 991f685.
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/3871581606
📝 Reported issues:

@kevin940726 kevin940726 merged commit 3a33500 into trunk Jan 9, 2023
@kevin940726 kevin940726 deleted the add/copy-paste-styles branch January 9, 2023 08:13
@github-actions github-actions bot added this to the Gutenberg 15.0 milestone Jan 9, 2023
@srcek
Copy link

srcek commented Jan 23, 2023

Hi! Is there a possibility to add an exception to secure connection requirement if a local development / testing domain is used? For example: http://test.local/

@talldan
Copy link
Contributor

talldan commented Jan 24, 2023

@srcek The feature uses the browser's clipboard API, and that's the limiting factor, rather than anything controllable by Gutenberg.

There's more info here - https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts.

It seems like you may be able to workaround the issue by modifying your hostname to something like 'test.localhost' instead of 'test.local'.

@srcek
Copy link

srcek commented Jan 24, 2023

Thank you for clarifying.

Changing the hostname to test.localhost solved the problem.

@prconcepcion
Copy link

Hello! Is there a way to disable this option for specific blocks?

@kevin940726
Copy link
Member Author

Hello! Is there a way to disable this option for specific blocks?

I don't think so. What's your use case?

@prconcepcion
Copy link

prconcepcion commented Mar 21, 2023

Because I am using 3rd party block called Stackable and the attributes are not being copied whenever I paste them into another Stackable block. It also has its own copy-paste styles feature; so I was looking for a way to disable the option to prevent others from using it whenever they edit Stackable blocks.

@kevin940726
Copy link
Member Author

I think the problem lies in the className block support, which we default it to true even when the block doesn't specify it. It makes sense in other places but I think we should only paste it if it's explicitly set. Otherwise, we'll end up pasting unexpected class names which could break existing styles for third-party blocks. By changing the default support to false, the button will do no action on unsupported third-party blocks.

As for actually disabling the feature entirely, I think we'll need more time and cases to come up with a solution that doesn't confuse users. Please share more feedback if you have any!

@mrfoxtalbot
Copy link

I have added an explicit reference to the browser permissions issue in the "More Options" end-user documentation. I adding it here in case someone looks up the exact messaeg I got in Chrome.

Website wants to: "See text and images copied to the clipboard".
More-options-6-3-clipboard-permissions-chrioe

@richtabor
Copy link
Member

Safari also requires a confirmation; it looks a bit different — not sure if it should be documented though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Blocks Overall functionality of blocks Needs User Documentation Needs new user documentation [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make it easy to copy (and paste) block styles