aminghadersohi commented on code in PR #43836:
URL: https://github.com/apache/superset/pull/43836#discussion_r3931345484


##########
superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx:
##########
@@ -165,19 +165,48 @@ const StyledContent = styled.div<{
 }>`
   grid-column: 2;
   grid-row: 2;
-  /* @z-index-above-dashboard-header (100) + 1 = 101 */
-  ${({ fullSizeChartId }) => fullSizeChartId && `z-index: 101;`}
+  /* @z-index-above-dashboard-header (100) + 2 = 102: a maximized chart
+     must also cover the version-history overlay (101) so the two stack the
+     same way on both sides of the overlay breakpoint. */
+  ${({ fullSizeChartId }) => fullSizeChartId && `z-index: 102;`}
 `;
 
 // Sticks alongside the page scroll so the panel stays fully visible.
+// Below the XXL breakpoint the dashboard grid's min-content width plus the
+// panel exceed the viewport (the content column cannot shrink), which would
+// push the panel past the page's right edge and clip its own controls
+// (sc-119737). Mirror the Explore panel host in spirit — Explore anchors
+// absolutely inside its relatively-positioned container, but the dashboard
+// page owns the scroll, so this pins to the viewport instead. While open at
+// these widths the overlay covers the page's right edge (including the top
+// navbar while scrolled to the top) — accepted: it is a closable surface.
 const VersionHistoryColumn = styled.div`
-  grid-column: 3;
-  grid-row: 1 / span 2;
-  position: sticky;
-  top: 0;
-  align-self: start;
-  height: 100vh;
-  z-index: 99;
+  ${({ theme }) => css`
+    grid-column: 3;
+    grid-row: 1 / span 2;
+    position: sticky;
+    top: 0;
+    align-self: start;
+    height: 100vh;
+    z-index: 99;
+    @media (max-width: ${theme.screenXLMax}px) {

Review Comment:
   Question about the chosen boundary, not an objection.
   
   `theme.screenXLMax` exists (`packages/superset-core/src/theme/types.ts:478`) 
and resolves to antd's `screenXXL - 1` = **1599px**. But the commit message 
measures the actual overflow as starting "below roughly 1446px", and the 
capture you posted is at 1280px.
   
   So between roughly **1447px and 1599px** the side-by-side layout still fit, 
and this PR converts it to an overlay anyway — trading a working two-column 
layout for the navbar occlusion you documented, in a band where there was no 
bug. That may well be deliberate (a standard token beats a magic number derived 
from one dashboard's min-content width, and 1446 will drift with filter-bar 
width and panel width anyway), and `ExploreVersionHistory`'s `PanelHost` uses 
`screenXL` for the same reason.
   
   Just confirming it's a conscious choice rather than "XXL was the nearest 
token" — and if it is, a half-sentence in the comment above saying so ("the 
measured threshold is ~1446px and moves with filter-bar width; snap to the 
breakpoint") would save the next reader the same derivation.
   



##########
superset-frontend/src/features/versionHistory/DashboardVersionHistory.test.tsx:
##########
@@ -253,3 +253,21 @@ test('withholds restore on an externally managed 
dashboard', () => {
     expect.objectContaining({ canRestore: false }),
   );
 });
