Skip to content

Fix: Wide Alignment + Block Tree Selection#70

Open
theMasudRana wants to merge 4 commits intodevelopfrom
fix/editor-width
Open

Fix: Wide Alignment + Block Tree Selection#70
theMasudRana wants to merge 4 commits intodevelopfrom
fix/editor-width

Conversation

@theMasudRana
Copy link
Collaborator

@theMasudRana theMasudRana commented Mar 2, 2026

Bug Fix: Wide Alignment + Block Tree Selection

The Problem

Two issues showed up in the block editor when using the carousel with Wide or Full alignment:

  1. Slides didn't scroll fully. Clicking the arrow button would move the slides, but the transition stopped midway — the previous slide stayed partially visible instead of being fully replaced.

  2. Clicking slides in the List View was unreliable. Sometimes the selected slide just wouldn't appear in the editor.

Both worked perfectly on the frontend — this was editor-only.

Root Cause

For the scroll issue: Embla measures the viewport width once at startup to calculate how far to translate slides. We had disabled its built-in resize watcher (watchResize: false) because Gutenberg's block toolbar popping in/out would cause tiny layout shifts that triggered unwanted recalculations. But that also meant Embla never re-measured when the width actually changed (like switching to Wide alignment), so its math was wrong.

For the List View issue: There was simply no code to tell Embla "scroll to slide 3" when you clicked Slide 3 in the List View. On top of that, Gutenberg's own scrollIntoView() was setting a native scrollLeft on the viewport, which broke Embla's transform-based positioning.

The Fix

  • Resize: Added a debounced ResizeObserver that only fires when the width changes by more than 1px. This ignores the tiny toolbar shifts but catches real layout changes.

  • List View selection: Added a store subscription that detects which slide is selected (including clicks on blocks inside a slide). When the selection changes, we scroll Embla to that slide. A scroll event listener resets any native scrollLeft that Gutenberg's scrollIntoView sets.

  • Refactoring: Extracted the resize and mutation observer logic into their own hooks (useEmblaResizeObserver, useEmblaQueryLoopObserver) to keep the main component clean.

Why This Is Safe

  • The resize observer uses the same debounce + threshold approach that prevents toolbar-induced jitter, so the original reason for disabling watchResize is still handled.
  • The scroll-to-slide logic is a no-op when you're already on the right slide, so it won't interfere with normal editing.
  • The native scroll reset is scoped to the .embla viewport div only — it can't affect page scroll or other elements.

Issue: #69

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves two significant editor-specific issues within the carousel block: slides failing to scroll completely when using Wide or Full alignment, and unreliable selection of slides from the List View. The solution involves integrating a debounced resize observer to ensure the carousel accurately adapts to layout changes and implementing logic to synchronize the carousel's scroll position with the selected block, while also mitigating conflicts with Gutenberg's native scroll behavior.

Highlights

  • Improved Carousel Responsiveness: Implemented a debounced ResizeObserver that triggers Embla Carousel re-initialization only when the viewport width changes by more than 1px, effectively handling wide/full alignment changes without reacting to minor toolbar-induced layout shifts.
  • Enhanced Block Tree Selection: Added a store subscription to detect the currently selected slide (including nested blocks) and programmatically scroll the Embla carousel to that slide, resolving issues where selected slides were not reliably displayed in the editor.
  • Native Scroll Conflict Resolution: Introduced a scroll event listener to reset native scrollLeft and scrollTop values on the Embla viewport, preventing Gutenberg's scrollIntoView from interfering with Embla's transform-based positioning.
  • Code Refactoring: Extracted resize and mutation observer logic into dedicated React hooks (useEmblaResizeObserver and useEmblaQueryLoopObserver) to improve modularity and maintainability of the main component.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/blocks/carousel/useEmblaQueryLoopObserver.ts
    • Added a new React hook to observe mutations within Query Loop blocks inside the carousel viewport and trigger Embla re-initialization.
  • src/blocks/carousel/useEmblaResizeObserver.ts
    • Added a new React hook to provide a debounced ResizeObserver for the Embla viewport, triggering reInit only on significant width changes.
  • src/blocks/carousel/viewport/edit.tsx
    • Imported useState, useEmblaResizeObserver, and useEmblaQueryLoopObserver.
    • Updated the useSelect hook to track selectedSlideIndex based on block selection, including nested child blocks.
    • Introduced emblaApiRef, initEmblaRef, and viewportEl state to manage the Embla instance and observer hooks.
    • Integrated the new useEmblaResizeObserver and useEmblaQueryLoopObserver hooks.
    • Added a useEffect to scroll Embla to the selectedSlideIndex using requestAnimationFrame to avoid conflicts with Gutenberg's scroll behavior.
    • Refactored the main Embla initialization useEffect to delegate resize and mutation observation to the newly created hooks.
    • Added a scroll event listener to the viewport to reset scrollLeft and scrollTop to zero, counteracting Gutenberg's native scroll behavior.
    • Updated Embla initialization to store the API instance in emblaApiRef and the init function in initEmblaRef for external hook access.
Activity
  • No human activity has occurred on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request effectively resolves two editor-only bugs in the carousel block related to wide alignment and block tree selection. The solution, which involves a custom debounced ResizeObserver and logic to handle slide selection from the List View, is well-implemented. The refactoring of observer logic into separate hooks is a great improvement for code modularity and maintainability. My review includes suggestions to enhance the robustness of the mutation detection, improve code clarity by removing magic numbers in setTimeout calls, and simplify some logic for better readability.

@theMasudRana theMasudRana changed the title [WIP] Fix: Wide Alignment + Block Tree Selection Fix: Wide Alignment + Block Tree Selection Mar 3, 2026
@theMasudRana theMasudRana self-assigned this Mar 3, 2026
@theMasudRana theMasudRana marked this pull request as ready for review March 3, 2026 05:51
@gemini-code-assist
Copy link

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes editor-only carousel issues when using Wide/Full alignment and when selecting slides via the List View (block tree), by ensuring Embla re-measures on meaningful width changes and scrolls to the currently selected slide in the editor.

Changes:

  • Add debounced ResizeObserver + deferred reInit() to keep Embla measurements correct after editor layout/alignment changes.
  • Subscribe to block-editor selection to scroll Embla to the selected slide (including nested selection), and neutralize Gutenberg’s native scrollLeft/scrollTop interference.
  • Refactor observer logic into useEmblaResizeObserver and useEmblaQueryLoopObserver hooks.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/blocks/carousel/viewport/edit.tsx Adds editor selection-driven scrolling, native scroll reset, deferred reInit(), and wires in new observer hooks.
src/blocks/carousel/styles/_core.scss Adds alignment-related width styling for .alignfull in the shared block stylesheet.
src/blocks/carousel/hooks/useEmblaResizeObserver.ts New hook: debounced width-change observer that triggers Embla reInit().
src/blocks/carousel/hooks/useEmblaQueryLoopObserver.ts New hook: debounced mutation observer for Query Loop slide-count changes that re-initializes Embla.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants