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

Image block: Add animation toggle to lightbox behavior #51357

Merged
merged 16 commits into from Jun 15, 2023

Conversation

artemiomorales
Copy link
Contributor

@artemiomorales artemiomorales commented Jun 8, 2023

What?

This adds a dropdown allowing users to select between the zoom animation or the fade animation for the experimental image lightbox.

Why?

Addresses #51055
We'd like to give users the option to opt for their preferred animation and get feedback on the UX for this functionality.

How?

It adds the option and some conditionals to the behaviors UI in block supports, and also adds the styles needed to make the zoom work.

Testing Instructions

  1. Ensure the Gutenberg Interactivity API experiments are enabled.
  2. Add two image blocks to the post:
    -- A horizontal image
    -- A vertical image
  3. Enable the lightbox for the images in Advanced > Behaviors under the block settings.
  4. See that a new dropdown to configure the Animation is activated, which should have zoom set as the default.
  5. Publish and view the post.
  6. Click on the image to see the zoom animation.
  7. If possible, test using a physical mobile device as well.
  8. Try changing the Animation to fade to ensure that works.

Testing Instructions for Keyboard

N/A

@artemiomorales
Copy link
Contributor Author

artemiomorales commented Jun 8, 2023

A few outstanding items I'm still working on:

  • Get feedback on the design and implement changes
  • overflow: hidden is disabled on the body because otherwise the animation is jerky when the zoom starts and ends
  • I disabled using the largest available image because it was breaking the zoom animation; I need to look into reenabling that and calculating the values properly
  • The code for enabling the UI can probably be simpler
  • Add support for prefers-reduced-motion; accessibility feedback and testing
  • I need to fix broken tests and add new ones
  • Code cleanup

@artemiomorales
Copy link
Contributor Author

@jasmussen I'd appreciate your feedback on the design for the UI! I know this is still an experiment so not sure how much we should think through it, but currently the UI looks like this, with the Animation dropdown being activated when Lightbox is selected:

Screen Shot 2023-06-08 at 5 06 54 PM

@artemiomorales artemiomorales linked an issue Jun 8, 2023 that may be closed by this pull request
@github-actions
Copy link

github-actions bot commented Jun 8, 2023

Size Change: +1.5 kB (0%)

Total Size: 1.4 MB

