8.3 KiB
DOM Reference: Settings, Profile & Dock Rail
Inspected live via CDP on the opm browser (warp-opm netns, CDP 9440), 2026-10-04. Structure only — no credential, token, or personal values are recorded here.
Related: DOM-CHAT-PANEL.md (chat panel), DOM-MESSAGES.md (messages),
DOM-PAGE-STRUCTURE.md (page states).
1. Dock rail
The left vertical nav rail. Container:
<div data-testid="hatch-dock-rail" class="relative flex h-full">
Rail items (top to bottom)
| # | Selector | Tag | aria-label |
Notes |
|---|---|---|---|---|
| 1 | [data-testid="hatch-nav-chat"] |
<a href="/"> |
Chat |
The chat/message button from the user's screenshot. Navigates /thread/new → https://muse.ai/. See "chat activation" below. |
| 2 | [data-testid="hatch-nav-search"] |
<button> |
Search |
Opens quick-search dialog [data-testid="hatch-quick-search-frame"] (heading "Search Muse"). |
| 3 | (none) | <button> |
Get the Muse app |
App download upsell. No data-testid. |
| 4 | [data-testid="hatch-dock-more"] |
<button> |
Settings |
Opens the settings menu (radix menu). Bottom of rail (div.mt-auto). |
Parent chain of the settings button (4 levels):
div[data-testid="hatch-dock-rail"].relative.flex.h-full
> div.relative.z-10.flex
> div.mt-auto.flex.flex-col
> button#radix-_[data-testid="hatch-dock-more"].hatch-dock-reveal-item.group.relative
Key attributes on the button:
<button type="button"
aria-label="Settings"
data-testid="hatch-dock-more"
aria-haspopup="menu"
aria-expanded="false" <!-- unreliable: stays "false" even when menu is open -->
data-state="closed" <!-- unreliable: stays "closed" even when menu is open -->
data-pel-click="settings_menu_open_click">
Automation note:
data-state/aria-expandeddo NOT reflect the real open state. Detect the open menu by counting[role="menuitem"]elements (> 0means open). Synthetic.click()does not open the radix menu; use real mouse events via CDPInput.dispatchMouseEvent(mousePressed+mouseReleasedat the button center). The button toggles, so click only when[role="menuitem"]count is 0.
Chat activation via hatch-nav-chat
Clicking [data-testid="hatch-nav-chat"] from the stripped /thread/new state
navigates to https://muse.ai/ and the chat switcher appears (~1s). This is
the reliable "activate chat" primitive — see the _ensure_chat_active()
logic in muse-chat-api.py (priority: compose → switcher → nav-chat).
aria-label on this link is unstable ("Chat" vs "Chat, N notification");
always match on the data-testid.
2. Settings menu (dock "more" menu)
Radix menu rendered in a popper. Items (role="menuitem", no data-testid):
| Text | data-pel-click |
Action (observed) |
|---|---|---|
| Keyboard shortcuts | keyboard_shortcuts_nav_click |
No dialog rendered under automation (see §5) |
| Download apps | mobile_app_upsell_menu_click |
— (not opened) |
| Report an issue | bug_report_nav_click |
— (not opened) |
| Settings | settings_nav_click |
Opens the Settings dialog (§3) |
Menu container selectors (either may match):
document.querySelector('[role="menu"]')
document.querySelector('[data-radix-popper-content-wrapper]')
Find a menuitem reliably:
[...document.querySelectorAll('[role="menuitem"]')]
.find(m => m.getAttribute('data-pel-click') === 'settings_nav_click')
3. Settings dialog
A radix dialog (div[role="dialog]", id like radix-_r_10g_; the id suffix
is random per render — do not hardcode it).
div#radix-_<role=dialog>
- Heading is an
H2with textSettings(noth1). - Layout: left nav column + right content column.
3a. Left nav (section buttons)
Plain <button> elements, no data-testids. In order:
General
Connectors
Wallet
Secure store
Permissions
Messaging channels
Devices
Data controls
Help & support
Legal info
Log out ← the sign-out control; no confirmation dialog observed at open
Close
3b. General section
Headings (all h2): General, Usage, Appearance.
Usage — one button:
| Control | Label | Notes |
|---|---|---|
<button> |
Upgrade |
Plan upgrade upsell |
Appearance — theme + accent color:
| Control | Label |
|---|---|
<button> |
Light |
<button> |
Dark |
<button> |
System |
<input type="radio"> |
Match my avatar |
<input type="radio"> |
Default |
<input type="radio"> |
Blue |
<input type="radio"> |
Purple |
<input type="radio"> |
Pink |
<input type="radio"> |
Orange |
<input type="radio"> |
Green |
<input type="radio"> |
Beige |
<input type="radio"> |
Monochrome |
3c. Profile / avatar
- Avatar image:
<img>with emptyalt,srcpresent (value not recorded). Nodata-testidon the img. Edit avatar and namebutton (aria-label="Edit avatar and name",<button>, nodata-testid) appears in the profile area of the settings dialog. Chain (3 levels):
div.pointer-events-auto.absolute.z-20
> div.group-has-[[data-hatch-avatar-media-loading]]/status-avatar:hidden
> span.contents
> button[aria-label="Edit avatar and name"].inline-flex.shrink-0.cursor-pointer
3d. Other sections (not opened)
Connectors, Wallet, Secure store, Permissions, Messaging channels,
Devices, Data controls, Help & support, Legal info were not opened
during mapping (each is a left-nav <button>; clicking one swaps the right
content column). Secure store / Wallet likely contain credential-adjacent
UI — map with care, structure only, never values.
4. Account switching
No multi-account switcher was observed in the settings dialog or dock
rail. The only account control found is the Log out button in the settings
left nav. Each Muse account runs in its own isolated browser profile
(muse, pip, 646, opm nodes), so in this fleet account switching
happens at the profile level, not inside the app UI.
5. Keyboard shortcuts modal
Menu item exists:
[...document.querySelectorAll('[role="menuitem"]')]
.find(m => m.getAttribute('data-pel-click') === 'keyboard_shortcuts_nav_click')
Clicking it via automation (menuitem .click() after opening the dock menu
with real mouse events) produced no [role="dialog"] within 3s and no
URL change. The modal likely requires a trusted user gesture deeper in the
radix event chain, or renders on a longer delay. Status: selector documented,
modal content not captured — needs a headed/manual pass or longer wait.
6. Quick reference: reliable selectors
// Dock rail
'[data-testid="hatch-dock-rail"]'
'[data-testid="hatch-nav-chat"]' // chat button (stable; aria-label unstable)
'[data-testid="hatch-nav-search"]' // search
'[data-testid="hatch-dock-more"]' // settings menu trigger
// Settings menu (after real mouse click on hatch-dock-more)
'[role="menuitem"]' // count > 0 => menu open
'[data-pel-click="settings_nav_click"]'
'[data-pel-click="keyboard_shortcuts_nav_click"]'
'[data-pel-click="bug_report_nav_click"]'
'[data-pel-click="mobile_app_upsell_menu_click"]'
// Settings dialog
'div[role="dialog"]' // id is random per render
'button[aria-label="Edit avatar and name"]'
// Search dialog
'[data-testid="hatch-quick-search-frame"]'
7. Automation recipes
Open the settings menu:
// 1. real mouse click at button center (synthetic .click() does NOT work)
const b = document.querySelector('[data-testid="hatch-dock-more"]');
const r = b.getBoundingClientRect();
// CDP: Input.dispatchMouseEvent mousePressed + mouseReleased at (r.x + r.width/2, r.y + r.height/2)
// 2. verify: document.querySelectorAll('[role="menuitem"]').length > 0
// (the button toggles — only click when count is 0)
Open the Settings dialog:
[...document.querySelectorAll('[role="menuitem"]')]
.find(m => m.getAttribute('data-pel-click') === 'settings_nav_click')
.click();
// dialog appears in ~2s: document.querySelector('div[role="dialog"]')
// heading: [...document.querySelectorAll('h2')].find(h => h.innerText.trim() === 'Settings')
Close any dialog: Escape keydown (works for the settings dialog).