@nextclaw/ui 0.15.2 → 0.15.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/assets/aiden0z-pptx-renderer.es-Bd99vut2.js +94 -0
  3. package/dist/assets/api-BOXOrpcJ.js +13 -0
  4. package/dist/assets/app-presenter-provider-CkHLbvZQ.js +106 -0
  5. package/dist/assets/app-presenter-provider-D3BuuOyZ.css +1 -0
  6. package/dist/assets/appearance-settings-page-fLIJbx1C.js +1 -0
  7. package/dist/assets/{book-open-Ba2f7YiG.js → book-open-DWUjS6aW.js} +1 -1
  8. package/dist/assets/channels-list-page-CvCTJraa.js +8 -0
  9. package/dist/assets/chat-page-B42UUIFR.js +1 -0
  10. package/dist/assets/chunk-DseTPa7n.js +1 -0
  11. package/dist/assets/config-split-page-DBgt9S8b.js +1 -0
  12. package/dist/assets/confirm-dialog-GSXIvoRU.js +5 -0
  13. package/dist/assets/desktop-update-config-7bmNeWIC.js +1 -0
  14. package/dist/assets/dist-DC7f4TJH.js +41 -0
  15. package/dist/assets/doc-browser-CgdoLUT92.js +1 -0
  16. package/dist/assets/doc-browser-D0monHjG.js +1 -0
  17. package/dist/assets/doc-browser-context-CGwEOhBy.js +1 -0
  18. package/dist/assets/docx-preview-eFH9DRsS.js +20 -0
  19. package/dist/assets/download-DiP9zx-J.js +1 -0
  20. package/dist/assets/{external-link-DxuPaDoK.js → external-link-C6ZeSPef.js} +1 -1
  21. package/dist/assets/eye-suvKmtwn.js +1 -0
  22. package/dist/assets/folder-CMELbQGG.js +1 -0
  23. package/dist/assets/{form-actions-BztL7P_T.js → form-actions-CUAzpNe_.js} +1 -1
  24. package/dist/assets/index-BFeNDQ4R.css +1 -0
  25. package/dist/assets/index-D_6U-M94.js +2 -0
  26. package/dist/assets/jszip.min-Das2IAnb.js +2 -0
  27. package/dist/assets/loader-circle-tYHStefV.js +1 -0
  28. package/dist/assets/logo-badge-Cu5UGH_4.js +1 -0
  29. package/dist/assets/mcp-marketplace-page-BUzHDwW6.js +9 -0
  30. package/dist/assets/mcp-marketplace-page-ohUAdfqJ.js +1 -0
  31. package/dist/assets/model-config-page-CWP6pyBm.js +1 -0
  32. package/dist/assets/plus-tywizkeY.js +1 -0
  33. package/dist/assets/popover-DImguRok.js +1 -0
  34. package/dist/assets/provider-models-C_yOh6DE.js +1 -0
  35. package/dist/assets/provider-scoped-model-input-CE7p4SbJ.js +1 -0
  36. package/dist/assets/providers-config-page-BKPo8SjH.js +1 -0
  37. package/dist/assets/react-5sjAT_6d.js +8 -0
  38. package/dist/assets/{refresh-cw-eT8BF-8B.js → refresh-cw-CHLBzWWj.js} +1 -1
  39. package/dist/assets/remote-DXJryUxB.js +1 -0
  40. package/dist/assets/rotate-cw-BefO5brU.js +1 -0
  41. package/dist/assets/runtime-config-page-1Axv4QGu.js +1 -0
  42. package/dist/assets/{save-Cb2g0BOi.js → save-BABzyrjB.js} +1 -1
  43. package/dist/assets/{search-BcHjwdsb.js → search-BTqxG3ZG.js} +1 -1
  44. package/dist/assets/search-config-page-BkKKmxmS.js +1 -0
  45. package/dist/assets/secrets-config-page-CWJMyu-k.js +3 -0
  46. package/dist/assets/security-config-DeQUIXfi.js +1 -0
  47. package/dist/assets/select-TYZDBNmq.js +1 -0
  48. package/dist/assets/setting-row-DR23Z_5I.js +1 -0
  49. package/dist/assets/{settings-2-2DWauOjY.js → settings-2-D8WWcBnw.js} +1 -1
  50. package/dist/assets/{skeleton-P5oM14E1.js → skeleton-CloHeg0S.js} +1 -1
  51. package/dist/assets/tabs-CX-ckWoo.js +1 -0
  52. package/dist/assets/tag-chip-mCc23Rhb.js +1 -0
  53. package/dist/assets/trash-2-SAW1Z4Po.js +1 -0
  54. package/dist/assets/use-config-BucdaK23.js +1 -0
  55. package/dist/assets/use-confirm-dialog-C95F6sT1.js +1 -0
  56. package/dist/assets/use-viewport-layout-C6m3Nte7.js +1 -0
  57. package/dist/assets/x-DtCPHwCu.js +1 -0
  58. package/dist/assets/xlsx-B6zVt1RK.js +64 -0
  59. package/dist/index.html +34 -28
  60. package/package.json +14 -9
  61. package/src/app/components/layout/sidebar-items.tsx +3 -3
  62. package/src/app/components/layout/sidebar-rail.styles.ts +2 -2
  63. package/src/app/components/layout/sidebar.tsx +1 -1
  64. package/src/app/styles/design-system.css +17 -4
  65. package/src/features/chat/components/__tests__/chat-popover-content.test.tsx +41 -0
  66. package/src/features/chat/components/chat-popover-content.tsx +26 -0
  67. package/src/features/chat/components/conversation/__tests__/chat-conversation-content.test.tsx +13 -0
  68. package/src/features/chat/components/conversation/__tests__/chat-conversation-header-section.test.tsx +21 -11
  69. package/src/features/chat/components/conversation/__tests__/chat-conversation-header.test.tsx +2 -2
  70. package/src/features/chat/components/conversation/__tests__/chat-conversation-workspace-section.test.tsx +28 -1
  71. package/src/features/chat/components/conversation/chat-conversation-content.tsx +5 -4
  72. package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +9 -18
  73. package/src/features/chat/components/conversation/chat-conversation-track.tsx +35 -0
  74. package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +1 -0
  75. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +7 -7
  76. package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +4 -15
  77. package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +20 -1
  78. package/src/features/chat/features/conversation/components/session-conversation-input.tsx +69 -54
  79. package/src/features/chat/features/conversation/components/session-queued-input-rows.tsx +1 -1
  80. package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +62 -1
  81. package/src/features/chat/features/message/components/chat-message-list.container.tsx +63 -2
  82. package/src/features/chat/features/message/utils/__tests__/chat-message-file-operation.utils.test.ts +30 -0
  83. package/src/features/chat/features/message/utils/__tests__/chat-message-process-summary.utils.test.ts +11 -1
  84. package/src/features/chat/features/message/utils/__tests__/chat-message-texts.utils.test.ts +23 -0
  85. package/src/features/chat/features/message/utils/chat-message-process-summary.utils.ts +5 -0
  86. package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +138 -0
  87. package/src/features/chat/features/session/components/__tests__/chat-sidebar-session-item.test.tsx +37 -0
  88. package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +5 -4
  89. package/src/features/chat/features/session/components/chat-sidebar-session-item.tsx +3 -8
  90. package/src/features/chat/features/session/components/session-header/__tests__/chat-session-header-actions.test.tsx +65 -20
  91. package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +26 -28
  92. package/src/features/chat/features/session/components/session-header/chat-session-project-badge.tsx +3 -3
  93. package/src/features/chat/features/session/components/session-header/chat-session-title-switcher.tsx +5 -5
  94. package/src/features/chat/features/welcome/components/chat-welcome-project-picker.tsx +4 -4
  95. package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +4 -4
  96. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.test.tsx +463 -99
  97. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +113 -2
  98. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel.test.tsx +1 -0
  99. package/src/features/chat/features/workspace/components/chat-session-workspace-directory-browser.tsx +197 -44
  100. package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumb-browser.tsx +11 -5
  101. package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +8 -6
  102. package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +99 -67
  103. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +239 -1
  104. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +56 -6
  105. package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +29 -7
  106. package/src/features/chat/features/workspace/components/file-content-preview/use-workspace-file-buffer.ts +42 -0
  107. package/src/features/chat/features/workspace/components/file-content-preview/workspace-document-preview-state.tsx +18 -0
  108. package/src/features/chat/features/workspace/components/file-content-preview/workspace-docx-preview.css +89 -0
  109. package/src/features/chat/features/workspace/components/file-content-preview/workspace-docx-preview.tsx +87 -0
  110. package/src/features/chat/features/workspace/components/file-content-preview/workspace-presentation-preview.tsx +82 -0
  111. package/src/features/chat/features/workspace/components/file-content-preview/workspace-spreadsheet-preview.tsx +180 -0
  112. package/src/features/chat/features/workspace/components/workspace-file-content-preview.tsx +191 -0
  113. package/src/features/chat/features/workspace/hooks/use-chat-conversation-workspace-state.ts +1 -4
  114. package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +53 -10
  115. package/src/features/chat/features/workspace/utils/chat-thread-workspace-session.utils.ts +68 -2
  116. package/src/features/chat/features/workspace/utils/chat-workspace-file-tab-persistence.utils.ts +21 -0
  117. package/src/features/chat/features/workspace/utils/chat-workspace-file-tab.utils.ts +63 -0
  118. package/src/features/chat/features/workspace/utils/chat-workspace-file-viewer.utils.ts +49 -0
  119. package/src/features/chat/features/workspace/utils/chat-workspace-panel-layout.utils.ts +13 -0
  120. package/src/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils.ts +120 -38
  121. package/src/features/chat/index.ts +1 -0
  122. package/src/features/chat/managers/__tests__/chat-thread-workspace.manager.test.ts +76 -0
  123. package/src/features/chat/managers/__tests__/chat-thread.manager.test.ts +44 -60
  124. package/src/features/chat/managers/chat-thread.manager.ts +123 -124
  125. package/src/features/chat/pages/ncp-chat-page.tsx +1 -2
  126. package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +78 -1
  127. package/src/features/chat/stores/chat-message-layout.store.test.ts +37 -0
  128. package/src/features/chat/stores/chat-message-layout.store.ts +41 -0
  129. package/src/features/chat/stores/chat-thread.store.ts +73 -13
  130. package/src/features/cron/components/cron-config.tsx +63 -80
  131. package/src/features/marketplace/components/detail-doc/__tests__/marketplace-detail-doc.test.tsx +44 -6
  132. package/src/features/marketplace/components/marketplace-detail-doc.tsx +8 -4
  133. package/src/features/marketplace/components/marketplace-page-parts.tsx +1 -1
  134. package/src/features/marketplace/hooks/use-marketplace-detail-doc-entry.ts +84 -0
  135. package/src/features/panel-apps/components/panel-apps-list.tsx +2 -2
  136. package/src/features/right-panel-resources/components/right-panel-resource-home-page.tsx +1 -1
  137. package/src/features/settings/pages/__tests__/appearance-settings-page.test.tsx +25 -8
  138. package/src/features/settings/pages/appearance-settings-page.tsx +92 -13
  139. package/src/features/side-dock/components/side-dock.tsx +3 -3
  140. package/src/index.css +275 -15
  141. package/src/shared/components/__tests__/file-type-icon.test.tsx +61 -0
  142. package/src/shared/components/actions/action-link.tsx +1 -1
  143. package/src/shared/components/doc-browser/__tests__/doc-browser-context.test.tsx +19 -0
  144. package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +16 -0
  145. package/src/shared/components/doc-browser/doc-browser-context.tsx +1 -0
  146. package/src/shared/components/doc-browser/doc-browser-panel-parts.tsx +1 -1
  147. package/src/shared/components/doc-browser/doc-browser.tsx +11 -3
  148. package/src/shared/components/doc-browser/managers/doc-browser.manager.ts +5 -0
  149. package/src/shared/components/doc-browser/stores/doc-browser.store.ts +6 -1
  150. package/src/shared/components/doc-browser/types/doc-browser.types.ts +2 -0
  151. package/src/shared/components/doc-browser/utils/doc-browser-state.utils.ts +11 -0
  152. package/src/shared/components/file-type-icon.tsx +272 -0
  153. package/src/shared/components/resizable-right-panel/__tests__/resizable-right-panel.test.tsx +22 -0
  154. package/src/shared/components/resizable-right-panel/resizable-right-panel.tsx +17 -2
  155. package/src/shared/components/ui/actions/icon-action-button.tsx +1 -1
  156. package/src/shared/components/ui/button.tsx +1 -1
  157. package/src/shared/components/ui/dialog.tsx +1 -1
  158. package/src/shared/components/ui/input.tsx +1 -1
  159. package/src/shared/components/ui/select.tsx +1 -1
  160. package/src/shared/components/ui/switch.tsx +1 -1
  161. package/src/shared/components/ui/tab-strip/__tests__/compact-tab-strip.test.tsx +38 -0
  162. package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +82 -2
  163. package/src/shared/components/ui/tabs.tsx +1 -1
  164. package/src/shared/components/ui/textarea.tsx +1 -1
  165. package/src/shared/lib/api/__tests__/server-path.utils.test.ts +28 -0
  166. package/src/shared/lib/api/utils/server-path.utils.ts +19 -20
  167. package/src/shared/lib/i18n/locales/en-US/chat.json +99 -0
  168. package/src/shared/lib/i18n/locales/en-US/core.json +6 -0
  169. package/src/shared/lib/i18n/locales/zh-CN/chat.json +99 -0
  170. package/src/shared/lib/i18n/locales/zh-CN/core.json +6 -0
  171. package/dist/assets/api-B7Qigvtm.js +0 -13
  172. package/dist/assets/appearance-settings-page-CuE0Iiqj.js +0 -1
  173. package/dist/assets/channels-list-page-CTsM6TcP.js +0 -8
  174. package/dist/assets/chat-page-C_5dcuE3.js +0 -1
  175. package/dist/assets/config-split-page-Fbb4PtTf.js +0 -1
  176. package/dist/assets/confirm-dialog-D2EG3nqE.js +0 -5
  177. package/dist/assets/desktop-update-config-BGR3HUi1.js +0 -1
  178. package/dist/assets/dist-7JTjycxE.js +0 -1
  179. package/dist/assets/dist-wXLhk4hl.js +0 -1
  180. package/dist/assets/doc-browser-bHyXnxlj.js +0 -1
  181. package/dist/assets/doc-browser-context-CYAGm5d5.js +0 -1
  182. package/dist/assets/doc-browser-gTrQ3jCF.js +0 -1
  183. package/dist/assets/es2015-j1SRCIX5.js +0 -41
  184. package/dist/assets/i18n-provider-B4oMxOFx.js +0 -1
  185. package/dist/assets/index-CvrvblgX.css +0 -1
  186. package/dist/assets/index-Obd4JYU2.js +0 -104
  187. package/dist/assets/loader-circle-CdzgK4eH.js +0 -1
  188. package/dist/assets/mcp-marketplace-page-Bt7CuOoq.js +0 -9
  189. package/dist/assets/mcp-marketplace-page-Ck3t78_n.js +0 -1
  190. package/dist/assets/model-config-page-DeKk9gvE.js +0 -1
  191. package/dist/assets/plus-Bx7wQbhG.js +0 -1
  192. package/dist/assets/provider-scoped-model-input-DsH2LF1q.js +0 -1
  193. package/dist/assets/providers-config-page-BFnGp68F.js +0 -1
  194. package/dist/assets/react-UirzUuST.js +0 -8
  195. package/dist/assets/remote-CDkHZtA8.js +0 -1
  196. package/dist/assets/rotate-cw-1JqxHTuw.js +0 -1
  197. package/dist/assets/runtime-config-page-BelAqiNG.js +0 -1
  198. package/dist/assets/search-config-page-zPm6--Ig.js +0 -1
  199. package/dist/assets/secrets-config-page-Cxyp-KuQ.js +0 -3
  200. package/dist/assets/security-config-B_gCq9fn.js +0 -1
  201. package/dist/assets/select-CdSEOwVM.js +0 -1
  202. package/dist/assets/setting-row-CTAtGexr.js +0 -1
  203. package/dist/assets/side-dock-DPvakJ0a.js +0 -3
  204. package/dist/assets/switch-BU_UEULb.js +0 -1
  205. package/dist/assets/tag-chip-D-WsKoT1.js +0 -1
  206. package/dist/assets/tooltip-CjkOaHW7.js +0 -1
  207. package/dist/assets/use-config--hx5oxQn.js +0 -1
  208. package/dist/assets/use-confirm-dialog-CD9a_SK1.js +0 -1
  209. package/dist/assets/x-DT5x45JU.js +0 -1
  210. /package/dist/assets/{config-hints-C_iP1zl_.js → config-hints-fDrYfl0l.js} +0 -0
  211. /package/dist/assets/{host-capabilities-9bB_998Z.js → host-capabilities-zZvY9U63.js} +0 -0
  212. /package/dist/assets/{middleware-BILWbJE4.js → middleware-BLMHv9YF.js} +0 -0