Filename Size Change
build/block-editor/index.min.js 195 kB -301 B (0%)
build/block-library/blocks/image/interactivity.min.js 1.34 kB +544 B (+68%) 🆘
build/block-library/blocks/image/style-rtl.css 1.34 kB +231 B (+21%) 🚨
build/block-library/blocks/image/style.css 1.34 kB +235 B (+21%) 🚨
build/block-library/style-rtl.css 13.5 kB +198 B (+1%)
build/block-library/style.css 13.5 kB +204 B (+2%)
build/edit-site/index.min.js 69.9 kB +355 B (+1%)
build/edit-site/style-rtl.css 11.6 kB +16 B (0%)
build/edit-site/style.css 11.6 kB +15 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.29 kB
build/autop/index.min.js 2.1 kB
build/blob/index.min.js 451 B
build/block-directory/index.min.js 7.05 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.22 kB
build/block-editor/content.css 4.22 kB
build/block-editor/default-editor-styles-rtl.css 381 B
build/block-editor/default-editor-styles.css 381 B
build/block-editor/style-rtl.css 14.9 kB
build/block-editor/style.css 14.9 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 584 B
build/block-library/blocks/button/editor.css 582 B
build/block-library/blocks/button/style-rtl.css 624 B
build/block-library/blocks/button/style.css 623 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 409 B
build/block-library/blocks/columns/style.css 409 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.61 kB
build/block-library/blocks/cover/style.css 1.6 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 159 B
build/block-library/blocks/details/style.css 159 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/interactivity.min.js 395 B
build/block-library/blocks/file/style-rtl.css 269 B
build/block-library/blocks/file/style.css 270 B
build/block-library/blocks/freeform/editor-rtl.css 2.58 kB
build/block-library/blocks/freeform/editor.css 2.58 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.53 kB
build/block-library/blocks/gallery/style.css 1.53 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 76 B
build/block-library/blocks/heading/style.css 76 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/theme-rtl.css 126 B
build/block-library/blocks/image/theme.css 126 B
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 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 712 B
build/block-library/blocks/navigation-link/editor.css 711 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 296 B
build/block-library/blocks/navigation-submenu/editor.css 295 B
build/block-library/blocks/navigation/editor-rtl.css 2.35 kB
build/block-library/blocks/navigation/editor.css 2.36 kB
build/block-library/blocks/navigation/interactivity.min.js 978 B
build/block-library/blocks/navigation/style-rtl.css 2.21 kB
build/block-library/blocks/navigation/style.css 2.2 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 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 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 588 B
build/block-library/blocks/post-featured-image/editor.css 586 B
build/block-library/blocks/post-featured-image/style-rtl.css 319 B
build/block-library/blocks/post-featured-image/style.css 319 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 314 B
build/block-library/blocks/post-template/style.css 314 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 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 335 B
build/block-library/blocks/pullquote/style.css 335 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 450 B
build/block-library/blocks/query/editor.css 449 B
build/block-library/blocks/quote/style-rtl.css 222 B
build/block-library/blocks/quote/style.css 222 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 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 178 B
build/block-library/blocks/search/editor.css 178 B
build/block-library/blocks/search/style-rtl.css 587 B
build/block-library/blocks/search/style.css 584 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 531 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 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.43 kB
build/block-library/blocks/social-links/style.css 1.42 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 433 B
build/block-library/blocks/table/editor.css 433 B
build/block-library/blocks/table/style-rtl.css 645 B
build/block-library/blocks/table/style.css 644 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 174 B
build/block-library/blocks/video/style.css 174 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.2 kB
build/block-library/editor.css 12.1 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/index.min.js 201 kB
build/block-library/interactivity/runtime.min.js 2.71 kB
build/block-library/interactivity/vendors.min.js 8.2 kB
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/theme-rtl.css 686 B
build/block-library/theme.css 691 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 50.8 kB
build/commands/index.min.js 14.9 kB
build/commands/style-rtl.css 827 B
build/commands/style.css 827 B
build/components/index.min.js 231 kB
build/components/style-rtl.css 11.8 kB
build/components/style.css 11.8 kB
build/compose/index.min.js 12.1 kB
build/core-commands/index.min.js 1.77 kB
build/core-data/index.min.js 15.7 kB
build/customize-widgets/index.min.js 12 kB
build/customize-widgets/style-rtl.css 1.38 kB
build/customize-widgets/style.css 1.38 kB
build/data-controls/index.min.js 640 B
build/data/index.min.js 8.3 kB
build/date/index.min.js 40.4 kB
build/deprecated/index.min.js 451 B
build/dom-ready/index.min.js 324 B
build/dom/index.min.js 4.63 kB
build/edit-post/classic-rtl.css 544 B
build/edit-post/classic.css 545 B
build/edit-post/index.min.js 34.1 kB
build/edit-post/style-rtl.css 7.58 kB
build/edit-post/style.css 7.57 kB
build/edit-widgets/index.min.js 16.8 kB
build/edit-widgets/style-rtl.css 4.53 kB
build/edit-widgets/style.css 4.53 kB
build/editor/index.min.js 44.7 kB
build/editor/style-rtl.css 3.54 kB
build/editor/style.css 3.53 kB
build/element/index.min.js 4.8 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 7.57 kB
build/format-library/style-rtl.css 554 B
build/format-library/style.css 553 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/is-shallow-equal/index.min.js 527 B
build/keyboard-shortcuts/index.min.js 1.71 kB
build/keycodes/index.min.js 1.84 kB
build/list-reusable-blocks/index.min.js 2.13 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/notices/index.min.js 948 B
build/plugins/index.min.js 1.84 kB
build/preferences-persistence/index.min.js 1.84 kB
build/preferences/index.min.js 1.24 kB
build/primitives/index.min.js 941 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 939 B
build/react-i18n/index.min.js 696 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.7 kB
build/reusable-blocks/index.min.js 2.21 kB
build/reusable-blocks/style-rtl.css 243 B
build/reusable-blocks/style.css 243 B
build/rich-text/index.min.js 10.7 kB
build/router/index.min.js 1.77 kB
build/server-side-render/index.min.js 2.02 kB
build/shortcode/index.min.js 1.39 kB
build/style-engine/index.min.js 1.42 kB
build/token-list/index.min.js 582 B
build/url/index.min.js 3.57 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.04 kB
build/warning/index.min.js 268 B
build/widgets/index.min.js 7.16 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

