From 491851f4f033b1845c08aa0f0efa13065b538986 Mon Sep 17 00:00:00 2001 From: pythonlearner1025 Date: Wed, 16 Sep 2026 17:35:40 -0700 Subject: [PATCH] fix(editor): the Inspector header stays one line on a long path The Inspector header put the title and its buttons in one row, and the title could wrap. A picked mesh inside a placed asset writes a long title, for example "Editing: assets/models/map/wall-12x3x1/wall-12x3x1.gltf > Wall_segment_concrete". At a 260px panel that title took five lines. The row keeps its 30px height, so the text spilled 24px above the panel's top edge and the first line was cut off, it covered the Geometry row under it, and it pushed the Reload and Save buttons out of the panel. The title's flex base was width 100% and its automatic minimum size was min-content, so it never gave width back to the buttons. The title is now one line at every panel width. It sets white-space nowrap, min-width 0 and no width 100%, so it shrinks and the buttons, which Blueprint already gives flex 0 0 auto, keep their place. The title splits at its last slash: the folder part is dimmed and shrinks a hundred times faster, so the file name and the picked child name are what survive. Both parts use overflow clip, not hidden, because a hidden box is a scroll container and Chrome reserves 11px of scrollbar width inside it, which opened a hole in the middle of the path. The whole title is the tooltip, which is where a long path belongs. Verification: headless Chrome 153, viewport 1512x982, the terminator-next project, the right panel dragged to 260px, 152px and 419px. Ten header states each time: the scene document, a plain scene object, an asset root, a mesh in a placed asset, an open object document, a mesh in an open object document, a material document, a texture document, a file picked in the Files panel, and the Instance branch. Before, six of ten wrapped and the header read scrollHeight 54 against clientHeight 30; after, all ten read one line and 30 against 30, every button hit-tests to itself and sits inside the panel, and the title attribute carries the full path. Typecheck, lint, the kite3d suite (8 tests) and the scripts tests (2 tests) all pass. Co-Authored-By: Claude Fable 5.1 --- .../editor/src/components/InsSectionTitle.tsx | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/components/InsSectionTitle.tsx b/packages/editor/src/components/InsSectionTitle.tsx index 3d487514..94058d1a 100644 --- a/packages/editor/src/components/InsSectionTitle.tsx +++ b/packages/editor/src/components/InsSectionTitle.tsx @@ -3,23 +3,39 @@ import {MaybeElement} from "@blueprintjs/core/src/common/props.ts"; import {Icon} from "@blueprintjs/core"; import React from "react"; +// `clip` and not `hidden`: a hidden box is a scroll container, and Chrome reserves a scrollbar width +// inside it, which opens a hole in the middle of the path. +const clip: React.CSSProperties = {minWidth: 0, overflow: "clip"} + +/** + * One line, at every panel width. The end of the title names the thing, so the folder in front of it + * is dimmed and gives up its width a hundred times faster. The whole title stays in the tooltip. + */ export function InsSectionTitle({title, icon}: { title: string, icon?: IconName | MaybeElement }) { + const nameAt = title.lastIndexOf('/') + 1 return
- {icon && (typeof icon === 'string' ? : icon)} + {icon && (typeof icon === 'string' ? : icon)} - {title} + {/* One flex item, so the row's gap never opens inside a path. */} + + {nameAt > 0 && + {title.slice(0, nameAt)} + } + {title.slice(nameAt)} +
; }