fix(layout): bandeau d'erreur cellule au-dessus des boutons de contrôle (#48)

Corrige la superposition z-index dans LeafView : le bandeau d'erreur de
cellule passait sous les boutons de contrôle, rendant le message illisible.
Le voile d'annonces ciblées est réaligné en conséquence.

Couvert par un nouveau test de layering (128/128 frontend au vert QA).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 08:42:13 +02:00
parent 1331c5b2c2
commit e64c0b7840
3 changed files with 264 additions and 5 deletions

View File

@ -252,6 +252,28 @@ function goToCell(nodeId: string): void {
}, 1200);
}
/**
* Local z-index scale for a single cell (ticket #48). Intra-cell layering only —
* unrelated to the global {@link zIndex} scale used for app-level surfaces.
*
* The cell controls (agent selector, split, close) must stay reachable even when
* a non-modal banner is shown, otherwise a cell stuck in an error state (e.g. an
* agent launch failure) can no longer be managed. Full-cell veils (write-portal
* injection, F3 busy) deliberately cover the terminal and sit above the banners,
* but they are `pointer-events:none` and stay *below* the controls so the user
* can always re-pick an agent / split / close the cell.
*
* terminal 0 (implicit — the xterm surface)
* status/error 3 (in-cell status strip, launch-error banner, notices)
* full-cell veils 4 (write-portal + F3 overlays; mutually exclusive)
* cell controls 5 (always on top and clickable)
*/
const CELL_Z = {
banner: 3,
veil: 4,
controls: 5,
} as const;
function LeafView({
id,
session,
@ -597,7 +619,9 @@ function LeafView({
// edge, ~15px wide). Without this offset the right-most control — the
// close button — sits *behind* the scrollbar and is hard to click.
right: 16,
zIndex: 2,
// Above every banner/veil so a cell in an error state stays manageable
// (ticket #48).
zIndex: CELL_Z.controls,
display: "flex",
gap: 2,
alignItems: "center",
@ -711,7 +735,7 @@ function LeafView({
position: "absolute",
top: 30,
left: 4,
zIndex: 3,
zIndex: CELL_Z.banner,
display: "flex",
maxWidth: "calc(100% - 8px)",
alignItems: "center",
@ -878,7 +902,7 @@ function LeafView({
style={{
position: "absolute",
inset: 0,
zIndex: 4,
zIndex: CELL_Z.veil,
display: "flex",
alignItems: "center",
justifyContent: "center",
@ -886,6 +910,7 @@ function LeafView({
color: "var(--color-content, #e0e0e0)",
fontSize: 13,
pointerEvents: "none",
// veil tier — below the cell controls (ticket #48).
userSelect: "none",
}}
>
@ -924,7 +949,7 @@ function LeafView({
background: "var(--color-surface, #1e1e1e)",
padding: "2px 6px",
borderRadius: 3,
zIndex: 3,
zIndex: CELL_Z.banner,
display: "flex",
alignItems: "center",
justifyContent: "space-between",