@artemiomorales artemiomorales added [Type] Enhancement A suggestion for improvement. [Block] Image Affects the Image Block [Feature] Interactivity API API to add frontend interactivity to blocks. labels Jun 8, 2023
@jasmussen
Copy link
Contributor

Nice, thanks for the ping. Just looking at the box here:

image

  • The help text for both dropdowns is a bit redundant and doesn't really provide clarity. I'd actually omit both of those for now. We can potentially revisit in case the help text can be made contextual to its selected state, and it's useful, however I wouldn't do that until we know that it's necessary, it adds verbosity to screen readers as well and doesn't really help clarity. A "Animation" label followed by a dropdown that reads "Fade" feels clear enough to me.
  • Speaking of, I'd just call the animation label "Animation", instead of "Lightbox" animation. I recognize the second dropdown is likely contextual to the former, but I'd still keep the label generic for clarity and to avoid the interface jumping around.
  • Can we do without the "Reset" button? As a pattern, we don't use that reset button in many places and it needs a bit of a holistic rethink. It's also not much of a shortcut assuming you can simply click the dropdown and choose "No behavior", or whichever the default option is.

@github-actions
Copy link

github-actions bot commented Jun 9, 2023

Flaky tests detected in 7fc4425.
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/5279095792
📝 Reported issues:

@artemiomorales
Copy link
Contributor Author

artemiomorales commented Jun 12, 2023

I tested the working implementation on an iPhone XS running iOS 16.0 and unfortunately the animation is shaky; the issue is present in Chrome, Safari, and Firefox.

iphone-xs-zoom.mov

It's also present but less severe on iPad Pro running iPadOS 15.6.1

ipad-zoom.mp4

None of the shakiness is present on desktop at responsive sizes.

Am currently looking at identifying the cause and possible solutions.

As I go down this rabbit hole, I want to check my assumptions here — should we even have the zoom animation on mobile? I wonder if we have the same kind of benefit in this scenario that we do on desktop where...

  1. Pinch to zoom is present
  2. Given the current design, the lightbox image can actually appear smaller on the screen than the image in the content

I also wonder if there would be accessibility considerations to consider with pinch to zoom or the lightbox behavior on mobile in general. Pinging @jasmussen @SaxonF @jameskoster @andrewhayward for guidance.

@artemiomorales
Copy link
Contributor Author

  • The help text for both dropdowns is a bit redundant and doesn't really provide clarity. I'd actually omit both of those for now. We can potentially revisit in case the help text can be made contextual to its selected state, and it's useful, however I wouldn't do that until we know that it's necessary, it adds verbosity to screen readers as well and doesn't really help clarity. A "Animation" label followed by a dropdown that reads "Fade" feels clear enough to me.

  • Speaking of, I'd just call the animation label "Animation", instead of "Lightbox" animation. I recognize the second dropdown is likely contextual to the former, but I'd still keep the label generic for clarity and to avoid the interface jumping around.

@jasmussen Great, thanks! These changes have been implemented.

  • Can we do without the "Reset" button? As a pattern, we don't use that reset button in many places and it needs a bit of a holistic rethink. It's also not much of a shortcut assuming you can simply click the dropdown and choose "No behavior", or whichever the default option is.

This was part of a separate PR by @c4rl0sbr4v0 to remove the custom attributes from the block markup, which from what I understand can't be easily accomplished using the dropdowns, though I'm not sure that this is apparent to end users. Is it worth exploring this further for the moment or should we go with what we have for now and await feedback?

@jasmussen
Copy link
Contributor

None of the shakiness is present on desktop at responsive sizes.
Am currently looking at identifying the cause and possible solutions.

It's been a while since I was deep in CSS and animation, but you could look at transform-origin: center; to center the pivot axis of the image, and see if it gets faster if you apply will-change: transform; to render the animation on the GPU.

As I go down this rabbit hole, I want to check my assumptions here — should we even have the zoom animation on mobile? I wonder if we have the same kind of benefit in this scenario that we do on desktop where...
Pinch to zoom is present

