fix(shell): the dashboard switcher opens above the app navigation, not behind it - #555
Merged
rubenvdlinde merged 1 commit intoSep 5, 2026
Conversation
…t behind it #551 adopted the shared shell, and the dashboard switcher has been unreachable ever since. 58 e2e tests across eleven specs fail as `locator.click` timing out, and all 240 interception lines in that run name the same element: `[data-testid="cn-nav"] .app-navigation`. The panel slides out, it is visible, and every click on it lands on the navigation instead. This is a stacking context, not a z-index. The sidebar is `position: fixed`, which escapes the scroll flow but not the stacking context. Until #551 this view WAS the page, so there was no context to escape and nothing else claimed the left 280px. Now it renders inside `#app-content`, a sibling of `.app-navigation`, and NcAppNavigation carries `z-index: 1400` on itself. A sibling with a z-index paints above the whole of a sibling subtree whose own z-index is auto, so the sidebar's 1500 could never win: it was competing inside a box that had already lost. Raising the number again would have changed nothing, which is worth saying because that is the obvious first move. The sidebar and its backdrop are therefore teleported to `body`, making them siblings of the navigation rather than descendants of the content, which is the only place their z-index means what it says. The backdrop goes from 999 to 1450 while it is there. At 999 the navigation painted over it even once teleported, so a click meant to dismiss the sidebar navigated instead. 1450 puts it above the navigation and below the sidebar it sits behind. Verified locally: 682 unit tests pass, webpack build clean, eslint and prettier clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
Quality Report — ConductionNL/launchpad @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| format | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 104/104 | |||
| npm | ✅ | ✅ 527/527 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ⏭️ deferred — runs on the promotion into beta/main, not on a pull request into development | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-09-05 18:12 UTC
Download the full PDF report from the workflow artifacts.
rubenvdlinde
added a commit
that referenced
this pull request
Sep 5, 2026
…ve (#557) * fix(shell): the dashboard switcher opens above the app navigation, not behind it #551 adopted the shared shell, and the dashboard switcher has been unreachable ever since. 58 e2e tests across eleven specs fail as `locator.click` timing out, and all 240 interception lines in that run name the same element: `[data-testid="cn-nav"] .app-navigation`. The panel slides out, it is visible, and every click on it lands on the navigation instead. This is a stacking context, not a z-index. The sidebar is `position: fixed`, which escapes the scroll flow but not the stacking context. Until #551 this view WAS the page, so there was no context to escape and nothing else claimed the left 280px. Now it renders inside `#app-content`, a sibling of `.app-navigation`, and NcAppNavigation carries `z-index: 1400` on itself. A sibling with a z-index paints above the whole of a sibling subtree whose own z-index is auto, so the sidebar's 1500 could never win: it was competing inside a box that had already lost. Raising the number again would have changed nothing, which is worth saying because that is the obvious first move. The sidebar and its backdrop are therefore teleported to `body`, making them siblings of the navigation rather than descendants of the content, which is the only place their z-index means what it says. The backdrop goes from 999 to 1450 while it is there. At 999 the navigation painted over it even once teleported, so a click meant to dismiss the sidebar navigated instead. 1450 puts it above the navigation and below the sidebar it sits behind. Verified locally: 682 unit tests pass, webpack build clean, eslint and prettier clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(shell): the floating controls move with the backdrop they sit above #555 teleported the sidebar and its backdrop to `body` and raised the backdrop to 1450. It should have moved the floating controls at the same time, and the e2e said so within one run. Those controls are `position: fixed` with `z-index: 1000`, and that number was not arbitrary: it sat just above the backdrop's original 999 so that "click the hamburger again to close the sidebar" works — the sidebar is open, the backdrop is up, and the toggle has to stay reachable through it. Teleporting one half of that pairing broke it. The backdrop became a body-level sibling while the controls stayed inside `#app-content`, whose own z-index is auto, so the backdrop painted over them whatever number they carried. `runtime-shell-canEdit` names it exactly: the backdrop intercepting pointer events over a button the same log calls visible, enabled and stable. So both halves move, and the controls go to 1460 — above the backdrop, below the sidebar they never overlap. The comment says which number it is above and why the Teleport is what makes it mean anything, because the next person to see 1460 will otherwise try raising it. Verified locally: 682 unit tests pass, webpack build clean, eslint and prettier clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Conduction Release Bot <release-bot@conduction.nl> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The dashboard switcher has been unreachable since #551 adopted the shared shell. 58 e2e tests across eleven specs fail as
locator.clicktiming out, and all 240 interception lines in that run name the same element:[data-testid="cn-nav"] .app-navigation. The panel slides out, it is visible, and every click on it lands on the navigation instead.Why the z-index was not the fix
This is a stacking context. The sidebar is
position: fixed, which escapes the scroll flow but not the stacking context.Until #551 this view was the page, so there was no context to escape and nothing else claimed the left 280px. Now it renders inside
#app-content, a sibling of.app-navigation, and NcAppNavigation carriesz-index: 1400on itself. A sibling with a z-index paints above the whole of a sibling subtree whose own z-index is auto, so the sidebar's 1500 could never win: it was competing inside a box that had already lost.Raising the number again would have changed nothing. That is worth saying, because it is the obvious first move.
What changes
body, making them siblings of the navigation rather than descendants of the content. That is the only place their z-index means what it says.Verification
Local, because the E2E leg only runs on the
developmentpush:The proof is the next
developmentpush run.🤖 Generated with Claude Code