+
+test('renders nothing in place while the panel is closed', () => {
+  // The DashboardBuilder overlay relies on this contract: the closed
+  // column must stay DOM-empty (the restore modal portals out of it), or
+  // the :empty shadow guard stops matching and a stray shadow line appears
+  // at the viewport edge below the overlay breakpoint (sc-119737).
+  const store = makeTestStore({
+    versionHistory: versionHistoryState({ isPanelOpen: false }),
+    dashboardInfo: {
+      uuid: 'dash-uuid',
+      last_modified_time: 100,
+      dash_edit_perm: true,
+    },
+    dashboardState: { hasUnsavedChanges: false, lastModifiedTime: 500 },
+  });
+  const { container } = renderAdapter(store);
+  expect(container).toBeEmptyDOMElement();

Review Comment:
   **The assertion is insensitive to the state it claims to pin — it passes 
identically with the panel open.**
   
   Both things that could put DOM into the closed column are mocked away in 
this file:
   
   * `jest.mock('./VersionHistoryPanel', ...)` (L26–32) replaces the panel with 
`() => null`;
   * `jest.mock('./useVersionActions', ...)` (L36–41) returns `restoreModal: 
null`.
   
   So `DashboardVersionHistory` renders an empty container in *both* branches 
of `if (!isPanelOpen) return restoreModal;`, and `toBeEmptyDOMElement()` cannot 
distinguish them.
   
   Measured (RAN, not reasoned): changing L263 to `isPanelOpen: true` and 
re-running this test leaves it green —
   
   ```
   ✓ renders nothing in place while the panel is closed (3 ms)
   Tests: 7 skipped, 1 passed, 8 total
   ```
   
   That matters because two comments — L258–261 here and the `&:empty` block at 
`DashboardBuilder.tsx:200–204` ("Pinned by the closed-state test in 
DashboardVersionHistory.test.tsx") — assert this test guards the sc-119737 
shadow sliver. As written it would stay green if the closed path started 
rendering the real panel, or if `RestoreConfirmModal` stopped portalling and 
rendered in place.
   
   To be clear about the production behaviour: I traced it and **the contract 
does hold** — `restoreModal` is always a `<RestoreConfirmModal>` element, but 
it returns `null` while `target` is null, and antd's `Modal` portals to 
`document.body` when it isn't. It's only the *test* that doesn't prove it.
   
   Two cheap strengthenings, either of which makes it fail on a real regression:
   
   ```ts
   // closed => the panel component is never rendered at all
   expect(mockPanelProps).not.toHaveBeenCalled();
   ```
   
   and, to cover the modal half, render this case with a non-null 
`restoreModal` (e.g. `jest.mocked(useVersionActions)` returning the real 
`<RestoreConfirmModal target={null} … />`, or unmocking `useVersionActions` for 
this one test) and assert the container is still empty.
   
   bito flagged the `restoreModal` half of this above; the 
`VersionHistoryPanel` mock is the larger half, since it's what makes the open 
state indistinguishable too.
   



##########
superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx:
##########
@@ -165,19 +165,48 @@ const StyledContent = styled.div<{
 }>`
   grid-column: 2;
   grid-row: 2;
-  /* @z-index-above-dashboard-header (100) + 1 = 101 */
-  ${({ fullSizeChartId }) => fullSizeChartId && `z-index: 101;`}
+  /* @z-index-above-dashboard-header (100) + 2 = 102: a maximized chart
+     must also cover the version-history overlay (101) so the two stack the
+     same way on both sides of the overlay breakpoint. */
+  ${({ fullSizeChartId }) => fullSizeChartId && `z-index: 102;`}

Review Comment:
   I enumerated everything in the 95–199 band under `superset-frontend/src` and 
`packages/` to check the ladder, and **the 101 → 102 bump is correct — nothing 
was jumped over**:
   
   | z-index | what |
   |---|---|
   | 99 | `StyledHeader` (`DashboardBuilder.tsx:128`), `Loading` 
(`packages/…/Loading/index.tsx:37`), `VersionHistoryColumn` at ≥XXL |
   | 100 | `TabsRenderer:100`, FilterBar `ActionButtons:55`, 
`RangeFilterPlugin:74` |
   | 101 | `ResizableSidebar` resizer (`:34`), `AddSliceDragPreview` (`:45`), 
**VersionHistoryColumn overlay (new)** |
   | 102 | **maximized chart (this line)** |
   
   Two notes:
   
   1. **Portalled antd popups are safe.** `DashboardWrapper`'s `StyledDiv` is 
`position: relative` with no `z-index`, so it creates no stacking context and 
all of the above live in the root one. antd dropdowns/tooltips/popovers portal 
to `<body>` at `zIndexPopupBase` (1000+), so a kebab menu opened from inside 
the panel still paints above the 101 overlay. No occlusion.
   2. **One new tie, cosmetic:** `AddSliceDragPreview` is `position: fixed; 
zIndex: 101` and now ties the overlay. Equal z-index resolves by tree order, 
and `VersionHistoryColumn` comes after `StyledContent`, so below XXL the "add 
chart" drag preview would slide *under* the open panel — where previously 
(column at 99) it slid over it. That needs edit mode + panel open + <1600px + 
dragging across the panel's strip, and the panel is opaque there anyway, so I'd 
leave it; noting it only because you're touching this ladder.
   



##########
superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx:
##########
@@ -165,19 +165,48 @@ const StyledContent = styled.div<{
 }>`
   grid-column: 2;
   grid-row: 2;
-  /* @z-index-above-dashboard-header (100) + 1 = 101 */
-  ${({ fullSizeChartId }) => fullSizeChartId && `z-index: 101;`}
+  /* @z-index-above-dashboard-header (100) + 2 = 102: a maximized chart
+     must also cover the version-history overlay (101) so the two stack the
+     same way on both sides of the overlay breakpoint. */
+  ${({ fullSizeChartId }) => fullSizeChartId && `z-index: 102;`}
 `;
 
 // Sticks alongside the page scroll so the panel stays fully visible.
+// Below the XXL breakpoint the dashboard grid's min-content width plus the
+// panel exceed the viewport (the content column cannot shrink), which would
+// push the panel past the page's right edge and clip its own controls
+// (sc-119737). Mirror the Explore panel host in spirit — Explore anchors
+// absolutely inside its relatively-positioned container, but the dashboard
+// page owns the scroll, so this pins to the viewport instead. While open at
+// these widths the overlay covers the page's right edge (including the top
+// navbar while scrolled to the top) — accepted: it is a closable surface.
 const VersionHistoryColumn = styled.div`
-  grid-column: 3;
-  grid-row: 1 / span 2;
-  position: sticky;
-  top: 0;
-  align-self: start;
-  height: 100vh;
-  z-index: 99;
+  ${({ theme }) => css`
+    grid-column: 3;
+    grid-row: 1 / span 2;
+    position: sticky;
+    top: 0;
+    align-self: start;
+    height: 100vh;
+    z-index: 99;
+    @media (max-width: ${theme.screenXLMax}px) {
+      /* @z-index-above-dashboard-header (100) + 1 = 101 */
+      position: fixed;
+      right: 0;
+      bottom: 0;
+      height: auto;

Review Comment:
   **Keep `height: auto` — bito's "Overlay scroll never engages" suggestion 
above is incorrect, and switching to `height: 100vh` would be a (harmless but 
unnecessary) change made for a wrong reason.**
   
   bito's claim is that with an `auto`-height parent, `Panel { height: 100% }` 
resolves to `auto`, so `Body { overflow-y: auto }` never scrolls. That skips 
the absolute-positioning height algorithm:
   
   * This box is `position: fixed` with **both** `top: 0` and `bottom: 0` and 
`height: auto`, so CSS 2.1 §10.6.4 *solves for* `height` — the used height 
becomes definite (the viewport height), not content-derived.
   * CSS 2.1 §10.5's "percentage height computes to `auto`" fallback only 
applies when the containing block's height depends on its content. Here it 
doesn't, so `Panel { height: 100%; }` resolves against the viewport height and 
`Body { overflow-y: auto; }` engages normally.
   
   Net effect is identical to `height: 100vh`, and `top`/`bottom` is arguably 
the better spelling since it doesn't inherit `100vh`'s mobile-URL-bar 
behaviour. This is spec reasoning, not a browser measurement — I can't run a 
browser here — but the `top: 0` you inherit from the base rule is doing real 
work and is worth keeping as-is.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to