Good question. The image that gets zoomed, is that always the same fidelity version that is used in the resting state? I.e. is it a scaled down version, or does a larger fidelity version get loaded?

If the former, it'd be good to separtely look at a way to lazy-load and replace the low fidelity version with a higher fidelity version when zoomed.

And to answer your question, yes I still think it can be valuable to have the lightbox on mobile. Not just to ensure you get the highest fidelity version, but to ensure you get it centered on the screen and with the viewport locked to prevent scrolling (I know that last part is harder on Mobile Safari, but it's something to strive for still). In that situation, you can more comfortably pinch to zoom and pan on a high res lightbox-isolated image.

Given the current design, the lightbox image can actually appear smaller on the screen than the image in the content

I think we can be smarter with the padding. Since the image is always vertically centered, we can probably use a clamp based padding left and right, that goes from minimum of 0 to a max of 80px, so that on desktops, there's 80px padding, on tablet there may be about 40px, and on phones there's a 0 padding left and right:

Mobile padding, landscape

The top and bottom padding we can keep fixed, e.g. at 80px always, as usually phones are taller aspect ratio than portraits:

Mobile padding, portrait

This was part of a #51239 by @c4rl0sbr4v0 to remove the custom attributes from the block markup, which from what I understand can't be easily accomplished using the dropdowns, though I'm not sure that this is apparent to end users.

Just to be sure I'm reading this right: both the "Reset" button, and selecting the default value (None) in the top dropdown, remove the attributes from the markup? In that case I'd remove the reset button. As noted, it is not a pattern we are using widely, lest we end up with reset buttons everywhere. Further, it's always important we start with less and add only when it's clear it is necessary. Because if it's not necessary, omitting it will provide the clearest interface, and if it is necessary, that will become clear quickly and easy to follow up on. On the flipside, if we start with more, then it won't be clear if it's needed at all.

@cbravobernal
Copy link
Contributor

Just to be sure I'm reading this right: both the "Reset" button, and selecting the default value (None) in the top dropdown, remove the attributes from the markup? In that case I'd remove the reset button. As noted, it is not a pattern we are using widely, lest we end up with reset buttons everywhere. Further, it's always important we start with less and add only when it's clear it is necessary. Because if it's not necessary, omitting it will provide the clearest interface, and if it is necessary, that will become clear quickly and easy to follow up on. On the flipside, if we start with more, then it won't be clear if it's needed at all.

Hi @jasmussen !

In this case, those are different options, as 'None' could not be the default value. The default option can be set by the theme.json file, and, depending on the theme design, could be Lightbox, none or whatever in a future.

That's the reason for having a reset button, to remove the attribute from the markup (none sets none as an attribute), and just retrieve the value from the source of truth, in this case, a theme.json file, that could be set in Core or in each Theme.

Adding or removing the button is not a really big change, and we are happy to listen for feedback and adapt its behavior to a better approach, maybe we could add a Default option to the dropdown instead of using the button. What do you think about that?

@jasmussen
Copy link
Contributor

That's the reason for having a reset button, to remove the attribute from the markup (none sets none as an attribute), and just retrieve the value from the source of truth, in this case, a theme.json file, that could be set in Core or in each Theme.

maybe we could add a Default option to the dropdown instead of using the button. What do you think about that?

Yes, I'd think a "Default" you can set it back to is a great alternative.

@cbravobernal
Copy link
Contributor

cbravobernal commented Jun 13, 2023

Yes, I'd think a "Default" you can set it back to is a great alternative.

I did a proof of concept and I still don't like the user experience, as you choose an option and instantly goes to the default one. I'd like to see how this would work in a future with more than one behavior. So we could just use this approach at the moment and wait for more design feedback.

Screen.Recording.2023-06-13.at.16.37.22.mov

@jasmussen
Copy link
Contributor

Thank you for the video and clarification. I recognize the matrix:

  • Set in the global styles/theme.json, but not locally
  • Set in global styles, overridden locally
  • Not set in global styles, set locally

The reason why it's important we don't add a "clear" button here, is because this challenge is identical to every other style inherited from global styles, and we need to seek out a generic solution that works across all. If we make local solutions we end up encumbering the UI. The issue where we're discussing it is here: #43082, and a solution to that would also be a solution here.

So what you can do is have 3 options:

  • Default (inherits from Global Styles or theme.json)
  • No behaviors (explicit override, adds local markup)
  • Lightbox (explicit override, adds local markup)

I realize that #51464 almost does the above. But from what I can tell, when you choose default, it automatically selects the "Lightbox" option. Presumably this is smarts that shows that option to indicate it is inherited. I wouldn't do that last part — just let the control rest on "Default", we do the same for the Font family:

Screenshot 2023-06-14 at 09 14 29

As noted, the larger issue is one we need to solve in a universal way across all design tools. But the important part for now is that we don't add too many local behaviors to these controls — they should all feel related and behave similarly. What do you think?

@artemiomorales
Copy link
Contributor Author

And to answer your question, yes I still think it can be valuable to have the lightbox on mobile. Not just to ensure you get the highest fidelity version, but to ensure you get it centered on the screen and with the viewport locked to prevent scrolling (I know that last part is harder on Mobile Safari, but it's something to strive for still). In that situation, you can more comfortably pinch to zoom and pan on a high res lightbox-isolated image.

Ok got it @jasmussen. I've pushed up some changes fixing the mobile animation on iOS. I don't have a physical Android device to test with though — while I'll look around for services so I can do that remotely, I'd greatly appreciate if some Android users could test this on their own devices 😄

I've also incorporated your padding suggestion.

Good question. The image that gets zoomed, is that always the same fidelity version that is used in the resting state? I.e. is it a scaled down version, or does a larger fidelity version get loaded?

If the former, it'd be good to separtely look at a way to lazy-load and replace the low fidelity version with a higher fidelity version when zoomed.

We load a high-fidelity version when the image gets clicked.

I've also added the styles for prefers-reduced-motion and fixed an overflow styling issue. Next steps are to clean up the code and sync with what's happening in #51464

@cbravobernal
Copy link
Contributor

sync with what's happening in #51464

I updated the code, now it stays at defaults if the option is to inherit (attribute removed from markup)

@jasmussen
Copy link
Contributor

All sounds great. I run Android and can test this and hopefully give a green check. I can't test today, but can test in my morning.

@artemiomorales artemiomorales changed the base branch from trunk to update/move-reset-button-to-default-option June 14, 2023 19:16
@artemiomorales
Copy link
Contributor Author

I updated the code, now it stays at defaults if the option is to inherit (attribute removed from markup)

Ok perfect, I rebased on #51464 and set it as the target branch for now so we can clearly see the diff. How does this implementation for the UI look, @c4rl0sbr4v0? I wasn't sure whether to create a separate component or implement the settings for the animation the way I did, with a separate onChange function to handle the new setting. Let me know what you think.

All sounds great. I run Android and can test this and hopefully give a green check. I can't test today, but can test in my morning.

@jasmussen Great. thanks! Note that I think I've set up the logic properly to make sure the image doesn't stretch incorrectly in horizontal or vertical orientation, though will go over it again tomorrow with fresh eyes to make sure and see if the code around that can also be clearer.

@cbravobernal cbravobernal force-pushed the update/move-reset-button-to-default-option branch from 8db1d0d to 286541f Compare June 15, 2023 07:45
Copy link
Contributor

@jasmussen jasmussen 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:

behaviors

  • Default means inherit, like it does for fonts
  • No lightbox means explicit none
  • Lightbox means explicit lightbox

I think the zoom can be a bit faster, but I'll let you explore that separately. Thanks for the effort!

@cbravobernal cbravobernal marked this pull request as ready for review June 15, 2023 10:02
cbravobernal and others added 13 commits June 15, 2023 12:25
Because the image in the lightbox has absolute positioning and
does not respect the padding of its parent container, we need to
get references to both the parent <figure> element and the <image>
element to set the right scale and smoothly animate the zoom.

To accomplish that, since we don't have access to the img src
or its natural width and height until it actually appears
in the DOM, I needed to hoist the imgSrc up to the parent context
to allow for retrieval of the target dimensions from an <img>
element created on the fly.
The previous method of centering the image was peforming poorly
on mobile. By doing more manual calculation, the animation now
performs much better.
The 'has-lightbox-open' class was previously causing the
content to shift before the image animation occurred and looked
like a mistake. I've now moved the declaration so that the
class is added during the animation so it draws less attention.
Mostly moved code around, renamed variables for clarity, and
add comments.

Fixed a bug wherein the lightbox wouldn't close on scroll
when using a fade animation.
Removed stylesheet padding declarations for the lightbox
and cleaned up logic to ensure correct dimensions get set
for vertical images on mobile devices.
@cbravobernal cbravobernal force-pushed the update/lightbox-zoom-animation branch from 0f36f61 to f557f74 Compare June 15, 2023 10:25
@cbravobernal
Copy link
Contributor

cbravobernal commented Jun 15, 2023

Tested and worked as expected!
I will merge to trunk after tests are green.
Edit: the Animation dropdown is not working is default is selected. I will address it in another PR.

@cbravobernal
Copy link
Contributor

I'm fixing the tests right now 😄

@artemiomorales artemiomorales merged commit f2108ee into trunk Jun 15, 2023
50 checks passed
@artemiomorales artemiomorales deleted the update/lightbox-zoom-animation branch June 15, 2023 13:59
@github-actions github-actions bot added this to the Gutenberg 16.1 milestone Jun 15, 2023
@keyframes lightbox-zoom-out {
0% {
visibility: visible;
left: var(--lightbox-target-left-position);
Copy link
Contributor

Choose a reason for hiding this comment

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

👋 Just dropping by and skimming through the code, and noticed that you may be animating the position of the lightbox via top and left CSS properties — have you considered using transform (or the new translate prop) for more performant animations?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great, thanks for the suggestion! Will take a look

@@ -162,8 +130,8 @@ test.describe( 'Testing behaviors functionality', () => {
// attributes takes precedence over the theme's value.
await expect( select ).toHaveValue( 'lightbox' );

// There should be 2 options available: `No behaviors` and `Lightbox`.
await expect( select.getByRole( 'option' ) ).toHaveCount( 2 );
// There should be 3 options available: `No behaviors` and `Lightbox`.
Copy link
Contributor

@ciampo ciampo Jun 19, 2023

Choose a reason for hiding this comment

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

We may want to update this comment to explain what is the third option that we're expecting to find?

sethrubenstein pushed a commit to pewresearch/gutenberg that referenced this pull request Jul 13, 2023
* Remove reset button in behaviors, use dropdown option instead

* Use default option reading from the theme, prevent autoupdate

* Add zoom animation UI and styles

* Add logic to use original image and scale its dimensions

Because the image in the lightbox has absolute positioning and
does not respect the padding of its parent container, we need to
get references to both the parent <figure> element and the <image>
element to set the right scale and smoothly animate the zoom.

To accomplish that, since we don't have access to the img src
or its natural width and height until it actually appears
in the DOM, I needed to hoist the imgSrc up to the parent context
to allow for retrieval of the target dimensions from an <img>
element created on the fly.

* Remove extraneous help text

* Manually center lightbox image to improve animation performance

The previous method of centering the image was peforming poorly
on mobile. By doing more manual calculation, the animation now
performs much better.

* Move and reenable class declaration for overflow

The 'has-lightbox-open' class was previously causing the
content to shift before the image animation occurred and looked
like a mistake. I've now moved the declaration so that the
class is added during the animation so it draws less attention.

* Add prefers reduced motion accessibility styles

* Modify fade styles to prevent image flashing

* Simplify code for lightbox UI

* Fix PHP error and linter syntax

* Clean up code; fix bug, add comments

Mostly moved code around, renamed variables for clarity, and
add comments.

Fixed a bug wherein the lightbox wouldn't close on scroll
when using a fade animation.

* Fix bug wherein newly placed images were not setting lightbox animation

* Fix bug wherein vertical images were stretched on mobile

Removed stylesheet padding declarations for the lightbox
and cleaned up logic to ensure correct dimensions get set
for vertical images on mobile devices.

* Update e2e tests

* Update e2e tests, fix selector showing when it should not

---------

Co-authored-by: Carlos Bravo <carlos.bravo@automattic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Image Affects the Image Block [Feature] Interactivity API API to add frontend interactivity to blocks. [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Experiment: Add zoom and animation toggle for image lightbox
4 participants