From 679dc669f420ceee090398562073749a52dce4fa Mon Sep 17 00:00:00 2001 From: bowenliang123 Date: Sun, 18 Oct 2026 10:52:59 +0800 Subject: [PATCH] fix(client): keep the block map's height steady when rows open MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Opening a category or an exact row grew the rows region's flex base, and the capped card charged the whole deficit to the map — the only other shrinkable item — folding it to its 40px floor on every pick. The map sat in the fixed zone but still changed shape under the click. Pin the map's flex base so opened rows scroll the rows region instead of squeezing it; a percentage ceiling still folds the map when a capped card is genuinely too short (a content-sized card ignores it). The /context dialog's hard viewport cap is the one real pressure: while the map shows, the dialog fills its cap and the browser card and rows region size from the leftover, so the map folds exactly to what is left instead of overflowing. --- src/client/components/browser.tsx | 3 +-- src/client/styles/browser.css | 10 ++++++---- src/client/styles/modal.css | 9 ++++++++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/client/components/browser.tsx b/src/client/components/browser.tsx index 68c1459..1700153 100644 --- a/src/client/components/browser.tsx +++ b/src/client/components/browser.tsx @@ -896,8 +896,7 @@ export function makeContextBrowser( {/* The block map sits in the card's fixed zone, right under the head: the rows region below is the - only scroller, so the map never rides a scroll, whether it is shown or not. The squarified panel - re-measures whatever box the cap leaves it, folding in height under pane pressure (browser.css). */} + only scroller, and the map keeps the height it opens at (browser.css). */} {mapOn ? ( .lc-map { flex: 0 1 auto; min-height: 40px; } +/* The block map: a measured squarified treemap (browserTreemap.tsx) in the card's fixed zone. It keeps the + height it opens at: opened rows scroll the rows region below instead of squeezing the map, whose own flex + base no longer follows the content. The percentage ceiling folds it only when a capped card is genuinely + too short — it also leaves room for the head, the map's margin and the rows region's floor — and a + content-sized card ignores the percentage. */ +.lc-br > .lc-map { flex: none; min-height: 40px; max-height: calc(100% - 140px); } .lc-map { position: relative; height: 240px; margin-top: 8px; } /* Narrow panes stack taller so regions stay legible instead of crushing into slivers. */ @container lc-card (max-width: 560px) { .lc-map { height: 320px; } } diff --git a/src/client/styles/modal.css b/src/client/styles/modal.css index c7cf69b..091ab57 100644 --- a/src/client/styles/modal.css +++ b/src/client/styles/modal.css @@ -1,7 +1,7 @@ /* Fixed positioning escapes the composer anchor; the card's percentage width resolves against the backdrop, so a docked mask clamps it inside the main column. */ .lc-modal-backdrop { position: fixed; inset: 0; z-index: 200; background: var(--dsw-alias-bg-mask-1, rgba(0, 0, 0, 0.45)); display: flex; align-items: center; justify-content: center; } /* Side margins keep 2/3 of the old fixed-720px cap's (pane/3 + 480 ⇒ margin = pane/3 − 240); the 32px floor is the old 24px gutter cut to 16. */ -.lc-modal-card { width: min(calc(33.333% + 480px), calc(100% - 32px)); max-height: min(82vh, 760px); overflow-y: auto; box-sizing: border-box; background: var(--dsw-alias-bg-layer-1); border: 1px solid var(--dsw-alias-border-l2); border-radius: 12px; box-shadow: var(--dsw-shadow-lv3, 0 12px 32px rgba(0, 0, 0, 0.4)); padding: 16px 18px 18px; color: var(--dsw-alias-label-primary); font-size: 13px; } +.lc-modal-card { width: min(calc(33.333% + 480px), calc(100% - 32px)); --lc-modal-h: min(82vh, 760px); max-height: var(--lc-modal-h); overflow-y: auto; box-sizing: border-box; background: var(--dsw-alias-bg-layer-1); border: 1px solid var(--dsw-alias-border-l2); border-radius: 12px; box-shadow: var(--dsw-shadow-lv3, 0 12px 32px rgba(0, 0, 0, 0.4)); padding: 16px 18px 18px; color: var(--dsw-alias-label-primary); font-size: 13px; } .lc-modal-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 12px; } .lc-modal-title { font-weight: 600; font-size: 14px; } .lc-modal-close { margin-left: auto; border: 0; background: transparent; color: var(--dsw-alias-label-secondary); font-size: 18px; line-height: 1; padding: 2px 6px; border-radius: 6px; cursor: pointer; font-family: inherit; transition: color var(--ds-transition-duration, 0.2s) var(--ds-ease-in-out, ease-in-out), background-color var(--ds-transition-duration, 0.2s) var(--ds-ease-in-out, ease-in-out); } @@ -14,6 +14,13 @@ .lc-modal-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; } .lc-modal-body > * { flex: none; } .lc-modal-body > .lc-br { flex: 0 1 auto; } +/* While the map is shown, fill the dialog's viewport cap and give the body's leftover to the browser card + and its rows region: opened rows never squeeze the map, and the map folds exactly to the remaining height, + which the fixed head reserve of browser.css's ceiling cannot track. */ +.lc-modal-fill:has(.lc-map) { height: var(--lc-modal-h); } +.lc-modal-fill:has(.lc-map) .lc-modal-body > .lc-br { flex: 1 1 0; } +.lc-modal-fill:has(.lc-map) .lc-br-scroll { flex: 1 1 0; } +.lc-modal-fill:has(.lc-map) .lc-map { flex: 0 1 auto; max-height: none; } /* ---- the baseline-gate dialog (upgradeGate.tsx) ---- */ .lc-gate-card { width: min(440px, calc(100vw - 48px)); }