feat: replace native select dropdowns with custom dropdown menus#12
feat: replace native select dropdowns with custom dropdown menus#12dingmeng-xue wants to merge 2 commits into
Conversation
- Replace turn and subagent <select> elements with custom button+menu components - Add unified closeDropdowns handler for all three filter dropdowns - Add Event Filters section to sidebar - Update e2e tests to match new custom dropdown selectors
There was a problem hiding this comment.
Pull request overview
This PR updates the session detail UI to replace native <select> controls (Turn navigation + Subagent filter) with custom button+menu dropdowns aligned with the existing Event Type filter, and adds an “Event Filters” button group to the sidebar.
Changes:
- Replaced Turn and Subagent
<select>inputs with custom toggles + floating menus, including mutual close behavior and outside-click close. - Added an “Event Filters” section in the sidebar using the existing computed
filters. - Updated E2E tests to use the new dropdown toggle/menu item selectors.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| views/session-vue.ejs | Adds styling for sidebar event filter buttons and new custom dropdown components. |
| src/frontend/session-detail.js | Adds open/close state for new dropdowns, outside-click close logic, sidebar filter buttons, and replaces select-based markup with custom menus. |
| package-lock.json | Updates multiple dependency versions (including runtime deps). |
| tests/e2e/subagent-view.spec.js | Adjusts selectors/interactions to operate the new subagent custom dropdown. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <button | ||
| class="turn-dropdown-toggle" | ||
| :class="{ active: currentTurnIndex > 0 }" | ||
| @click.stop="turnFilterOpen = !turnFilterOpen; subagentFilterOpen = false; typeFilterOpen = false" | ||
| > | ||
| <option v-for="turn in req.turns" :key="turn.id" :value="turn.id"> | ||
| Turn {{ turn.originalTurnId ?? turn.id }} ({{ turn.duration }}) | ||
| </option> | ||
| </optgroup> | ||
| </select> | ||
| 🔄 {{ currentTurnIndex > 0 ? 'Turn ' + (turns[currentTurnIndex]?.originalTurnId ?? currentTurnIndex) : 'All Turns' }} ▾ | ||
| </button> |
There was a problem hiding this comment.
The turn dropdown toggle treats currentTurnIndex === 0 as the “All Turns” state (currentTurnIndex > 0 ? ... : 'All Turns'), but turn id 0 is a real/valid turn (the first turn). This makes the label/active styling incorrect after selecting the first turn (and likely on initial load). Consider using a distinct sentinel value for “All Turns” (e.g., null/-1) and/or add an explicit “All Turns” menu item, and update the active/label logic accordingly.
| <div | ||
| v-for="turn in req.turns" | ||
| :key="turn.id" | ||
| :class="['turn-dropdown-menu-item', { active: currentTurnIndex === turn.id }]" | ||
| @click="currentTurnIndex = turn.id; jumpToTurn(turn.id); turnFilterOpen = false" | ||
| > | ||
| <span class="turn-dropdown-menu-label">Turn {{ turn.originalTurnId ?? turn.id }}</span> | ||
| <span class="turn-dropdown-menu-duration">{{ turn.duration }}</span> | ||
| </div> |
There was a problem hiding this comment.
The custom turn dropdown menu items are plain <div> elements with only @click, so they aren’t keyboard-focusable and don’t expose menu semantics to assistive tech. Consider using semantic elements (e.g., <button>), or add appropriate role/tabindex plus key handlers (Enter/Space/Escape/Arrow keys) and aria-expanded/aria-controls on the toggle.
| <div | ||
| :class="['subagent-dropdown-menu-item', { active: !selectedSubagent }]" | ||
| @click="selectSubagent(null); subagentFilterOpen = false" | ||
| > | ||
| <span class="subagent-dropdown-menu-label">🤖 All Agents</span> | ||
| </div> | ||
| <div | ||
| v-for="sa in subagentList" | ||
| :key="sa.toolCallId" | ||
| :class="['subagent-dropdown-menu-item', { active: selectedSubagent === sa.toolCallId }]" | ||
| @click="selectSubagent(sa.toolCallId); subagentFilterOpen = false" | ||
| > | ||
| <span class="subagent-dropdown-menu-label">🤖 {{ sa.name }}</span> | ||
| </div> |
There was a problem hiding this comment.
The custom subagent dropdown menu items are <div> elements with @click only, which are not keyboard accessible and lack ARIA menu semantics. Consider switching these menu items to <button> (preferred) or add role/tabindex and keyboard handlers, and wire aria-expanded/aria-controls on the toggle.
| cursor: pointer; | ||
| font-size: 12px; | ||
| transition: all 0.2s; | ||
| white-space: nowrap; |
There was a problem hiding this comment.
.filter-btn forces white-space: nowrap but doesn’t constrain width or apply ellipsis. Event type strings can be long, so these buttons can overflow the sidebar and cause horizontal scrolling. Consider adding a max-width with overflow: hidden; text-overflow: ellipsis; (or allowing wrapping).
| white-space: nowrap; | |
| white-space: nowrap; | |
| max-width: 100%; | |
| overflow: hidden; | |
| text-overflow: ellipsis; |
| .subagent-dropdown-toggle { | ||
| padding: 4px 10px; | ||
| background: #161b22; | ||
| border: 1px solid #30363d; | ||
| border-radius: 6px; | ||
| color: #c9d1d9; | ||
| font-size: 13px; | ||
| cursor: pointer; | ||
| max-width: 220px; | ||
| white-space: nowrap; | ||
| transition: all 0.2s; | ||
| } |
There was a problem hiding this comment.
.subagent-dropdown-toggle forces white-space: nowrap without a max-width/ellipsis, so long subagent names can overflow the toolbar (especially on mobile where the previous max-width was removed). Consider adding max-width + overflow: hidden; text-overflow: ellipsis; similar to the menu label styling.
|
@dingmeng-xue |


Replace native
<select>elements for Turn navigation and Subagent filter with custom button+menu components, consistent with the Event Type filter style.Changes:
.subagent-dropdown-toggle/.subagent-dropdown-menu-itemselectorsUpdated Part is