frontend: drop the Panel forwarding object and the side-panel-body compat class
Per mara's review: '2 and maybe 1, but 3 also sounds reasonable on first
glance' (against 3 options I posted). Doing 2 and 1, leaving open()/
openNamed() as-is (option 3, tentative only).
Both dashboard/common.js and agent/app.js now export/use the
<hive-side-panel> element instance directly (sidePanel) instead of a
thin Panel = { open, openNamed, refresh, close } object that existed
purely to keep the old call-site shape unchanged. All 6 real call sites
updated to call the element's own methods directly.
The .side-panel-body class each wrapper stamped onto its own instance,
purely so common.css/agent.css's pre-existing content-styling selectors
kept matching, is gone too -- those selectors now use the element's own
tag name as the root (hive-side-panel .md, hive-side-panel .agent-inbox),
which already uniquely identifies the light-DOM instance without a
compatibility class. Verified via headless Chromium/CDP that the
tag-name selectors resolve correctly with no class needed.
Drive-by: removed an unrelated dead Panel import in call.js.
This commit is contained in:
parent
996899fcad
commit
399a837e17
8 changed files with 73 additions and 90 deletions
|
|
@ -14,7 +14,7 @@
|
|||
// live-mutation paths call an injected `onCountsChanged` callback the entry
|
||||
// registers once via `initCall`.
|
||||
|
||||
import { $, form, Panel, appendLinkified } from './common.js';
|
||||
import { $, form, appendLinkified } from './common.js';
|
||||
import { el } from '@hive/shared/dom.js';
|
||||
import { themedToast } from '@hive/shared/modal.js';
|
||||
import { epochSec, fmtAgo, fmtDuration } from './util.js';
|
||||
|
|
|
|||
|
|
@ -376,49 +376,49 @@ code {
|
|||
not just the shared element's own shadow tree) and the styling for
|
||||
the panel's own content types, which the shared element's shadow tree
|
||||
can never reach (see @hive/shared/side-panel/hive-side-panel.css's
|
||||
header comment). `.side-panel-body` below is the compatibility class
|
||||
common.js's `Panel` wrapper puts directly on its `<hive-side-panel>`
|
||||
instance so these rules keep reaching the slotted content by ordinary
|
||||
light-DOM descendant matching. */
|
||||
header comment). The `hive-side-panel .md …` rules below use the
|
||||
element's own tag name as the selector root — no compatibility class
|
||||
needed, the tag name already uniquely identifies the light-DOM
|
||||
instance `common.js`'s `sidePanel` creates. */
|
||||
body.side-panel-resizing {
|
||||
user-select: none;
|
||||
}
|
||||
body.side-panel-resizing * { cursor: ew-resize !important; }
|
||||
.side-panel-body .md { color: var(--fg); line-height: 1.5; }
|
||||
.side-panel-body .md > :first-child { margin-top: 0; }
|
||||
.side-panel-body .md > :last-child { margin-bottom: 0; }
|
||||
.side-panel-body .md p { margin: 0.5em 0; }
|
||||
.side-panel-body .md h1,
|
||||
.side-panel-body .md h2,
|
||||
.side-panel-body .md h3,
|
||||
.side-panel-body .md h4 { color: var(--purple); margin: 0.9em 0 0.4em; }
|
||||
.side-panel-body .md code {
|
||||
hive-side-panel .md { color: var(--fg); line-height: 1.5; }
|
||||
hive-side-panel .md > :first-child { margin-top: 0; }
|
||||
hive-side-panel .md > :last-child { margin-bottom: 0; }
|
||||
hive-side-panel .md p { margin: 0.5em 0; }
|
||||
hive-side-panel .md h1,
|
||||
hive-side-panel .md h2,
|
||||
hive-side-panel .md h3,
|
||||
hive-side-panel .md h4 { color: var(--purple); margin: 0.9em 0 0.4em; }
|
||||
hive-side-panel .md code {
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 2px;
|
||||
padding: 0.1em 0.3em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.side-panel-body .md pre {
|
||||
hive-side-panel .md pre {
|
||||
background: var(--crust);
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.5em 0.7em;
|
||||
overflow-x: auto;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
.side-panel-body .md pre code { background: none; border: none; padding: 0; }
|
||||
.side-panel-body .md a { color: var(--cyan); }
|
||||
.side-panel-body .md ul,
|
||||
.side-panel-body .md ol { margin: 0.4em 0; padding-left: 1.5em; }
|
||||
.side-panel-body .md blockquote {
|
||||
hive-side-panel .md pre code { background: none; border: none; padding: 0; }
|
||||
hive-side-panel .md a { color: var(--cyan); }
|
||||
hive-side-panel .md ul,
|
||||
hive-side-panel .md ol { margin: 0.4em 0; padding-left: 1.5em; }
|
||||
hive-side-panel .md blockquote {
|
||||
border-left: 3px solid var(--purple-dim);
|
||||
padding-left: 0.8em;
|
||||
margin: 0.4em 0;
|
||||
color: var(--muted);
|
||||
}
|
||||
.side-panel-body .md table { border-collapse: collapse; margin: 0.5em 0; }
|
||||
.side-panel-body .md th,
|
||||
.side-panel-body .md td {
|
||||
hive-side-panel .md table { border-collapse: collapse; margin: 0.5em 0; }
|
||||
hive-side-panel .md th,
|
||||
hive-side-panel .md td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.2em 0.5em;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -281,30 +281,21 @@ export function openBuildLogStream(id, pre, { onDone, onError } = {}) {
|
|||
// ─── side panel ─────────────────────────────────────────────────────────
|
||||
// Singleton drawer that swipes in from the right. Long content
|
||||
// (file previews, approval diffs, journald logs, applied config)
|
||||
// opens here via `Panel.open(title, node)` instead of expanding
|
||||
// opens here via `sidePanel.open(title, node)` instead of expanding
|
||||
// inline. Body is swapped on each open; closing just slides out so
|
||||
// the content stays visible through the transition.
|
||||
//
|
||||
// Thin wrapper around the shared `<hive-side-panel>` element (see
|
||||
// @hive/shared/side-panel.js for the chrome/behavior it owns, including
|
||||
// drag-to-resize). The instance is created once, eagerly, at module
|
||||
// evaluation time — ES modules run after the document is parsed (same
|
||||
// timing `defer` scripts get), so `document.body` already exists here;
|
||||
// no per-call lazy-init guard needed, and no easy-to-forget step for
|
||||
// any new method added later. `side-panel-body` is a plain compatibility
|
||||
// class this wrapper puts on its own instance so `common.css`'s
|
||||
// existing `.side-panel-body .md …` rules keep reaching the slotted
|
||||
// content by ordinary light-DOM descendant matching — the shared
|
||||
// element itself has no idea that class name means anything.
|
||||
const panelEl = document.createElement('hive-side-panel');
|
||||
panelEl.classList.add('side-panel-body');
|
||||
document.body.append(panelEl);
|
||||
export const Panel = {
|
||||
open: (title, content) => panelEl.open(title, content),
|
||||
openNamed: (name, title, content) => panelEl.openNamed(name, title, content),
|
||||
refresh: (name, title, content) => panelEl.refresh(name, title, content),
|
||||
close: () => panelEl.close(),
|
||||
};
|
||||
// The instance is created once, eagerly, at module evaluation time — ES
|
||||
// modules run after the document is parsed (same timing `defer` scripts
|
||||
// get), so `document.body` already exists here. Exported directly (not
|
||||
// wrapped in a forwarding object) — callers use the element's own
|
||||
// `open`/`openNamed`/`refresh`/`close`/`currentOwner` methods, see
|
||||
// @hive/shared/side-panel.js for what they do. `common.css` reaches the
|
||||
// slotted content via a plain `hive-side-panel .md …` tag-name selector
|
||||
// (no compatibility class needed — the element's own tag name already
|
||||
// uniquely identifies it in the light DOM).
|
||||
export const sidePanel = document.createElement('hive-side-panel');
|
||||
document.body.append(sidePanel);
|
||||
|
||||
// ─── path linkification ─────────────────────────────────────────────────
|
||||
// Agents constantly drop pointer strings into messages + question
|
||||
|
|
@ -395,14 +386,14 @@ async function openFilePanel(path) {
|
|||
'(could not load image — it may be missing or over the preview size cap)'));
|
||||
});
|
||||
img.src = '/api/state-file?path=' + encodeURIComponent(path);
|
||||
Panel.open('↳ ' + path, img);
|
||||
sidePanel.open('↳ ' + path, img);
|
||||
return;
|
||||
}
|
||||
const isMd = /\.(md|markdown)$/i.test(path);
|
||||
const isSvg = /\.svg$/i.test(path);
|
||||
const view = el('div');
|
||||
view.textContent = '(fetching…)';
|
||||
Panel.open('↳ ' + path, view);
|
||||
sidePanel.open('↳ ' + path, view);
|
||||
try {
|
||||
const text = await fetchStateFile(path);
|
||||
if (isSvg) {
|
||||
|
|
|
|||
|
|
@ -276,8 +276,8 @@ window.marked = marked;
|
|||
// NOTIF.bind() (the enable/mute/unmute toggle UI) moved to /settings.html
|
||||
// with the S3TT1NGS page. The dashboard keeps NOTIF.show() for approval/
|
||||
// question notifications — it reads the browser permission + localStorage
|
||||
// mute flag the settings page sets, so no bind() is needed here. Panel
|
||||
// (backed by <hive-side-panel>) wires its own internals in
|
||||
// mute flag the settings page sets, so no bind() is needed here. The
|
||||
// side panel (<hive-side-panel>) wires its own internals in
|
||||
// connectedCallback — no bind() step needed either.
|
||||
|
||||
// ─── live updates: dashboard event stream ──────────────────────────────
|
||||
|
|
|
|||
Loading…
Reference in a new issue