diff --git a/docs/DOM-CHAT-PANEL.md b/docs/DOM-CHAT-PANEL.md new file mode 100644 index 0000000..28b4634 --- /dev/null +++ b/docs/DOM-CHAT-PANEL.md @@ -0,0 +1,367 @@ +# muse.ai Chat Panel & Sidechat DOM Reference + +> Captured live via CDP on `opm` browser (warp-opm netns, CDP 9440) on 2026-10-04. +> Page: `https://muse.ai/`, title "Chat — operator-main". +> This is a development reference for reliable automation of the chat navigation panel +> and sidechat creation. Prefer these selectors over text matching. + +--- + +## 1. Chat Panel Switcher + +**Selector:** `[data-testid="hatch-chat-switcher-trigger"]` + +The button that toggles the chat navigation panel open/closed. Always present in the DOM, +top-left of the viewport. + +```html + +``` + +**Key facts:** + +| Property | Value | +|---|---| +| Tag | `BUTTON` | +| Always in DOM | Yes (both panel states) | +| Visible | Yes (`offsetParent !== null`) | +| Position | Top-left: `x:84, y:12, w:82, h:36` | +| `aria-expanded` | **Not set** (`null`) — do NOT use for state detection | +| Visible text | `Chats` | +| Screen-reader text | `Open chat and side chats` | +| Icon | Hamburger menu (3 horizontal lines), not a chat bubble | + +**Parent chain (bottom-up, 4 levels):** + +``` +1. DIV [data-testid="hatch-chat-leading-controls"] + class="pointer-events-auto absolute start-3 top-0 flex h-[60px] items-center gap-2" +2. DIV (no testid) class="pointer-events-none absolute inset-x-0 top-0 z-10 h-44" +3. DIV (no testid) class="absolute inset-0 overflow-hidden" +4. DIV (no testid) class="relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden" +``` + +**Behavior:** The switcher **toggles**. Clicking when the panel is closed opens it; +clicking when open closes it. Always check panel state before clicking — never +blind-click. + +**Child testids** (for reference): +- `[data-testid="hatch-chat-switcher-icon-knockout"]` — icon wrapper span +- `[data-testid="hatch-chat-switcher-navigation-icon"]` — the hamburger SVG span + +--- + +## 2. Sidechat Create Button ("New side chat") + +**Selector:** `[data-testid="hatch-chat-compose"]` + +The `+` button that creates a new sidechat. **Only exists in the DOM when the panel +is OPEN.** This makes it the most reliable "panel is open and ready" signal. + +```html + +``` + +**Key facts:** + +| Property | Value | +|---|---| +| Tag | `BUTTON` | +| In DOM when panel closed | **No** — completely absent | +| In DOM when panel open | Yes | +| Text content | None (icon-only) | +| `aria-label` | `New side chat` | +| `title` | `New side chat` | +| Icon | Plus sign (`+`), single SVG path | + +**Parent chain (bottom-up, 8 levels):** + +``` +1. SPAN (no testid) class="contents" ← direct wrapper +2. DIV (no testid) class="group/nav-section flex w-full items-center" + children: [H3 "Side chats", SPAN(contents) > BUTTON#compose] +3. SECTION (no testid) class="flex flex-col" ← "Side chats" section + children: [DIV(header: H3 + compose), DIV(chat list)] +4. DIV (no testid) class="flex flex-col relative grow-1" + children: [DIV[data-testid="hatch-thread-row"] (Main chat), + SECTION (Side chats), + DIV[data-testid="active-side-chat-load-more-sentinel"]] +5. DIV (no testid) class="flex flex-col overflow-hidden relative z-0 overflow-y-auto overscroll-y-contain min-h-0 min-w-0 flex-1 px-3 pb-3" +6. DIV (no testid) class="flex min-h-0 flex-1 flex-col" +7. DIV (no testid) class="text-text-primary flex h-full min-h-0 w-full flex-col overflow-hidden" +8. DIV (no testid) class="min-h-0 min-w-0 flex-1" +``` + +**Location in UI:** Inside the "Side chats" section header row, to the right of the +`H3` "Side chats" collapsible heading. + +**What clicking does:** Creates a new sidechat. Browser navigates to +`https://muse.ai/thread/new` (placeholder URL; the real thread UUID appears after +the first message is sent or navigation settles). + +--- + +## 3. Chat Navigation Panel Structure + +### 3a. Panel shell (always in DOM) + +**Selector:** `[data-testid="hatch-side-chats-panel-shell"]` + +```html +
+ +
+``` + +| State | `innerHTML` | `innerText` | +|---|---|---| +| Closed | `""` (empty string) | `""` | +| Open | Full `