--- date: 2026-10-18 pr: pending feature: Phase 007 - full naive-ui to Arco Design Vue migration across all remaining views impact: Rendering-layer only. Every naive-ui component in packages/client/src is replaced by its Arco Design Vue equivalent across 24 views and roughly 80 components, and the naive-ui dependency is removed from package.json and package-lock.json. No chat store logic, no /chat-run payload, and no message rendering path is touched. Three chat-chain files changed as a consequence of that rendering-only sweep, listed below with the specific reason each needed a change. --- # Phase 007 — full Arco migration Phase 006 moved the chat page. Phase 007 finished the job: `grep -rn "naive-ui\|vueuc\|@css-render" packages/client/src` is now empty, and the project has exactly one UI library. Batches 7a-7g each shipped independently per `docs/phases/phase_007.md`. `docs/arco-migration-rules.md` holds the component mapping table the whole sweep followed. ## Why chat-chain files changed Four files under the chat chain were caught by the sweep. None of the changes touch logic. ### `chat/ChatPanel.vue` - Three leftover naive CSS custom properties were still referenced: `--n-text-color-3` (twice) and `--n-color-hover` (once). These were dead after Phase 006 — the variables no longer resolve, so the rules silently did nothing. Rewritten to the project's own tokens (`--text-muted`, `--bg-card-hover`). - `:native-scrollbar="false"` on the workspace dropdown had no Arco counterpart and was dropped. ### `group-chat/GroupChatInput.vue` - Eighteen dead naive rules under `.tool-trace-toggle`, `.input-settings-button` and `.send-button` targeted `.n-button__content`, `.n-button__icon`, `.n-button__border`, `.n-button__state-border`, `.n-button__ripple` and `.n-base-wave`. Arco's `a-button` has no content wrapper and none of the ripple internals, so `gap` now lives on the button itself and the ripple rules were deleted rather than renamed. - The settings button was `NDropdown > NTooltip > NButton` — a three-deep Trigger nest. Arco's Trigger components each claim the first element child via `mergeFirstChild`, so nested popups fight over it and the menu never opens. Flattened to `a-dropdown > a-button` with the description moved to a native `:title`, which is the same approach Phase 006 already took in `ChatInput.vue`. - The attach tooltip carried its label as trailing default-slot text. Arco renders the default slot inline, so that text became a zero-width flex item in the toolbar. Moved to the `content` prop. ### `group-chat/CreateRoomForm.vue` - Straight component swap. `InputLikeInstance = { focus: () => void }` was kept because Arco's `a-input` still exposes `focus()` (`es/input/input.js:315`), so the existing `nextTick` focus calls still work. ### `group-chat/GroupChatPanel.vue` - The room context menu was `NDropdown` in `trigger="manual"` mode driven by `:x` / `:y` / `:show` / `@clickoutside`. Arco has no manual trigger, so it became `a-trigger trigger="contextMenu"` with `:popup-style` for coordinates, matching the pattern already used by `FileContextMenu.vue` and `WorkflowView.vue`. Arco's `clickOutsideToClose` defaults to true, which replaces the hand-written clickoutside handler. - `NPopover`'s `placement="bottom-end"` maps to Arco `position="br"` (bottom-right). Arco's `a-popover` has no `width` prop and its `Trigger` sets `inheritAttrs: false`, so a `:width` would be dropped silently; the width moved to `:content-style`. ## Verification `packages/client/src` has zero naive references by three independent checks — `naive-ui` imports, `.n-*` class names in style blocks, and `--n-*` custom properties. The last two matter because `grep naive-ui` cannot see them; `tests/client/no-naive-ui.test.ts` now guards all three so the patterns cannot come back. ## Behavior impact Rendering-layer only. No chat store logic, no `/chat-run` payload, and no message rendering path was touched. The group-chat message bubbles already used plain HTML and were left untouched, so the "no Arco components inside bubbles" rule still holds — `a-tree`, `a-select` and the other components appear only outside the bubble.