@@ -32,6 +32,71 @@ export function buildChatMessageAdapterTexts(
32
32
  };
33
33
  }
34
34
 
35
+ function buildBuiltInToolStatusLabels() {
36
+ return {
37
+ directory: {
38
+ running: t("chatToolDirectoryRunning"),
39
+ success: t("chatToolDirectorySuccess"),
40
+ error: t("chatToolDirectoryError"),
41
+ cancelled: t("chatToolDirectoryCancelled"),
42
+ },
43
+ web: {
44
+ running: t("chatToolWebRunning"),
45
+ success: t("chatToolWebSuccess"),
46
+ error: t("chatToolWebError"),
47
+ cancelled: t("chatToolWebCancelled"),
48
+ },
49
+ message: {
50
+ running: t("chatToolMessageRunning"),
51
+ success: t("chatToolMessageSuccess"),
52
+ error: t("chatToolMessageError"),
53
+ cancelled: t("chatToolMessageCancelled"),
54
+ },
55
+ session: {
56
+ running: t("chatToolSessionRunning"),
57
+ success: t("chatToolSessionSuccess"),
58
+ error: t("chatToolSessionError"),
59
+ cancelled: t("chatToolSessionCancelled"),
60
+ },
61
+ agent: {
62
+ running: t("chatToolAgentRunning"),
63
+ success: t("chatToolAgentSuccess"),
64
+ error: t("chatToolAgentError"),
65
+ cancelled: t("chatToolAgentCancelled"),
66
+ },
67
+ memory: {
68
+ running: t("chatToolMemoryRunning"),
69
+ success: t("chatToolMemorySuccess"),
70
+ error: t("chatToolMemoryError"),
71
+ cancelled: t("chatToolMemoryCancelled"),
72
+ },
73
+ schedule: {
74
+ running: t("chatToolScheduleRunning"),
75
+ success: t("chatToolScheduleSuccess"),
76
+ error: t("chatToolScheduleError"),
77
+ cancelled: t("chatToolScheduleCancelled"),
78
+ },
79
+ system: {
80
+ running: t("chatToolSystemRunning"),
81
+ success: t("chatToolSystemSuccess"),
82
+ error: t("chatToolSystemError"),
83
+ cancelled: t("chatToolSystemCancelled"),
84
+ },
85
+ image: {
86
+ running: t("chatToolImageRunning"),
87
+ success: t("chatToolImageSuccess"),
88
+ error: t("chatToolImageError"),
89
+ cancelled: t("chatToolImageCancelled"),
90
+ },
91
+ display: {
92
+ running: t("chatToolDisplayRunning"),
93
+ success: t("chatToolDisplaySuccess"),
94
+ error: t("chatToolDisplayError"),
95
+ cancelled: t("chatToolDisplayCancelled"),
96
+ },
97
+ };
98
+ }
99
+
35
100
  export function buildChatMessageTexts(
36
101
  language: string,
37
102
  ): ChatMessageTexts {
@@ -42,8 +107,41 @@ export function buildChatMessageTexts(
42
107
  copyMessageLabel: t("chatMessageCopy"),
43
108
  copiedMessageLabel: t("chatMessageCopied"),
44
109
  typingLabel: t("chatTyping"),
110
+ reasoningCharacterCountTemplates: {
111
+ inProgress: t("chatReasoningInProgressCharacterCount"),
112
+ completed: t("chatReasoningCompletedCharacterCount"),
113
+ },
114
+ toolStatusLabels: {
115
+ terminal: {
116
+ running: t("chatToolTerminalRunning"),
117
+ success: t("chatToolTerminalSuccess"),
118
+ error: t("chatToolTerminalError"),
119
+ cancelled: t("chatToolTerminalCancelled"),
120
+ },
121
+ fileRead: {
122
+ running: t("chatToolFileReadRunning"),
123
+ success: t("chatToolFileReadSuccess"),
124
+ error: t("chatToolFileReadError"),
125
+ cancelled: t("chatToolFileReadCancelled"),
126
+ },
127
+ fileEdit: {
128
+ running: t("chatToolFileEditRunning"),
129
+ success: t("chatToolFileEditSuccess"),
130
+ error: t("chatToolFileEditError"),
131
+ cancelled: t("chatToolFileEditCancelled"),
132
+ },
133
+ search: {
134
+ running: t("chatToolSearchRunning"),
135
+ success: t("chatToolSearchSuccess"),
136
+ error: t("chatToolSearchError"),
137
+ cancelled: t("chatToolSearchCancelled"),
138
+ },
139
+ builtIn: buildBuiltInToolStatusLabels(),
140
+ },
45
141
  attachmentOpenLabel: t("chatAttachmentOpen"),
46
142
  attachmentAttachedLabel: t("chatAttachmentAttached"),
143
+ attachmentExpandLabel: t("chatAttachmentExpand"),
144
+ attachmentCloseLabel: t("chatAttachmentClosePreview"),
47
145
  attachmentCategoryLabels: {
48
146
  archive: t("chatAttachmentCategoryArchive"),
49
147
  audio: t("chatAttachmentCategoryAudio"),
@@ -56,5 +154,45 @@ export function buildChatMessageTexts(
56
154
  sheet: t("chatAttachmentCategorySheet"),
57
155
  video: t("chatAttachmentCategoryVideo"),
58
156
  },
157
+ toolActivitySegmentTemplates: {
158
+ read: {
159
+ one: t("chatToolActivityReadOne"),
160
+ other: t("chatToolActivityReadOther"),
161
+ },
162
+ edit: {
163
+ one: t("chatToolActivityEditOne"),
164
+ other: t("chatToolActivityEditOther"),
165
+ },
166
+ directory: {
167
+ one: t("chatToolActivityDirectoryOne"),
168
+ other: t("chatToolActivityDirectoryOther"),
169
+ },
170
+ search: {
171
+ one: t("chatToolActivitySearchOne"),
172
+ other: t("chatToolActivitySearchOther"),
173
+ },
174
+ bash: {
175
+ one: t("chatToolActivityBashOne"),
176
+ other: t("chatToolActivityBashOther"),
177
+ },
178
+ web: {
179
+ one: t("chatToolActivityWebOne"),
180
+ other: t("chatToolActivityWebOther"),
181
+ },
182
+ agent: {
183
+ one: t("chatToolActivityAgentOne"),
184
+ other: t("chatToolActivityAgentOther"),
185
+ },
186
+ panel: {
187
+ one: t("chatToolActivityPanelOne"),
188
+ other: t("chatToolActivityPanelOther"),
189
+ },
190
+ other: {
191
+ one: t("chatToolActivityOtherOne"),
192
+ other: t("chatToolActivityOtherOther"),
193
+ },
194
+ },
195
+ toolActivityFailedLabel: t("chatProcessSummaryFailed"),
196
+ toolActivityCancelledLabel: t("chatProcessSummaryCancelled"),
59
197
  };
60
198
  }
@@ -0,0 +1,37 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { expect, it, vi } from 'vitest';
3
+ import { ChatSidebarSessionItem } from '@/features/chat/features/session/components/chat-sidebar-session-item';
4
+
5
+ it('shows session actions only on hover or when an action owns focus', () => {
6
+ render(
7
+ <ChatSidebarSessionItem
8
+ sessionKey="session:current"
9
+ active
10
+ showUnreadDot={false}
11
+ context={{ icon: null, label: null }}
12
+ isPinned={false}
13
+ title="Current Task"
14
+ previewText="Preview"
15
+ trailingText="Now"
16
+ isEditing={false}
17
+ draftLabel="Current Task"
18
+ isSaving={false}
19
+ onSelect={vi.fn()}
20
+ onStartEditing={vi.fn()}
21
+ onDraftLabelChange={vi.fn()}
22
+ onSave={vi.fn()}
23
+ onCancel={vi.fn()}
24
+ onTogglePinned={vi.fn()}
25
+ />,
26
+ );
27
+
28
+ screen.getByText('Current Task').closest('button')?.focus();
29
+ const actions = screen.getByLabelText('Pin session').parentElement;
30
+
31
+ expect(actions?.className).toContain('opacity-0');
32
+ expect(actions?.className).toContain('group-hover/session:opacity-100');
33
+ expect(actions?.className).toContain('focus-within:opacity-100');
34
+ expect(actions?.className).not.toContain(
35
+ 'group-focus-within/session:opacity-100',
36
+ );
37
+ });
@@ -2,7 +2,8 @@ import { useMemo, useState, type ReactNode } from 'react';
2
2
  import { ChevronDown, ChevronRight, Folder, Pin, Plus } from 'lucide-react';
3
3
  import { usePresenter } from '@/features/chat/components/providers/chat-presenter.provider';
4
4
  import { ChatSessionTypeMenu } from "@/features/chat/features/session-type/components/chat-session-type-menu";
5
- import { Popover, PopoverContent, PopoverTrigger } from '@/shared/components/ui/popover';
5
+ import { Popover, PopoverTrigger } from '@/shared/components/ui/popover';
6
+ import { ChatPopoverContent } from '@/features/chat/components/chat-popover-content';
6
7
  import { IconActionButton } from '@/shared/components/ui/actions/icon-action-button';
7
8
  import type { ChatSessionTypeOption } from "@/features/chat/features/session-type/utils/chat-session-type.utils";
8
9
  import type { NcpSessionListItemView } from '@/features/chat/features/ncp/hooks/use-ncp-session-list-view';
@@ -64,7 +65,7 @@ export function ChatSidebarProjectGroups(props: ChatSidebarProjectGroupsProps) {
64
65
  ? 'chatSidebarExpandProject'
65
66
  : 'chatSidebarCollapseProject',
66
67
  )}
67
- className="flex h-full w-full min-w-0 items-center gap-1.5 pr-14 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
68
+ className="flex h-full w-full min-w-0 items-center gap-1.5 pr-14 text-left focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border"
68
69
  onClick={() =>
69
70
  presenter.chatSessionListManager.toggleProjectCollapsed(
70
71
  group.projectRoot,
@@ -107,7 +108,7 @@ export function ChatSidebarProjectGroups(props: ChatSidebarProjectGroupsProps) {
107
108
  label={actionLabel}
108
109
  />
109
110
  </PopoverTrigger>
110
- <PopoverContent
111
+ <ChatPopoverContent
111
112
  align="end"
112
113
  className="w-56 rounded-2xl border border-border bg-popover p-1.5 text-popover-foreground shadow-[0_24px_60px_-28px_rgba(15,23,42,0.38)]"
113
114
  >
@@ -122,7 +123,7 @@ export function ChatSidebarProjectGroups(props: ChatSidebarProjectGroupsProps) {
122
123
  setOpenProjectRoot(null);
123
124
  }}
124
125
  />
125
- </PopoverContent>
126
+ </ChatPopoverContent>
126
127
  </Popover>
127
128
  ) : (
128
129
  <IconActionButton
@@ -169,12 +169,7 @@ function ChatSidebarSessionDisplayView({
169
169
  event.stopPropagation();
170
170
  onOpenChildSessions();
171
171
  }}
172
- className={cn(
173
- 'absolute right-12 top-0 inline-flex h-6 items-center gap-1 rounded-md px-1.5 text-[10px] font-medium text-muted-foreground transition-colors hover:bg-black/10 hover:text-foreground',
174
- active
175
- ? 'opacity-100'
176
- : 'opacity-0 group-hover/session:opacity-100 group-focus-within/session:opacity-100'
177
- )}
172
+ className="pointer-events-none absolute right-12 top-0 inline-flex h-6 items-center gap-1 rounded-md px-1.5 text-[10px] font-medium text-muted-foreground opacity-0 transition-colors hover:bg-black/10 hover:text-foreground group-hover/session:pointer-events-auto group-hover/session:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100"
178
173
  aria-label={t('chatSessionOpenChildSessions')}
179
174
  title={t('chatSessionOpenChildSessions')}
180
175
  >
@@ -183,11 +178,11 @@ function ChatSidebarSessionDisplayView({
183
178
  </button>
184
179
  ) : null}
185
180
  {runStatus ? (
186
- <span className="absolute right-0 top-0 inline-flex h-6 w-6 items-center justify-center transition-opacity group-hover/session:opacity-0 group-focus-within/session:opacity-0">
181
+ <span className="absolute right-0 top-0 inline-flex h-6 w-6 items-center justify-center transition-opacity group-hover/session:opacity-0">
187
182
  <SessionRunBadge status={runStatus} />
188
183
  </span>
189
184
  ) : null}
190
- <div className="absolute right-0 top-0 flex h-6 items-center gap-0.5 opacity-0 transition-opacity group-hover/session:opacity-100 group-focus-within/session:opacity-100">
185
+ <div className="pointer-events-none absolute right-0 top-0 flex h-6 items-center gap-0.5 opacity-0 transition-opacity group-hover/session:pointer-events-auto group-hover/session:opacity-100 focus-within:pointer-events-auto focus-within:opacity-100">
191
186
  <IconActionButton
192
187
  size="sm"
193
188
  tone="strong"
@@ -6,8 +6,7 @@ import { ChatSessionHeaderActions } from '@/features/chat/features/session/compo
6
6
  const mocks = vi.hoisted(() => ({
7
7
  updateSessionProject: vi.fn(),
8
8
  onDeleteSession: vi.fn(),
9
- onOpenChildSessions: vi.fn(),
10
- onOpenSessionCronJobs: vi.fn(),
9
+ onToggleWorkspace: vi.fn(),
11
10
  }));
12
11
 
13
12
  vi.mock('@/features/chat/features/session/hooks/use-chat-session-project', () => ({
@@ -22,8 +21,7 @@ describe('ChatSessionHeaderActions', () => {
22
21
  beforeEach(() => {
23
22
  mocks.updateSessionProject.mockReset();
24
23
  mocks.onDeleteSession.mockReset();
25
- mocks.onOpenChildSessions.mockReset();
26
- mocks.onOpenSessionCronJobs.mockReset();
24
+ mocks.onToggleWorkspace.mockReset();
27
25
  });
28
26
 
29
27
  it('keeps only the set-project action in the more-actions menu when a project is already attached', async () => {
@@ -35,8 +33,8 @@ describe('ChatSessionHeaderActions', () => {
35
33
  canDeleteSession
36
34
  isDeletePending={false}
37
35
  projectRoot="/tmp/project-alpha"
38
- childSessionCount={0}
39
- onOpenChildSessions={mocks.onOpenChildSessions}
36
+ isWorkspaceOpen={false}
37
+ onToggleWorkspace={mocks.onToggleWorkspace}
40
38
  onDeleteSession={mocks.onDeleteSession}
41
39
  />
42
40
  );
@@ -58,8 +56,8 @@ describe('ChatSessionHeaderActions', () => {
58
56
  canDeleteSession={false}
59
57
  isDeletePending={false}
60
58
  projectRoot={null}
61
- childSessionCount={0}
62
- onOpenChildSessions={mocks.onOpenChildSessions}
59
+ isWorkspaceOpen={false}
60
+ onToggleWorkspace={mocks.onToggleWorkspace}
63
61
  onDeleteSession={mocks.onDeleteSession}
64
62
  />
65
63
  );
@@ -84,6 +82,8 @@ describe('ChatSessionHeaderActions', () => {
84
82
  codex_thread_id: 'thread-123',
85
83
  runtime: 'codex',
86
84
  }}
85
+ isWorkspaceOpen={false}
86
+ onToggleWorkspace={mocks.onToggleWorkspace}
87
87
  onDeleteSession={mocks.onDeleteSession}
88
88
  />
89
89
  );
@@ -98,7 +98,7 @@ describe('ChatSessionHeaderActions', () => {
98
98
  expect(screen.getByText(/thread-123/)).toBeTruthy();
99
99
  });
100
100
 
101
- it('shows a dedicated child-session entry button when the current session has child sessions', async () => {
101
+ it('opens the session workspace from one stable header action', async () => {
102
102
  const user = userEvent.setup();
103
103
 
104
104
  render(
@@ -107,28 +107,28 @@ describe('ChatSessionHeaderActions', () => {
107
107
  canDeleteSession
108
108
  isDeletePending={false}
109
109
  projectRoot={null}
110
- childSessionCount={2}
111
- onOpenChildSessions={mocks.onOpenChildSessions}
110
+ isWorkspaceOpen={false}
111
+ onToggleWorkspace={mocks.onToggleWorkspace}
112
112
  onDeleteSession={mocks.onDeleteSession}
113
113
  />
114
114
  );
115
115
 
116
- await user.click(screen.getByRole('button', { name: 'View child sessions' }));
116
+ await user.click(screen.getByRole('button', { name: 'Open session workspace' }));
117
117
 
118
- expect(mocks.onOpenChildSessions).toHaveBeenCalledTimes(1);
118
+ expect(mocks.onToggleWorkspace).toHaveBeenCalledTimes(1);
119
+ expect(screen.queryByRole('button', { name: 'View child sessions' })).toBeNull();
120
+ expect(screen.queryByRole('button', { name: 'View session cron jobs' })).toBeNull();
119
121
  });
120
122
 
121
- it('uses a shared spaced action group for child, cron, and menu buttons', () => {
123
+ it('uses the shared compact action density for workspace and menu buttons', () => {
122
124
  render(
123
125
  <ChatSessionHeaderActions
124
126
  sessionKey="session-actions"
125
127
  canDeleteSession
126
128
  isDeletePending={false}
127
129
  projectRoot={null}
128
- childSessionCount={1}
129
- sessionCronJobCount={1}
130
- onOpenChildSessions={mocks.onOpenChildSessions}
131
- onOpenSessionCronJobs={mocks.onOpenSessionCronJobs}
130
+ isWorkspaceOpen={false}
131
+ onToggleWorkspace={mocks.onToggleWorkspace}
132
132
  onDeleteSession={mocks.onDeleteSession}
133
133
  />
134
134
  );
@@ -136,7 +136,52 @@ describe('ChatSessionHeaderActions', () => {
136
136
  const actionGroup = screen.getByRole('button', { name: 'More actions' }).parentElement;
137
137
 
138
138
  expect(actionGroup?.className).toContain('gap-1.5');
139
- expect(screen.getByRole('button', { name: 'View child sessions' }).className).toContain('h-7');
140
- expect(screen.getByRole('button', { name: 'View session cron jobs' }).className).toContain('w-7');
139
+ expect(screen.getByRole('button', { name: 'Open session workspace' }).className).toContain('h-7');
140
+ expect(screen.getByRole('button', { name: 'Open session workspace' }).className).toContain('w-7');
141
+ });
142
+
143
+ it('places the workspace toggle at the far right of the visible header actions', () => {
144
+ render(
145
+ <ChatSessionHeaderActions
146
+ sessionKey="session-actions"
147
+ canDeleteSession
148
+ isDeletePending={false}
149
+ projectRoot={null}
150
+ isWorkspaceOpen={false}
151
+ onToggleWorkspace={mocks.onToggleWorkspace}
152
+ onDeleteSession={mocks.onDeleteSession}
153
+ />
154
+ );
155
+
156
+ const menuButton = screen.getByRole('button', { name: 'More actions' });
157
+ const workspaceButton = screen.getByRole('button', { name: 'Open session workspace' });
158
+
159
+ expect(menuButton.compareDocumentPosition(workspaceButton)).toBe(
160
+ Node.DOCUMENT_POSITION_FOLLOWING,
161
+ );
162
+ });
163
+
164
+ it('changes to a pressed close action while the workspace is open', async () => {
165
+ const user = userEvent.setup();
166
+
167
+ render(
168
+ <ChatSessionHeaderActions
169
+ sessionKey="session-actions"
170
+ canDeleteSession
171
+ isDeletePending={false}
172
+ projectRoot={null}
173
+ isWorkspaceOpen
174
+ onToggleWorkspace={mocks.onToggleWorkspace}
175
+ onDeleteSession={mocks.onDeleteSession}
176
+ />
177
+ );
178
+
179
+ const closeButton = screen.getByRole('button', {
180
+ name: 'Close session workspace',
181
+ });
182
+
183
+ expect(closeButton.getAttribute('aria-pressed')).toBe('true');
184
+ await user.click(closeButton);
185
+ expect(mocks.onToggleWorkspace).toHaveBeenCalledTimes(1);
141
186
  });
142
187
  });
@@ -1,7 +1,8 @@
1
1
  import { useState } from 'react';
2
- import { AlarmClock, Braces, FolderOpen, GitBranch, MoreVertical, Trash2 } from 'lucide-react';
2
+ import { Braces, FolderOpen, MoreVertical, PanelRightClose, PanelRightOpen, Trash2 } from 'lucide-react';
3
3
  import { IconActionButton } from '@/shared/components/ui/actions/icon-action-button';
4
- import { Popover, PopoverContent, PopoverTrigger } from '@/shared/components/ui/popover';
4
+ import { Popover, PopoverTrigger } from '@/shared/components/ui/popover';
5
+ import { ChatPopoverContent } from '@/features/chat/components/chat-popover-content';
5
6
  import { useChatSessionProject } from '@/features/chat/features/session/hooks/use-chat-session-project';
6
7
  import { ChatSessionHeaderMenuItem } from './chat-session-header-menu-item';
7
8
  import { ChatSessionMetadataDialog } from './chat-session-metadata-dialog';
@@ -16,10 +17,8 @@ type ChatSessionHeaderActionsProps = {
16
17
  isDeletePending: boolean;
17
18
  projectRoot?: string | null;
18
19
  metadata?: Record<string, unknown> | null;
19
- childSessionCount?: number;
20
- sessionCronJobCount?: number;
21
- onOpenChildSessions?: () => void;
22
- onOpenSessionCronJobs?: () => void;
20
+ isWorkspaceOpen: boolean;
21
+ onToggleWorkspace: () => void;
23
22
  onDeleteSession: () => void;
24
23
  };
25
24
 
@@ -29,10 +28,8 @@ export function ChatSessionHeaderActions({
29
28
  isDeletePending,
30
29
  projectRoot,
31
30
  metadata,
32
- childSessionCount = 0,
33
- sessionCronJobCount = 0,
34
- onOpenChildSessions,
35
- onOpenSessionCronJobs,
31
+ isWorkspaceOpen,
32
+ onToggleWorkspace,
36
33
  onDeleteSession,
37
34
  }: ChatSessionHeaderActionsProps) {
38
35
  const updateSessionProject = useChatSessionProject();
@@ -60,22 +57,6 @@ export function ChatSessionHeaderActions({
60
57
 
61
58
  return (
62
59
  <div className={SESSION_HEADER_ACTION_GROUP_CLASS}>
63
- {childSessionCount > 0 && onOpenChildSessions ? (
64
- <IconActionButton
65
- icon={<GitBranch className="h-4 w-4" />}
66
- label={t('chatSessionOpenChildSessions')}
67
- onClick={onOpenChildSessions}
68
- disabled={isBusy}
69
- />
70
- ) : null}
71
- {sessionCronJobCount > 0 && onOpenSessionCronJobs ? (
72
- <IconActionButton
73
- icon={<AlarmClock className="h-4 w-4" />}
74
- label={t('chatSessionOpenCronJobs')}
75
- onClick={onOpenSessionCronJobs}
76
- disabled={isBusy}
77
- />
78
- ) : null}
79
60
  <Popover open={isMenuOpen} onOpenChange={setIsMenuOpen}>
80
61
  <PopoverTrigger asChild>
81
62
  <IconActionButton
@@ -85,7 +66,7 @@ export function ChatSessionHeaderActions({
85
66
  disabled={isBusy}
86
67
  />
87
68
  </PopoverTrigger>
88
- <PopoverContent align="end" className="w-56 p-2">
69
+ <ChatPopoverContent align="end" className="w-56 p-2">
89
70
  <div className="space-y-1">
90
71
  <ChatSessionHeaderMenuItem
91
72
  icon={FolderOpen}
@@ -116,8 +97,25 @@ export function ChatSessionHeaderActions({
116
97
  destructive
117
98
  />
118
99
  </div>
119
- </PopoverContent>
100
+ </ChatPopoverContent>
120
101
  </Popover>
102
+ <IconActionButton
103
+ icon={
104
+ isWorkspaceOpen ? (
105
+ <PanelRightClose className="h-4 w-4" />
106
+ ) : (
107
+ <PanelRightOpen className="h-4 w-4" />
108
+ )
109
+ }
110
+ label={t(
111
+ isWorkspaceOpen
112
+ ? 'chatSessionCloseWorkspace'
113
+ : 'chatSessionOpenWorkspace',
114
+ )}
115
+ aria-pressed={isWorkspaceOpen}
116
+ onClick={onToggleWorkspace}
117
+ disabled={isBusy}
118
+ />
121
119
 
122
120
  <ChatSessionProjectDialog
123
121
  open={isDialogOpen}
@@ -5,10 +5,10 @@ import { ChatSessionHeaderMenuItem } from './chat-session-header-menu-item';
5
5
  import { ChatSessionProjectDialog } from './chat-session-project-dialog';
6
6
  import {
7
7
  Popover,
8
- PopoverContent,
9
8
  PopoverTrigger,
10
9
  createPopoverAvailableHeightLimit,
11
10
  } from '@/shared/components/ui/popover';
11
+ import { ChatPopoverContent } from '@/features/chat/components/chat-popover-content';
12
12
  import { t } from '@/shared/lib/i18n';
13
13
 
14
14
  type ChatSessionProjectBadgeProps = {
@@ -66,7 +66,7 @@ export function ChatSessionProjectBadge({
66
66
  </span>
67
67
  </button>
68
68
  </PopoverTrigger>
69
- <PopoverContent
69
+ <ChatPopoverContent
70
70
  align="start"
71
71
  className="w-72 p-2"
72
72
  style={SESSION_PROJECT_MENU_STYLE}
@@ -100,7 +100,7 @@ export function ChatSessionProjectBadge({
100
100
  disabled={isProjectPending}
101
101
  />
102
102
  </div>
103
- </PopoverContent>
103
+ </ChatPopoverContent>
104
104
  </Popover>
105
105
 
106
106
  <ChatSessionProjectDialog
@@ -32,15 +32,15 @@ import { useChatQueryStore } from "@/features/chat/stores/ncp-chat-query.store";
32
32
  import { useViewportLayoutStore } from "@/app/stores/viewport-layout.store";
33
33
  import {
34
34
  Popover,
35
- PopoverContent,
36
35
  PopoverTrigger,
37
36
  } from "@/shared/components/ui/popover";
37
+ import { ChatPopoverContent } from "@/features/chat/components/chat-popover-content";
38
38
  import { Input } from "@/shared/components/ui/input";
39
39
  import { t } from "@/shared/lib/i18n";
40
40
  import { cn } from "@/shared/lib/utils";
41
41
 
42
42
  const SWITCHER_TRIGGER_CLASS =
43
- "group inline-flex min-w-0 max-w-full items-center gap-1.5 rounded-md px-1.5 py-1 text-sm font-medium text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40";
43
+ "group inline-flex min-w-0 max-w-full items-center gap-1.5 rounded-md px-1.5 py-1 text-sm font-medium text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border";
44
44
 
45
45
  function ChatSessionTitle({ title }: { title: string }) {
46
46
  return (
@@ -111,7 +111,7 @@ function ChatSessionSwitchItem({
111
111
  type="button"
112
112
  aria-current={active ? "page" : undefined}
113
113
  className={cn(
114
- "flex w-full min-w-0 items-start gap-2 rounded-lg px-2.5 py-2 text-left transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40",
114
+ "flex w-full min-w-0 items-start gap-2 rounded-lg px-2.5 py-2 text-left transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border",
115
115
  active
116
116
  ? "bg-accent text-accent-foreground"
117
117
  : "text-popover-foreground hover:bg-accent/70",
@@ -217,7 +217,7 @@ function ChatSessionTitleSwitcherPopover({
217
217
  />
218
218
  </button>
219
219
  </PopoverTrigger>
220
- <PopoverContent
220
+ <ChatPopoverContent
221
221
  align="start"
222
222
  className="w-[22rem] max-w-[calc(100vw-2rem)] p-0"
223
223
  >
@@ -263,7 +263,7 @@ function ChatSessionTitleSwitcherPopover({
263
263
  />
264
264
  )}
265
265
  </div>
266
- </PopoverContent>
266
+ </ChatPopoverContent>
267
267
  </Popover>
268
268
  );
269
269
  }
@@ -3,10 +3,10 @@ import { ChevronDown, FolderOpen } from 'lucide-react';
3
3
  import type { ChatWelcomeProjectOption } from '@/features/chat/features/welcome/utils/chat-welcome-project-options.utils';
4
4
  import {
5
5
  Popover,
6
- PopoverContent,
7
6
  PopoverTrigger,
8
7
  createPopoverAvailableHeightLimit,
9
8
  } from '@/shared/components/ui/popover';
9
+ import { ChatPopoverContent } from '@/features/chat/components/chat-popover-content';
10
10
  import { t } from '@/shared/lib/i18n';
11
11
  import { getSessionProjectName } from '@/shared/lib/session-project';
12
12
 
@@ -49,7 +49,7 @@ export function ChatWelcomeProjectPicker({
49
49
  <PopoverTrigger asChild>
50
50
  <button
51
51
  type="button"
52
- className="inline-flex min-w-0 max-w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/25"
52
+ className="inline-flex min-w-0 max-w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border"
53
53
  title={projectRoot ?? undefined}
54
54
  aria-label={t('chatWelcomeProjectPickerLabel')}
55
55
  disabled={!selectable || isSaving}
@@ -64,7 +64,7 @@ export function ChatWelcomeProjectPicker({
64
64
  <ChevronDown className="h-3.5 w-3.5 shrink-0 text-muted-foreground/70" />
65
65
  </button>
66
66
  </PopoverTrigger>
67
- <PopoverContent
67
+ <ChatPopoverContent
68
68
  align="start"
69
69
  className="flex w-[min(20rem,calc(100vw-1rem))] flex-col overflow-hidden rounded-2xl border border-border bg-popover p-0 text-popover-foreground shadow-[0_24px_60px_-28px_rgba(15,23,42,0.38)]"
70
70
  style={{ maxHeight: PROJECT_PICKER_MAX_HEIGHT }}
@@ -121,7 +121,7 @@ export function ChatWelcomeProjectPicker({
121
121
  <span>{t('chatWelcomeProjectOpenFolder')}</span>
122
122
  </button>
123
123
  </div>
124
- </PopoverContent>
124
+ </ChatPopoverContent>
125
125
  </Popover>
126
126
  );
127
127
  }
@@ -5,10 +5,10 @@ import { ChatSessionTypeOptionItem } from '@/features/chat/features/session-type
5
5
  import type { ChatSessionTypeOption } from '@/features/chat/features/session-type/utils/chat-session-type.utils';
6
6
  import {
7
7
  Popover,
8
- PopoverContent,
9
8
  PopoverTrigger,
10
9
  createPopoverAvailableHeightLimit,
11
10
  } from '@/shared/components/ui/popover';
11
+ import { ChatPopoverContent } from '@/features/chat/components/chat-popover-content';
12
12
  import { t } from '@/shared/lib/i18n';
13
13
 
14
14
  type SessionTypeOption = ChatSessionTypeOption;
@@ -39,7 +39,7 @@ export function ChatWelcomeSessionTypePicker({
39
39
  <PopoverTrigger asChild>
40
40
  <button
41
41
  type="button"
42
- className="inline-flex min-w-0 max-w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/25"
42
+ className="inline-flex min-w-0 max-w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border"
43
43
  aria-label={t('chatWelcomeSessionTypePickerLabel')}
44
44
  >
45
45
  {selectedOption.icon?.src ? (
@@ -59,7 +59,7 @@ export function ChatWelcomeSessionTypePicker({
59
59
  <ChevronDown className="h-3.5 w-3.5 shrink-0 text-muted-foreground/70" />
60
60
  </button>
61
61
  </PopoverTrigger>
62
- <PopoverContent
62
+ <ChatPopoverContent
63
63
  align="start"
64
64
  className="flex w-[min(16rem,calc(100vw-1rem))] flex-col overflow-hidden rounded-2xl border border-border bg-popover p-1.5 text-popover-foreground shadow-[0_24px_60px_-28px_rgba(15,23,42,0.38)]"
65
65
  style={{ maxHeight: SESSION_TYPE_PICKER_MAX_HEIGHT }}
@@ -76,7 +76,7 @@ export function ChatWelcomeSessionTypePicker({
76
76
  />
77
77
  ))}
78
78
  </div>
79
- </PopoverContent>
79
+ </ChatPopoverContent>
80
80
  </Popover>
81
81
  );
82
82
  }