Skip to content

Commit f67833b

Browse files
Conduction Release Botclaude
andcommitted
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>
1 parent 728f6cc commit f67833b

3 files changed

Lines changed: 57 additions & 23 deletions

File tree

‎src/components/Workspace/DashboardSwitcherSidebar.vue‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,12 @@ export default {
802802
left: 0;
803803
bottom: 0;
804804
width: 280px;
805+
/*
806+
* Above NcAppNavigation's own 1400. This only started mattering with #551:
807+
* before the shared shell this view was the page, and nothing else claimed
808+
* the left 280px. See the Teleport in Views.vue for why the number alone
809+
* was not enough.
810+
*/
805811
z-index: 1500;
806812
background: var(--color-main-background, #fff);
807813
border-right: 1px solid var(--color-border, #e0e0e0);

‎src/components/Workspace/SidebarBackdrop.vue‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,14 @@ export default {
4848
left: 0;
4949
right: 0;
5050
bottom: 0;
51-
z-index: 999;
51+
/*
52+
* Above NcAppNavigation's own 1400, and below the sidebar's 1500 that it
53+
* sits behind. At 999 the navigation painted over the backdrop, so a click
54+
* meant to dismiss the sidebar navigated instead. Only meaningful together
55+
* with the Teleport in Views.vue: inside `#app-content` no value here can
56+
* beat a sibling subtree that already carries a z-index.
57+
*/
58+
z-index: 1450;
5259
background: rgba(0, 0, 0, 0.2);
5360
cursor: pointer;
5461
}

‎src/views/Views.vue‎

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,49 @@
77
`update:modelValue` — neither of which the sidebar declares —
88
and the panel would never open. Bind both halves explicitly.
99
Once `runtime-shell` ships and replaces this view with
10-
`WorkspaceApp.vue`, the same binding shape applies. -->
11-
<DashboardSwitcherSidebar
12-
:isOpen="sidebarOpen"
13-
:groupName="primaryGroupName"
14-
:groupDashboards="sidebarGroupDashboards"
15-
:userDashboards="sidebarUserDashboards"
16-
:activeDashboardId="activeDashboard?.id"
17-
:allowUserDashboards="allowUserDashboards"
18-
:canEdit="canEdit"
19-
:defaultUuid="defaultDashboardUuid"
20-
:dashboardQuotaReached="dashboardQuotaReached"
21-
:dashboardQuotaTooltip="dashboardQuotaTooltip"
22-
:isEditMode="isEditMode"
23-
@update:open="sidebarOpen = $event"
24-
@switch="onSidebarSwitch"
25-
@createDashboard="onSidebarCreateDashboard"
26-
@deleteDashboard="onSidebarDeleteDashboard"
27-
@toggleEdit="onRowToggleEdit"
28-
@openConfig="onRowOpenConfig"
29-
@addCustomWidget="onRowAddCustomWidget"
30-
@setDefault="onRowSetDefault" />
31-
<SidebarBackdrop v-if="sidebarOpen" @close="sidebarOpen = false" />
10+
`WorkspaceApp.vue`, the same binding shape applies.
11+
12+
TELEPORTED TO BODY, and the reason is a stacking context, not a
13+
z-index. The sidebar and its backdrop are `position: fixed`, but
14+
fixed positioning does not escape a stacking context — it only
15+
escapes the scroll flow. Until #551 this view WAS the page, so
16+
there was no context to escape. #551 adopted the shared shell, so
17+
this view now renders inside `#app-content`, a sibling of
18+
`.app-navigation`, and NcAppNavigation carries `z-index: 1400` on
19+
ITSELF. A sibling with a z-index paints above the whole of a
20+
sibling subtree whose own z-index is auto, so the sidebar's 1500
21+
could never win: it was competing inside a box that had already
22+
lost.
23+
24+
That cost 58 e2e failures across eleven specs, every one of them
25+
`locator.click` timing out with the SAME interceptor named in the
26+
log, `[data-testid="cn-nav"] .app-navigation`. Raising the number
27+
again would not have helped. Teleporting makes the sidebar a
28+
sibling of the navigation rather than a descendant of the content,
29+
which is the only place its z-index means what it says. -->
30+
<Teleport to="body">
31+
<DashboardSwitcherSidebar
32+
:isOpen="sidebarOpen"
33+
:groupName="primaryGroupName"
34+
:groupDashboards="sidebarGroupDashboards"
35+
:userDashboards="sidebarUserDashboards"
36+
:activeDashboardId="activeDashboard?.id"
37+
:allowUserDashboards="allowUserDashboards"
38+
:canEdit="canEdit"
39+
:defaultUuid="defaultDashboardUuid"
40+
:dashboardQuotaReached="dashboardQuotaReached"
41+
:dashboardQuotaTooltip="dashboardQuotaTooltip"
42+
:isEditMode="isEditMode"
43+
@update:open="sidebarOpen = $event"
44+
@switch="onSidebarSwitch"
45+
@createDashboard="onSidebarCreateDashboard"
46+
@deleteDashboard="onSidebarDeleteDashboard"
47+
@toggleEdit="onRowToggleEdit"
48+
@openConfig="onRowOpenConfig"
49+
@addCustomWidget="onRowAddCustomWidget"
50+
@setDefault="onRowSetDefault" />
51+
<SidebarBackdrop v-if="sidebarOpen" @close="sidebarOpen = false" />
52+
</Teleport>
3253

3354
<!-- Floating controls in top right.
3455
Wave3.3 removed the floating `DashboardConfigMenu` (cog) — its

0 commit comments

Comments
 (0)