Skip to content

Wizard page scrolls to the top after every Livewire update when the active step contains a dropdown (regression in v5.10.1) #20742

Closed

Description

@yuges92

Package

filament/schemas

Package Version

v5.10.2

Laravel Version

v13.35.0

Livewire Version

v4.4.7

PHP Version

PHP 8.5.10

Problem description

Since v5.10.1, any Livewire update on a page with a Wizard scrolls the page back to the top whenever the active step contains a dropdown (for example a Builder's add-block menu or an ActionGroup). With a ->live() field, this happens on every keystroke, so you can't edit fields further down a long step.

It's caused by two things that combine:

  1. Wizard\Step::toHtml() renders a static x-cloak on the step panel, and the step has no wire:ignore.self. Alpine removes x-cloak on load, so every Livewire morph adds it back and the whole active step is display: none until Alpine's next microtask removes it again.
  2. Since fix: support keyboard navigation in dropdown menus #20669 ("support keyboard navigation in dropdown menus", first released in v5.10.1), the dropdown's MutationObserver runs syncAria() → getTrigger() → isElementVisible() (getComputedStyle() + getClientRects()) while the morph is still running. Reading layout while the step is hidden makes the document collapse, so the browser clamps scrollY to 0.

Point 1 alone is harmless: no layout is read while the step is cloaked. Before #20669, nothing read layout during that window. In the reproduction:

Version x-cloak re-added to the step on update Page jumps to top
v5.10.0 yes no
v5.10.1 / v5.10.2 yes yes
v5.10.2, step without the Builder (no dropdown in the step) yes no
v5.10.2, step with ->extraAttributes(['wire:ignore.self' => true]) no no

Stack trace of the layout read while the step had x-cloak (v5.10.1):

window.getComputedStyle
Proxy.isElementVisible (support.js)
Array.find
Proxy.getTrigger (support.js)
Proxy.syncAria (support.js)
MutationObserver.<anonymous> (support.js)

Expected behavior

The page keeps its scroll position after a Livewire update, as it did in v5.10.0.

Steps to reproduce

  1. Clone the reproduction repository, then run composer setup and php artisan serve.
  2. Log in at /admin (test@example.com / password) and open /admin/wizard-scroll-reproduction.
  3. The wizard starts on its second step. That step contains a Builder, 30 filler inputs and, at the bottom, a ->live() text input.
  4. Scroll to the bottom input and type a character.
  5. After the Livewire update, the page jumps to the top.

The whole reproduction is one page:

Wizard::make([
    Step::make('First')
        ->schema([
            TextInput::make('name'),
        ]),
    Step::make('Second')
        ->schema([
            Builder::make('blocks')
                ->blocks([
                    Block::make('heading')
                        ->schema([
                            TextInput::make('text'),
                        ]),
                ]),
            ...collect(range(1, 30))
                ->map(fn (int $number): TextInput => TextInput::make("filler_{$number}"))
                ->all(),
            TextInput::make('type_here')
                ->live(),
        ]),
])
    ->startOnStep(2),

Reproduction repository (issue will be closed if this is not valid)

https://github.com/yuges92/filament-wizard-scroll-repro

Workaround / possible fix

Adding wire:ignore.self to every step fixes it, the same way the Wizard and Tabs roots already use wire:ignore.self. A step's own attributes are static, and Alpine binds fi-active, so only its children need morphing:

Step::configureUsing(
    fn (Step $step): Step => $step->extraAttributes(['wire:ignore.self' => true], merge: true),
);

Possible fixes in Filament:

  • add wire:ignore.self to the step panel in Wizard\Step::toHtml(), or
  • defer the dropdown's syncAria() visibility check until after the morph and Alpine's x-cloak removal, for example with queueMicrotask() or requestAnimationFrame().

A collapsible Section that renders x-cloak on its content wrapper (collapsed or persisted-collapsed) may hit the same problem, but I haven't confirmed it.

Activity

  1. added theissue type on Oct 14, 2026
  2. added this to the v4 milestone on Oct 14, 2026
  3. people-sea commented on Oct 14, 2026

    @people-sea
    Member

    This seems related to alpinejs/alpine#4922. I can reproduce it with the bundled Alpine, and testing that PR’s change locally kept the scroll position stable in the Wizard, Section and visibleJs() cases I tried. The change doesn’t seem to be included in the latest Alpine release (3.17.4) or Livewire bundles (3.8.10 / 4.4.7) yet.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions