Skip to content
Merged
22 changes: 22 additions & 0 deletions webviews/src/agent-session/acpmux/chatUnderGlass.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// What a glass floating over the chat covers, for its in-place blur (ui/glass/seeThroughBlur.ts):
// the chat stage's own blocks (its header, the transcript, a strip or a panel in it), never a whole
// column. The Summary popover sits in the stage and Session Info beside the chat's column
// (.acpmux-main), so a column-wide filter would also take the composer and make the column one
// stacking context; the stage's blocks are only what is under the glass. The surfaces themselves are
// skipped by seeThroughBlur.
import type { CoveredCandidates, SeeThroughOptions } from "../../ui/glass/seeThroughBlur";

export const chatUnderGlass: CoveredCandidates = (surface) =>
surface.closest(".acpmux-shell")?.querySelectorAll(".acpmux-stage > *") ?? [];

// The composer never takes a filter (it would re-anchor the composer's fixed menus), so a glass over
// it keeps its underlay there: a short pane's Session Info reaches down over the composer.
const composer: CoveredCandidates = (surface) =>
surface.closest(".acpmux-shell")?.querySelectorAll(".acpmux-dock") ?? [];

/** Session Info's overlay. */
export const chatGlass: SeeThroughOptions = { keepUnderlayOver: composer };

/** The Summary popover: its blocks carry data-glass-under="summary", which summary.css switches off
* while it hides the card (Find, review, inspect), with no observer to see that happen. */
export const summaryGlass: SeeThroughOptions = { owner: "summary", keepUnderlayOver: composer };
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ import {
type ReactNode,
} from "react";
import { flushSync } from "react-dom";
import { useSeeThroughBlur } from "../../../ui/glass/seeThroughBlur";
import { chatGlass, chatUnderGlass } from "../chatUnderGlass";
import { usePresence, type Presence } from "../../../ui/presence";
import { useChatDisplay } from "../chatDisplay";
import { CHAT_LAYOUT_EVENT, chatColumnOf, useChatSizing, type ChatColumn } from "../chatWidth";
Expand Down Expand Up @@ -861,6 +863,11 @@ export function SessionInfoPanel({
const t = useT();
const frame = useRef<HTMLElement | null>(null);
const drag = useRef<{ right: number } | undefined>(undefined);
// Floating over the chat (the narrow pane's Summary popover), the chat under it blurs itself there in
// a see-through Chromium page (ui/glass/seeThroughBlur.ts), as WebKit's backdrop draws it, so its
// text never reads through the glass (Leo 2026-10-30: "I don't like the non-glassness"). Pushing,
// it sits beside the chat and covers nothing.
useSeeThroughBlur(frame, placement === "overlay", chatUnderGlass, chatGlass);
// The foot animates only once it has been drawn at its first measure: the open draws it at once.
const footKnown = foot !== undefined && foot > 0;
const [footSettled, setFootSettled] = useState(false);
Expand Down
7 changes: 7 additions & 0 deletions webviews/src/agent-session/acpmux/summary/SummaryCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React, { useEffect, useMemo, useRef, useState } from "react";
import { flushSync } from "react-dom";
import { useEscapeCloses } from "../../../ui/escapeDismiss";
import { useSeeThroughBlur } from "../../../ui/glass/seeThroughBlur";
import { chatUnderGlass, summaryGlass } from "../chatUnderGlass";
import { usePresence } from "../../../ui/presence";
import { useT } from "../i18n";
import { Icon } from "../icons/Icon";
Expand Down Expand Up @@ -141,6 +143,11 @@ export function SummaryCard({
[shown, registry.processes, registry.listed, summary, running],
);
const panel = useRef<HTMLElement>(null);
// The popover floats over the chat: in a see-through Chromium page the chat under it blurs itself
// there (ui/glass/seeThroughBlur.ts), as WebKit's backdrop draws it, so its text never reads
// through the glass (Leo 2026-10-30: "I don't like the non-glassness"). The inline column is
// beside the chat and covers nothing.
useSeeThroughBlur(panel, drawn && !card.column, chatUnderGlass, summaryGlass);
const popover = shown && !card.column;
const edges = useScrollEdges();
const close = card.close;
Expand Down
3 changes: 3 additions & 0 deletions webviews/src/agent-session/acpmux/summary/summary.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 14 additions & 1 deletion webviews/src/ui/glass/glass.css
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@
page's flow (a user's bubble, a settings card) has nothing under it and keeps its tint, as in
WebKit. WebKit (which keeps -webkit-backdrop-filter), an opaque window and the lens (whose canvas
is under the glass) keep the tint alone. The strength is the experiment chromium-glass-underlay
(chromiumUnderlay.experiment.ts, which desktop.ts puts on <html>). */
(chromiumUnderlay.experiment.ts, which desktop.ts puts on <html>). A surface whose page blurs
itself under it (seeThroughBlur.ts, below) needs no underlay and draws none. */
:root {
--glass-underlay: 70%;
}
Expand All @@ -163,6 +164,18 @@
linear-gradient(var(--glass-tint), var(--glass-tint)),
color-mix(in srgb, var(--glass-surface) var(--glass-underlay), transparent);
}
/* THE PAGE BLURS ITSELF UNDER THE GLASS (Leo 2026-10-30, on the Summary popover: "I don't like
the non-glassness"). A surface that uses seeThroughBlur.ts (data-glass-over) makes what it
covers blur its own pixels inside the surface's rounded rect: each covered element
(data-glass-under) draws through its own SVG filter. The text under the glass is then
blurred in place, as WebKit's backdrop draws it, so the surface needs no underlay to hide it:
its tint and that blur carry the legibility (design/overlay-surfaces.md). */
:root[data-cmux-see-through]:not([data-glass-lens], [data-reduce-transparency]) [data-glass-under] {
filter: var(--glass-under-filter);
}
:root[data-cmux-see-through]:not([data-glass-lens], [data-reduce-transparency]) .ui-glass[data-glass-over] {
--glass-underlay: 0%;
}
}
}

Expand Down
Loading
Loading