Skip to content

Dashboard: option to use window scroll so native Nuxt scroll restoration works #6783

Description

@stuible

Description

UDashboardGroup is fixed inset-0 flex overflow-hidden and UDashboardPanel's body is flex-1 overflow-y-auto, so the document never scrolls — a panel inside it does. That's a deliberate app-shell design, but it means Nuxt's native scroll restoration cannot work, because both the browser and Vue Router operate on window:

  • vue-router records positions with const computeScrollPosition = () => ({ left: window.scrollX, top: window.scrollY }), which is permanently 0 inside a dashboard layout, so savedPosition is always { left: 0, top: 0 }.
  • Nuxt's default scrollBehavior (nuxt/dist/pages/runtime/router.options.js) ends in window.scrollTo(...) on every branch, including the { el } form, which resolves the element and then still scrolls the window.

The visible result is that scroll-to-top on navigation and back/forward restoration both do nothing. Clicking a row near the bottom of a long table opens the next route still scrolled to the same offset, and going back doesn't return you to your place in the list. Nothing errors, and nothing in the docs mentions it, so it reads as a Nuxt bug until you find the scroll container.

Request

Let the dashboard scroll the document instead of an inner panel — either as the default, or opt-in via a prop, e.g.:

<UDashboardGroup page-scroll>

The goal is specifically that Nuxt's own scroll restoration works with no custom code. Anything that keeps scrolling inside a nested container can't achieve that, since the framework only ever measures and sets window.

This is achievable today, but only by fighting the theme

It can be done in userland by overriding the theme, which is what we ended up doing:

  • unpin the shell — relative inset-auto min-h-svh overflow-visible on UDashboardGroup
  • fixed the sidebar and navbar so they hold the viewport edges
  • offset the panel by the sidebar width to replace the flow width the fixed sidebar no longer occupies

It works, and Nuxt's scroll handling then behaves normally with zero custom scroll code. But it means re-implementing things the fixed shell provided implicitly, each of which only surfaces as a visual bug once the document scrolls:

  • the sidebar has no background, so content scrolls visibly underneath it
  • the sidebar and navbar have no z-index, so ordinary page content using relative z-10 paints over them

Those are correct omissions under the current design and unavoidable breakage outside it, which is why this feels like it belongs in the library rather than in every app that wants it.

Additional context

Related to #5676, which asks for a scroll-region attribute so Inertia's scroll management can find the container — same root cause, different framework.

  • @nuxt/ui 4.10.0
  • nuxt 4.5.1
  • vue 3.5.39

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions