@nextclaw/ui 0.14.1 → 0.14.3

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 (224) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/assets/{api-DPcvCLfa.js → api-BP_8IaxB.js} +7 -7
  3. package/dist/assets/channels-list-page-DEh5Jjqx.js +8 -0
  4. package/dist/assets/chat-page-BRB0N5WW.js +105 -0
  5. package/dist/assets/config-split-page-CRhlZ_pH.js +1 -0
  6. package/dist/assets/{confirm-dialog-CWh5FfK2.js → confirm-dialog-DsivFJ4r.js} +2 -2
  7. package/dist/assets/{desktop-update-config-DsRhBizi.js → desktop-update-config-B0w9p2ep.js} +1 -1
  8. package/dist/assets/{dist-DPrgcEC0.js → dist-CikkhOlq.js} +1 -1
  9. package/dist/assets/{dist-DsE4OsSS.js → dist-PVA_xL1D.js} +1 -1
  10. package/dist/assets/doc-browser-BoNJ7-tE.js +1 -0
  11. package/dist/assets/doc-browser-CdJ_d4ik.js +1 -0
  12. package/dist/assets/doc-browser-context-MTw4EvKd.js +1 -0
  13. package/dist/assets/{ellipsis-B81FStLm.js → ellipsis-y6vDtq4M.js} +1 -1
  14. package/dist/assets/{external-link-C_dmG-WJ.js → external-link-DVJIQf_G.js} +1 -1
  15. package/dist/assets/index-BiE-K8-q.css +1 -0
  16. package/dist/assets/index-D9BAE_L_.js +105 -0
  17. package/dist/assets/mcp-marketplace-page-B1SZNY5m.js +40 -0
  18. package/dist/assets/mcp-marketplace-page-Cq_Tw42T.js +1 -0
  19. package/dist/assets/middleware-CkFT3R4v.js +1 -0
  20. package/dist/assets/model-config-page-DotaTUHb.js +1 -0
  21. package/dist/assets/plus-BbZqquJe.js +1 -0
  22. package/dist/assets/provider-scoped-model-input-DsFRuWJH.js +1 -0
  23. package/dist/assets/providers-config-page-DW4tQSLN.js +1 -0
  24. package/dist/assets/{react-sZz5HSCm.js → react-VNqT5Zp7.js} +1 -1
  25. package/dist/assets/remote-B8TiUfwW.js +1 -0
  26. package/dist/assets/rotate-cw-DjHDTkCv.js +1 -0
  27. package/dist/assets/runtime-config-page-S6ErRHR8.js +1 -0
  28. package/dist/assets/{save-MzjoiHri.js → save-BOJ477H-.js} +1 -1
  29. package/dist/assets/{search-B29dE4GN.js → search-BEti5beA.js} +1 -1
  30. package/dist/assets/{search-config-page-Dl5sZzob.js → search-config-page-DGj5am03.js} +1 -1
  31. package/dist/assets/{secrets-config-page-C_l-IFCK.js → secrets-config-page--IzrIOid.js} +2 -2
  32. package/dist/assets/{select-BKmh05hd.js → select-hoj8dK4K.js} +2 -2
  33. package/dist/assets/{tag-chip-BS_7Ueom.js → tag-chip-T8-h-die.js} +1 -1
  34. package/dist/assets/use-config-CjRV2hwL.js +1 -0
  35. package/dist/assets/x-D9PXs_xP.js +1 -0
  36. package/dist/index.html +70 -19
  37. package/index.html +55 -5
  38. package/package.json +9 -9
  39. package/src/app/components/app-presenter-provider.tsx +11 -2
  40. package/src/app/components/layout/__tests__/app-layout.test.tsx +11 -2
  41. package/src/app/components/layout/__tests__/sidebar.layout.test.tsx +110 -79
  42. package/src/app/components/layout/app-layout.tsx +18 -4
  43. package/src/app/components/layout/header.tsx +3 -3
  44. package/src/app/components/layout/page-layout.tsx +2 -2
  45. package/src/app/components/layout/runtime-status-entry.tsx +7 -7
  46. package/src/app/components/layout/sidebar-items.tsx +194 -71
  47. package/src/app/components/layout/sidebar-rail.styles.ts +15 -0
  48. package/src/app/components/layout/sidebar.tsx +340 -83
  49. package/src/app/managers/viewport-layout.manager.ts +10 -0
  50. package/src/app/stores/viewport-layout.store.ts +39 -3
  51. package/src/app/styles/design-system.css +388 -26
  52. package/src/app/test/vitest-setup.ts +31 -0
  53. package/src/features/agents/components/__tests__/agents-page.test.tsx +62 -39
  54. package/src/features/agents/components/agents-page.tsx +10 -6
  55. package/src/features/chat/components/chat-sidebar-list-mode-switch.tsx +3 -3
  56. package/src/features/chat/components/conversation/__tests__/chat-conversation-header-section.test.tsx +145 -0
  57. package/src/features/chat/components/conversation/__tests__/chat-conversation-header.test.tsx +4 -2
  58. package/src/features/chat/components/conversation/__tests__/chat-conversation-panel.test.tsx +69 -762
  59. package/src/features/chat/components/conversation/__tests__/chat-conversation-workspace-section.test.tsx +132 -0
  60. package/src/features/chat/components/conversation/chat-conversation-content.tsx +22 -15
  61. package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +15 -16
  62. package/src/features/chat/components/conversation/chat-conversation-header.tsx +7 -6
  63. package/src/features/chat/components/conversation/chat-conversation-panel.tsx +19 -19
  64. package/src/features/chat/components/conversation/chat-conversation-skeleton.tsx +13 -13
  65. package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +10 -4
  66. package/src/features/chat/components/layout/__tests__/chat-sidebar-read-state.test.tsx +52 -11
  67. package/src/features/chat/components/layout/__tests__/chat-sidebar.test.tsx +18 -16
  68. package/src/features/chat/components/layout/chat-page-shell.tsx +1 -1
  69. package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +247 -0
  70. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +93 -20
  71. package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +93 -36
  72. package/src/features/chat/components/layout/chat-sidebar.tsx +60 -93
  73. package/src/features/chat/components/providers/chat-presenter.provider.tsx +0 -6
  74. package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +225 -0
  75. package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +199 -0
  76. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +308 -0
  77. package/src/features/chat/features/conversation/components/session-conversation-input.tsx +439 -0
  78. package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +194 -0
  79. package/src/features/chat/features/conversation/hooks/use-session-conversation-input-attachments.ts +66 -0
  80. package/src/features/chat/features/{input/hooks/use-chat-input-bar-query-state.ts → conversation/hooks/use-session-conversation-input-query.ts} +51 -20
  81. package/src/features/chat/features/conversation/hooks/use-session-conversation-input-state.ts +281 -0
  82. package/src/features/chat/features/conversation/utils/session-conversation-input-toolbar.utils.ts +158 -0
  83. package/src/features/chat/features/input/hooks/__tests__/use-chat-input-surface-state.test.tsx +56 -0
  84. package/src/features/chat/features/input/hooks/use-chat-input-surface-state.ts +117 -0
  85. package/src/features/chat/features/input/input-surface-plugins/__tests__/panel-app-reference-plugin.test.ts +77 -0
  86. package/src/features/chat/features/input/input-surface-plugins/__tests__/slash-command-plugin.test.ts +108 -0
  87. package/src/features/chat/features/input/input-surface-plugins/chat-input-product-plugin-adapters.types.ts +10 -0
  88. package/src/features/chat/features/input/input-surface-plugins/input-surface-search.utils.ts +108 -0
  89. package/src/features/chat/features/input/input-surface-plugins/panel-app-reference-plugin.utils.ts +108 -0
  90. package/src/features/chat/features/input/input-surface-plugins/slash-command-plugin.utils.ts +161 -0
  91. package/src/features/chat/features/input/utils/__tests__/chat-composer-state.utils.test.ts +22 -1
  92. package/src/features/chat/features/input/utils/__tests__/chat-inline-token.utils.test.ts +26 -13
  93. package/src/features/chat/features/input/utils/__tests__/ncp-chat-input-availability.utils.test.ts +7 -28
  94. package/src/features/chat/features/input/utils/chat-composer-state.utils.ts +6 -0
  95. package/src/features/chat/features/input/utils/chat-inline-token.utils.ts +26 -51
  96. package/src/features/chat/features/input/utils/chat-input-bar.utils.ts +2 -0
  97. package/src/features/chat/features/input/utils/ncp-chat-input-availability.utils.ts +5 -6
  98. package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +47 -12
  99. package/src/features/chat/features/message/components/chat-inline-panel-app-card.tsx +7 -7
  100. package/src/features/chat/features/message/components/chat-message-list.container.tsx +99 -18
  101. package/src/features/chat/features/message/utils/__tests__/chat-message.utils.test.ts +31 -12
  102. package/src/features/chat/features/message/utils/chat-message-markdown-part.utils.ts +38 -0
  103. package/src/features/chat/features/message/utils/chat-message-part.utils.ts +1 -1
  104. package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +7 -7
  105. package/src/features/chat/features/session/components/chat-sidebar-session-list.tsx +6 -6
  106. package/src/features/chat/features/session/components/session-context-icon.tsx +2 -2
  107. package/src/features/chat/features/session/components/session-header/__tests__/chat-session-project-badge.test.tsx +2 -2
  108. package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +1 -1
  109. package/src/features/chat/features/session/components/session-header/chat-session-header-menu-item.tsx +1 -1
  110. package/src/features/chat/features/session/components/session-header/chat-session-metadata-dialog.tsx +1 -1
  111. package/src/features/chat/features/session/components/session-header/chat-session-project-badge.tsx +3 -3
  112. package/src/features/chat/features/session/components/session-run-badge.tsx +1 -1
  113. package/src/features/chat/features/session/hooks/__tests__/use-chat-session-project.test.tsx +3 -30
  114. package/src/features/chat/features/session/hooks/use-chat-session-project.ts +0 -5
  115. package/src/features/chat/features/session/utils/chat-run-metadata.utils.ts +8 -0
  116. package/src/features/chat/features/session-type/components/__tests__/chat-session-type-menu.test.tsx +2 -2
  117. package/src/features/chat/features/session-type/components/__tests__/chat-session-type-option-item.test.tsx +2 -0
  118. package/src/features/chat/features/session-type/components/chat-session-type-menu.tsx +2 -2
  119. package/src/features/chat/features/session-type/components/chat-session-type-option-item.tsx +2 -2
  120. package/src/features/chat/features/session-type/hooks/use-chat-session-type-state.ts +10 -2
  121. package/src/features/chat/features/welcome/components/__tests__/chat-conversation-welcome.test.tsx +49 -31
  122. package/src/features/chat/features/welcome/components/__tests__/chat-welcome.test.tsx +2 -9
  123. package/src/features/chat/features/welcome/components/chat-conversation-welcome.tsx +21 -10
  124. package/src/features/chat/features/welcome/components/chat-welcome-agent-picker.tsx +3 -3
  125. package/src/features/chat/features/welcome/components/chat-welcome-capability-grid.tsx +4 -4
  126. package/src/features/chat/features/welcome/components/chat-welcome-project-picker.tsx +14 -19
  127. package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +5 -5
  128. package/src/features/chat/features/welcome/components/chat-welcome.tsx +6 -6
  129. package/src/features/chat/features/welcome/utils/__tests__/chat-welcome-project-options.utils.test.ts +6 -8
  130. package/src/features/chat/features/welcome/utils/chat-welcome-project-options.utils.ts +1 -16
  131. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +54 -0
  132. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +44 -76
  133. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +5 -1
  134. package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +7 -1
  135. package/src/features/chat/features/workspace/hooks/use-chat-conversation-workspace-state.ts +40 -31
  136. package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +59 -1
  137. package/src/features/chat/features/workspace/utils/chat-thread-workspace-session.utils.ts +109 -0
  138. package/src/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils.ts +44 -4
  139. package/src/features/chat/index.ts +0 -1
  140. package/src/features/chat/managers/__tests__/chat-session-list.manager.test.ts +51 -99
  141. package/src/features/chat/managers/__tests__/chat-thread.manager.test.ts +135 -21
  142. package/src/features/chat/managers/chat-session-list.manager.ts +12 -43
  143. package/src/features/chat/managers/chat-thread.manager.ts +108 -34
  144. package/src/features/chat/pages/__tests__/ncp-chat-page.test.ts +48 -1
  145. package/src/features/chat/pages/__tests__/ncp-chat-page.test.tsx +72 -0
  146. package/src/features/chat/pages/ncp-chat-page.tsx +0 -122
  147. package/src/features/chat/presenters/chat.presenter.ts +2 -19
  148. package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +31 -0
  149. package/src/features/chat/stores/chat-thread.store.ts +42 -26
  150. package/src/features/panel-apps/components/panel-app-list-item.tsx +8 -8
  151. package/src/features/panel-apps/components/panel-app-toolbar.tsx +4 -4
  152. package/src/features/panel-apps/components/panel-apps-list.tsx +20 -20
  153. package/src/features/panel-apps/hooks/use-panel-apps.ts +2 -1
  154. package/src/features/pwa/managers/__tests__/pwa-shell-theme.manager.test.ts +70 -6
  155. package/src/features/pwa/managers/pwa-shell-theme.manager.ts +10 -5
  156. package/src/features/service-apps/components/service-action-authorization-dialog.tsx +8 -8
  157. package/src/features/service-apps/components/service-apps-panel.tsx +24 -24
  158. package/src/features/settings/components/config/provider-advanced-settings-section.tsx +5 -5
  159. package/src/features/settings/components/config/provider-auth-section.tsx +7 -7
  160. package/src/features/settings/components/config/provider-form.tsx +10 -10
  161. package/src/features/settings/components/config/provider-models-section.tsx +16 -16
  162. package/src/features/settings/components/config/provider-pill-selector.tsx +1 -1
  163. package/src/features/settings/pages/providers-config-page.tsx +17 -17
  164. package/src/platforms/desktop/components/__tests__/desktop-app-shell.test.tsx +50 -10
  165. package/src/platforms/desktop/components/desktop-app-shell.tsx +34 -10
  166. package/src/platforms/desktop/components/desktop-window-chrome.tsx +41 -16
  167. package/src/shared/components/config-split-page.tsx +11 -11
  168. package/src/shared/components/doc-browser/doc-browser-home-page.tsx +2 -2
  169. package/src/shared/components/doc-browser/doc-browser-panel-parts.tsx +4 -4
  170. package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +4 -4
  171. package/src/shared/components/doc-browser/doc-browser.tsx +3 -3
  172. package/src/shared/components/resizable-right-panel/resizable-right-panel.tsx +1 -1
  173. package/src/shared/components/ui/actions/icon-action-button.tsx +1 -1
  174. package/src/shared/components/ui/button.tsx +4 -4
  175. package/src/shared/components/ui/card.tsx +4 -4
  176. package/src/shared/components/ui/dialog.tsx +5 -5
  177. package/src/shared/components/ui/input.tsx +1 -1
  178. package/src/shared/components/ui/label.tsx +1 -1
  179. package/src/shared/components/ui/popover.tsx +1 -1
  180. package/src/shared/components/ui/select.tsx +3 -3
  181. package/src/shared/components/ui/switch.tsx +3 -3
  182. package/src/shared/components/ui/tab-strip/__tests__/compact-tab-strip.test.tsx +24 -1
  183. package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +8 -4
  184. package/src/shared/components/ui/tabs.tsx +4 -4
  185. package/src/shared/components/ui/textarea.tsx +1 -1
  186. package/src/shared/lib/i18n/locales/en-US/chat.json +20 -2
  187. package/src/shared/lib/i18n/locales/en-US/core.json +9 -2
  188. package/src/shared/lib/i18n/locales/zh-CN/chat.json +20 -2
  189. package/src/shared/lib/i18n/locales/zh-CN/core.json +9 -2
  190. package/src/shared/lib/theme/index.ts +94 -52
  191. package/src/shared/lib/ui-document-title/__tests__/ui-document-title.test.ts +49 -0
  192. package/src/shared/lib/ui-document-title/index.ts +50 -21
  193. package/dist/assets/channels-list-page-D6jtziu4.js +0 -8
  194. package/dist/assets/chat-page-BBnNJoKG.js +0 -105
  195. package/dist/assets/config-split-page-BCJhqdK9.js +0 -1
  196. package/dist/assets/doc-browser-C8xOF_9F.js +0 -1
  197. package/dist/assets/doc-browser-DgQedeAn.js +0 -1
  198. package/dist/assets/doc-browser-context-B46tQGmO.js +0 -1
  199. package/dist/assets/index-7o1WdUbU.js +0 -103
  200. package/dist/assets/index-DQWmEWzk.css +0 -1
  201. package/dist/assets/mcp-marketplace-page-CWZN7ohK.js +0 -1
  202. package/dist/assets/mcp-marketplace-page-Dzull_4-.js +0 -40
  203. package/dist/assets/model-config-page-Cv0O3BIj.js +0 -1
  204. package/dist/assets/plus-Bnt56oqG.js +0 -1
  205. package/dist/assets/provider-scoped-model-input-Duuh7i3h.js +0 -1
  206. package/dist/assets/providers-config-page-CPDz0Lxc.js +0 -1
  207. package/dist/assets/remote-B0LMs8u7.js +0 -1
  208. package/dist/assets/rotate-cw-BfyG_KEF.js +0 -1
  209. package/dist/assets/runtime-config-page-q0fvv8ME.js +0 -1
  210. package/dist/assets/use-config-DZkBWIdL.js +0 -1
  211. package/dist/assets/x-CW2KO-Hz.js +0 -1
  212. package/src/features/chat/components/conversation/chat-conversation-alerts.tsx +0 -37
  213. package/src/features/chat/features/input/components/__tests__/chat-attachment-upload-limit.test.ts +0 -38
  214. package/src/features/chat/features/input/components/chat-input-bar.container.tsx +0 -496
  215. package/src/features/chat/features/message/utils/chat-message-inline-content.utils.ts +0 -95
  216. package/src/features/chat/managers/__tests__/chat-input.manager.test.ts +0 -448
  217. package/src/features/chat/managers/__tests__/chat-run-snapshot.manager.test.ts +0 -129
  218. package/src/features/chat/managers/__tests__/chat-run.manager.test.ts +0 -236
  219. package/src/features/chat/managers/__tests__/chat-session-preference-sync.manager.test.ts +0 -219
  220. package/src/features/chat/managers/chat-input.manager.ts +0 -430
  221. package/src/features/chat/managers/chat-run.manager.ts +0 -110
  222. package/src/features/chat/managers/chat-session-preference-sync.manager.ts +0 -142
  223. package/src/features/chat/stores/chat-input.store.ts +0 -104
  224. /package/dist/assets/{config-hints-CTqBnCDp.js → config-hints-BkYBc7z0.js} +0 -0
@@ -6,8 +6,9 @@ import { ChatSidebar } from "@/features/chat/components/layout/chat-sidebar";
6
6
  import type { NcpSessionListItemView } from "@/features/chat/features/ncp/hooks/use-ncp-session-list-view";
7
7
  import { useChatQueryStore } from "@/features/chat/stores/ncp-chat-query.store";
8
8
  import { useChatSessionListStore } from "@/features/chat/stores/chat-session-list.store";
9
- import { PREFERENCE_KEYS, type ChatSessionTypeOptionView } from "@/shared/lib/api";
10
-
9
+ import { PREFERENCE_KEYS } from "@/shared/lib/api";
10
+ import type { ChatSessionTypeOptionView } from "@/shared/lib/api";
11
+ import { viewportLayoutManager } from "@/app/managers/viewport-layout.manager";
11
12
  const mocks = vi.hoisted(() => ({
12
13
  createSession: vi.fn(() => "draft-session-key"),
13
14
  goToSession: vi.fn(),
@@ -30,7 +31,6 @@ const mocks = vi.hoisted(() => ({
30
31
  sessionItems: [] as NcpSessionListItemView[],
31
32
  isLoading: false,
32
33
  }));
33
-
34
34
  vi.mock("@/shared/lib/api", async (importOriginal) => {
35
35
  const actual = await importOriginal();
36
36
  return {
@@ -39,14 +39,12 @@ vi.mock("@/shared/lib/api", async (importOriginal) => {
39
39
  updatePreference: mocks.updatePreference,
40
40
  };
41
41
  });
42
-
43
42
  function createSessionItem(
44
43
  session: NcpSessionListItemView["session"],
45
44
  runStatus?: NcpSessionListItemView["runStatus"],
46
45
  ): NcpSessionListItemView {
47
46
  return { session, runStatus };
48
47
  }
49
-
50
48
  function setSessionTypes(
51
49
  options: ChatSessionTypeOptionView[],
52
50
  defaultType = "native",
@@ -63,7 +61,6 @@ function setSessionTypes(
63
61
  },
64
62
  });
65
63
  }
66
-
67
64
  function sidebarElement(variant?: "desktop" | "mobile") {
68
65
  const queryClient = new QueryClient({
69
66
  defaultOptions: {
@@ -79,14 +76,14 @@ function sidebarElement(variant?: "desktop" | "mobile") {
79
76
  </QueryClientProvider>
80
77
  );
81
78
  }
82
-
83
79
  function renderSidebar(variant?: "desktop" | "mobile") {
84
80
  return render(sidebarElement(variant));
85
81
  }
86
-
87
82
  function expectCodexSelectedInSessionTypeMenu() {
88
83
  fireEvent.click(screen.getByLabelText("Session Type"));
89
- expect(screen.getByRole("button", { name: /Codex/i }).getAttribute("aria-pressed")).toBe("true");
84
+ expect(
85
+ screen.getByRole("button", { name: /Codex/i }).getAttribute("aria-pressed"),
86
+ ).toBe("true");
90
87
  }
91
88
 
92
89
  vi.mock("@/features/chat/components/providers/chat-presenter.provider", () => ({
@@ -191,6 +188,8 @@ vi.mock("@/features/system-status", () => ({
191
188
  }));
192
189
 
193
190
  function resetSidebarTestState() {
191
+ window.localStorage.clear();
192
+ viewportLayoutManager.resetForTests();
194
193
  mocks.createSession.mockReset();
195
194
  mocks.createSession.mockReturnValue("draft-session-key");
196
195
  mocks.goToSession.mockReset();
@@ -208,10 +207,13 @@ function resetSidebarTestState() {
208
207
  value: null,
209
208
  });
210
209
  mocks.updatePreference.mockReset();
211
- mocks.updatePreference.mockImplementation(async (key: string, value: string) => ({
212
- key, value,
213
- updatedAt: "2026-06-17T00:00:00.000Z",
214
- }));
210
+ mocks.updatePreference.mockImplementation(
211
+ async (key: string, value: string) => ({
212
+ key,
213
+ value,
214
+ updatedAt: "2026-06-17T00:00:00.000Z",
215
+ }),
216
+ );
215
217
  mocks.updateNcpSession.mockReset();
216
218
  mocks.updateNcpSession.mockResolvedValue({});
217
219
  mocks.agents = [];
@@ -291,7 +293,7 @@ describe("ChatSidebar create and list basics", () => {
291
293
 
292
294
  expect(
293
295
  screen.getByTestId("brand-header").parentElement?.className,
294
- ).toContain("py-2.5");
296
+ ).toMatch(/(?:^|\s)py-2(?:\s|$)/);
295
297
  });
296
298
 
297
299
  it("shows setup required status for runtime session types that are not ready yet", () => {
@@ -364,9 +366,9 @@ describe("ChatSidebar create and list basics", () => {
364
366
 
365
367
  fireEvent.click(screen.getByRole("button", { name: "Settings menu" }));
366
368
  fireEvent.click(screen.getByRole("combobox", { name: "Theme" }));
367
- fireEvent.click(screen.getByRole("option", { name: "Cool" }));
369
+ fireEvent.click(screen.getByRole("option", { name: "Probe" }));
368
370
 
369
- expect(mocks.setTheme).toHaveBeenCalledWith("cool");
371
+ expect(mocks.setTheme).toHaveBeenCalledWith("probe");
370
372
  });
371
373
 
372
374
  it("creates the default session directly from the compact mobile add button when no menu is needed", () => {
@@ -50,7 +50,7 @@ export function ChatPageLayout({ view, confirmDialog }: ChatPageLayoutProps) {
50
50
  {view === "chat" ? (
51
51
  isMobile ? <ChatMobileShell /> : <ChatConversationPanel />
52
52
  ) : (
53
- <section className="flex-1 min-h-0 overflow-hidden bg-gradient-to-b from-gray-50/60 to-white">
53
+ <section className="flex-1 min-h-0 overflow-hidden bg-background">
54
54
  {view === "cron" ? (
55
55
  <div className="h-full overflow-auto custom-scrollbar">
56
56
  <div className="mx-auto w-full max-w-[min(1120px,100%)] px-4 py-4 sm:px-6 sm:py-5">
@@ -0,0 +1,247 @@
1
+ import { BrandHeader } from "@/shared/components/common/brand-header";
2
+ import { StatusBadge } from "@/shared/components/common/status-badge";
3
+ import { ChatSidebarListModeSwitch } from "@/features/chat/components/chat-sidebar-list-mode-switch";
4
+ import type {
5
+ groupSessionsByDate,
6
+ groupSessionsByProject,
7
+ } from "@/features/chat/features/session/utils/chat-sidebar-session-groups.utils";
8
+ import type { NcpSessionListItemView } from "@/features/chat/features/ncp/hooks/use-ncp-session-list-view";
9
+ import type { useSystemStatus } from "@/features/system-status";
10
+ import { cn } from "@/shared/lib/utils";
11
+ import { t, type I18nLanguage } from "@/shared/lib/i18n";
12
+ import type { UiTheme } from "@/shared/lib/theme";
13
+ import { SidebarNavLinkItem } from "@/app/components/layout/sidebar-items";
14
+ import { IconActionButton } from "@/shared/components/ui/actions/icon-action-button";
15
+ import {
16
+ AlarmClock,
17
+ Bot,
18
+ BrainCircuit,
19
+ PanelLeftClose,
20
+ PanelLeftOpen,
21
+ } from "lucide-react";
22
+ import { ChatSidebarSessionList } from "@/features/chat/features/session/components/chat-sidebar-session-list";
23
+ import { ChatSidebarUtilityMenu } from "@/features/chat/components/layout/chat-sidebar-utility-menu";
24
+ import { isWindowsDesktopHost } from "@/platforms/desktop";
25
+ import { viewportLayoutManager } from "@/app/managers/viewport-layout.manager";
26
+ import {
27
+ SIDEBAR_RAIL_CONTROL_CLASS,
28
+ SIDEBAR_RAIL_ICON_CLASS,
29
+ SIDEBAR_RAIL_PADDING_X_CLASS,
30
+ SIDEBAR_RAIL_STACK_CLASS,
31
+ SIDEBAR_RAIL_SURFACE_CLASS,
32
+ } from "@/app/components/layout/sidebar-rail.styles";
33
+
34
+ const navItems = [
35
+ {
36
+ target: "/cron",
37
+ label: () => t("chatSidebarScheduledTasks"),
38
+ icon: AlarmClock,
39
+ },
40
+ {
41
+ target: "/skills",
42
+ label: () => t("chatSidebarSkills"),
43
+ icon: BrainCircuit,
44
+ },
45
+ { target: "/agents", label: () => t("agentsPageTitle"), icon: Bot },
46
+ ];
47
+
48
+ function ChatSidebarCollapseButton({ isCollapsed }: { isCollapsed: boolean }) {
49
+ const label = isCollapsed ? t("sidebarExpand") : t("sidebarCollapse");
50
+ const Icon = isCollapsed ? PanelLeftOpen : PanelLeftClose;
51
+
52
+ return (
53
+ <IconActionButton
54
+ icon={<Icon className={SIDEBAR_RAIL_ICON_CLASS} />}
55
+ label={label}
56
+ className={cn(SIDEBAR_RAIL_SURFACE_CLASS, isCollapsed && SIDEBAR_RAIL_CONTROL_CLASS)}
57
+ onClick={viewportLayoutManager.toggleSidebarCollapsed}
58
+ />
59
+ );
60
+ }
61
+
62
+ export function ChatSidebarDesktopHeader({
63
+ connectionStatus,
64
+ isCollapsed,
65
+ }: {
66
+ connectionStatus: ReturnType<typeof useSystemStatus>["connectionStatus"];
67
+ isCollapsed: boolean;
68
+ }) {
69
+ const isWindowsHost = isWindowsDesktopHost();
70
+ const shouldReserveMacWindowControls =
71
+ typeof window !== "undefined" &&
72
+ window.nextclawDesktop?.platform === "darwin";
73
+
74
+ return (
75
+ <div
76
+ className={cn(
77
+ "flex items-center",
78
+ isCollapsed
79
+ ? "justify-center px-2 py-1.5"
80
+ : isWindowsHost
81
+ ? "justify-end px-3 py-1.5"
82
+ : "gap-2 px-5 py-2",
83
+ isCollapsed && shouldReserveMacWindowControls ? "pt-8" : null,
84
+ )}
85
+ >
86
+ {isCollapsed || isWindowsHost ? null : (
87
+ <BrandHeader
88
+ className="flex min-w-0 flex-1 items-center gap-2"
89
+ suffix={<StatusBadge status={connectionStatus} />}
90
+ />
91
+ )}
92
+ <ChatSidebarCollapseButton isCollapsed={isCollapsed} />
93
+ </div>
94
+ );
95
+ }
96
+
97
+ export function ChatSidebarDesktopNav({
98
+ isCollapsed,
99
+ }: {
100
+ isCollapsed: boolean;
101
+ }) {
102
+ return (
103
+ <>
104
+ <div className={cn("pb-2", isCollapsed ? "px-0" : "px-3")}>
105
+ <ul className={isCollapsed ? SIDEBAR_RAIL_STACK_CLASS : "space-y-0.5"}>
106
+ {navItems.map((item) => (
107
+ <li
108
+ key={item.target}
109
+ className={isCollapsed ? "flex justify-center" : undefined}
110
+ >
111
+ <SidebarNavLinkItem
112
+ to={item.target}
113
+ label={item.label()}
114
+ icon={item.icon}
115
+ density="compact"
116
+ collapsed={isCollapsed}
117
+ />
118
+ </li>
119
+ ))}
120
+ </ul>
121
+ </div>
122
+ <div
123
+ className={cn(
124
+ "border-t border-border/70",
125
+ isCollapsed ? "mx-2 my-1.5" : "mx-4",
126
+ )}
127
+ />
128
+ </>
129
+ );
130
+ }
131
+
132
+ export function ChatSidebarSessionArea({
133
+ defaultSessionType,
134
+ groups,
135
+ isCollapsed,
136
+ isLoading,
137
+ isProjectFirstView,
138
+ onCreateSession,
139
+ onSelectMode,
140
+ projectGroups,
141
+ renderSessionItem,
142
+ sessionTypeOptions,
143
+ }: {
144
+ defaultSessionType: string;
145
+ groups: ReturnType<typeof groupSessionsByDate>;
146
+ isCollapsed: boolean;
147
+ isLoading: boolean;
148
+ isProjectFirstView: boolean;
149
+ onCreateSession: (sessionType: string, projectRoot?: string | null) => void;
150
+ onSelectMode: (mode: "time-first" | "project-first") => void;
151
+ projectGroups: ReturnType<typeof groupSessionsByProject>;
152
+ renderSessionItem: (item: NcpSessionListItemView) => JSX.Element;
153
+ sessionTypeOptions: Parameters<
154
+ typeof ChatSidebarSessionList
155
+ >[0]["sessionTypeOptions"];
156
+ }) {
157
+ if (isCollapsed) {
158
+ return <div className="min-h-0 flex-1" aria-hidden="true" />;
159
+ }
160
+
161
+ return (
162
+ <>
163
+ <div className="flex items-center justify-between px-5 pb-2 pt-3">
164
+ <div className="text-[11px] font-medium uppercase tracking-wider text-muted-foreground/75">
165
+ {t("chatSidebarTaskRecords")}
166
+ </div>
167
+ <ChatSidebarListModeSwitch
168
+ isProjectFirstView={isProjectFirstView}
169
+ onSelectMode={onSelectMode}
170
+ />
171
+ </div>
172
+
173
+ <div className="flex-1 min-h-0 overflow-y-auto custom-scrollbar px-3 py-2">
174
+ <ChatSidebarSessionList
175
+ isLoading={isLoading}
176
+ isProjectFirstView={isProjectFirstView}
177
+ groups={groups}
178
+ projectGroups={projectGroups}
179
+ defaultSessionType={defaultSessionType}
180
+ sessionTypeOptions={sessionTypeOptions}
181
+ renderSessionItem={renderSessionItem}
182
+ onCreateSession={onCreateSession}
183
+ />
184
+ </div>
185
+ </>
186
+ );
187
+ }
188
+
189
+ export function ChatSidebarDesktopFooter({
190
+ currentLanguage,
191
+ currentLanguageLabel,
192
+ currentTheme,
193
+ currentThemeLabel,
194
+ isCollapsed,
195
+ isOpen,
196
+ languageOptions,
197
+ onOpenApps,
198
+ onOpenChange,
199
+ onOpenDocs,
200
+ onSelectLanguage,
201
+ onSelectTheme,
202
+ themeOptions,
203
+ }: {
204
+ currentLanguage: I18nLanguage;
205
+ currentLanguageLabel: string;
206
+ currentTheme: UiTheme;
207
+ currentThemeLabel: string;
208
+ isCollapsed: boolean;
209
+ isOpen: boolean;
210
+ languageOptions: Array<{ value: I18nLanguage; label: string }>;
211
+ onOpenApps: () => void;
212
+ onOpenChange: (open: boolean) => void;
213
+ onOpenDocs: () => void;
214
+ onSelectLanguage: (language: I18nLanguage) => void;
215
+ onSelectTheme: (theme: UiTheme) => void;
216
+ themeOptions: Array<{
217
+ value: UiTheme;
218
+ label: string;
219
+ }>;
220
+ }) {
221
+ return (
222
+ <div
223
+ className={cn(
224
+ "border-t border-border/70 py-3",
225
+ isCollapsed
226
+ ? cn("flex justify-center", SIDEBAR_RAIL_PADDING_X_CLASS)
227
+ : "px-3",
228
+ )}
229
+ >
230
+ <ChatSidebarUtilityMenu
231
+ isOpen={isOpen}
232
+ onOpenChange={onOpenChange}
233
+ currentTheme={currentTheme}
234
+ currentThemeLabel={currentThemeLabel}
235
+ themeOptions={themeOptions}
236
+ onSelectTheme={onSelectTheme}
237
+ currentLanguage={currentLanguage}
238
+ currentLanguageLabel={currentLanguageLabel}
239
+ languageOptions={languageOptions}
240
+ onSelectLanguage={onSelectLanguage}
241
+ onOpenDocs={onOpenDocs}
242
+ onOpenApps={onOpenApps}
243
+ collapsed={isCollapsed}
244
+ />
245
+ </div>
246
+ );
247
+ }
@@ -8,12 +8,19 @@ import {
8
8
  } from "@/shared/components/ui/popover";
9
9
  import { SessionContextIconNode } from "@/features/chat/features/session/components/session-context-icon";
10
10
  import { ChatSessionTypeMenu } from "@/features/chat/features/session-type/components/chat-session-type-menu";
11
- import type { ChatInputSnapshot } from "@/features/chat/stores/chat-input.store";
11
+ import type { ChatSessionTypeOption } from "@/features/chat/features/session-type/utils/chat-session-type.utils";
12
12
  import { cn } from "@/shared/lib/utils";
13
13
  import { t } from "@/shared/lib/i18n";
14
14
  import { Bot, ChevronDown, Plus, Search } from "lucide-react";
15
+ import {
16
+ SIDEBAR_RAIL_CONTROL_CLASS,
17
+ SIDEBAR_RAIL_ICON_CLASS,
18
+ SIDEBAR_RAIL_ITEM_GAP_CLASS,
19
+ SIDEBAR_RAIL_PRIMARY_SURFACE_CLASS,
20
+ SIDEBAR_RAIL_SURFACE_CLASS,
21
+ } from "@/app/components/layout/sidebar-rail.styles";
15
22
 
16
- type SessionTypeOption = ChatInputSnapshot["sessionTypeOptions"][number];
23
+ type SessionTypeOption = ChatSessionTypeOption;
17
24
  type NewSessionActionStyleVariant =
18
25
  | "neutralSurface"
19
26
  | "brandSoft"
@@ -34,23 +41,23 @@ const NEW_SESSION_ACTION_STYLE_CLASSES: Record<
34
41
  neutralSurface: {
35
42
  leftVariant: "ghost",
36
43
  leftClassName:
37
- "bg-white/90 text-gray-700 shadow-none transition-[background-color,color,box-shadow] hover:bg-white hover:text-gray-950 hover:shadow-sm active:bg-white/95",
44
+ "bg-card text-foreground shadow-none transition-[background-color,color,box-shadow] hover:bg-accent hover:text-accent-foreground hover:shadow-sm active:bg-accent",
38
45
  rightClassName:
39
- "bg-white/90 text-gray-600 shadow-none transition-[background-color,color,box-shadow] hover:bg-white hover:text-gray-900 hover:shadow-sm active:bg-white/95",
46
+ "bg-card text-muted-foreground shadow-none transition-[background-color,color,box-shadow] hover:bg-accent hover:text-accent-foreground hover:shadow-sm active:bg-accent",
40
47
  },
41
48
  brandSoft: {
42
49
  leftVariant: "ghost",
43
50
  leftClassName:
44
- "bg-primary/10 text-primary shadow-none transition-[background-color,color,box-shadow] hover:bg-primary/15 hover:text-primary-700 hover:shadow-sm active:bg-primary/20",
51
+ "bg-primary/10 text-primary shadow-none ring-1 ring-primary/10 transition-[background-color,color,box-shadow] hover:bg-primary/15 hover:text-primary-700 hover:shadow-sm active:bg-primary/20",
45
52
  rightClassName:
46
- "bg-primary/10 text-primary shadow-none transition-[background-color,color,box-shadow] hover:bg-primary/15 hover:text-primary-700 hover:shadow-sm active:bg-primary/20",
53
+ "bg-primary/10 text-primary shadow-none ring-1 ring-primary/10 transition-[background-color,color,box-shadow] hover:bg-primary/15 hover:text-primary-700 hover:shadow-sm active:bg-primary/20",
47
54
  },
48
55
  brandTextSurface: {
49
56
  leftVariant: "ghost",
50
57
  leftClassName:
51
- "bg-white/90 text-primary shadow-none transition-[background-color,color,box-shadow] hover:bg-primary/10 hover:text-primary-700 hover:shadow-sm active:bg-primary/15",
58
+ "bg-card text-primary shadow-none transition-[background-color,color,box-shadow] hover:bg-accent hover:text-primary-700 hover:shadow-sm active:bg-primary/15",
52
59
  rightClassName:
53
- "bg-white/90 text-primary shadow-none transition-[background-color,color,box-shadow] hover:bg-primary/10 hover:text-primary-700 hover:shadow-sm active:bg-primary/15",
60
+ "bg-card text-primary shadow-none transition-[background-color,color,box-shadow] hover:bg-accent hover:text-primary-700 hover:shadow-sm active:bg-primary/15",
54
61
  },
55
62
  brandSolid: {
56
63
  leftVariant: "primary",
@@ -72,6 +79,7 @@ type ChatSidebarToolbarProps = {
72
79
  onCreateSession: (sessionType: string) => void;
73
80
  onSelectNewSessionType: (sessionType: string) => void;
74
81
  onQueryChange: (query: string) => void;
82
+ collapsed?: boolean;
75
83
  };
76
84
 
77
85
  function getMobileCreateOptions(params: {
@@ -122,11 +130,73 @@ export function ChatSidebarDesktopToolbar(props: ChatSidebarToolbarProps) {
122
130
  onCreateSession,
123
131
  onSelectNewSessionType,
124
132
  onQueryChange,
133
+ collapsed = false,
125
134
  } = props;
126
135
  const supportsSessionTypeSwitch = sessionTypeOptions.length > 1;
127
136
  const actionStyle =
128
137
  NEW_SESSION_ACTION_STYLE_CLASSES[NEW_SESSION_ACTION_STYLE_VARIANT];
129
138
 
139
+ if (collapsed) {
140
+ return (
141
+ <div className="px-2 pb-2">
142
+ <div
143
+ className={cn(
144
+ "flex flex-col items-center",
145
+ SIDEBAR_RAIL_ITEM_GAP_CLASS,
146
+ )}
147
+ >
148
+ <IconActionButton
149
+ icon={<Plus className={SIDEBAR_RAIL_ICON_CLASS} />}
150
+ label={t("chatSidebarNewTask")}
151
+ className={cn(
152
+ SIDEBAR_RAIL_CONTROL_CLASS,
153
+ SIDEBAR_RAIL_PRIMARY_SURFACE_CLASS,
154
+ )}
155
+ onClick={() => {
156
+ onCreateMenuOpenChange(false);
157
+ onCreateSession(selectedNewSessionType);
158
+ }}
159
+ />
160
+ {supportsSessionTypeSwitch ? (
161
+ <Popover
162
+ open={isCreateMenuOpen}
163
+ onOpenChange={onCreateMenuOpenChange}
164
+ >
165
+ <PopoverTrigger asChild>
166
+ <IconActionButton
167
+ icon={
168
+ <SessionTypeTriggerIcon
169
+ option={selectedNewSessionTypeOption}
170
+ />
171
+ }
172
+ label={t("chatSessionTypeLabel")}
173
+ className={cn(
174
+ SIDEBAR_RAIL_CONTROL_CLASS,
175
+ SIDEBAR_RAIL_SURFACE_CLASS,
176
+ )}
177
+ />
178
+ </PopoverTrigger>
179
+ <PopoverContent
180
+ align="start"
181
+ side="right"
182
+ 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)]"
183
+ >
184
+ <ChatSessionTypeMenu
185
+ options={sessionTypeOptions}
186
+ selectedSessionType={selectedNewSessionType}
187
+ onSelect={(sessionType) => {
188
+ onSelectNewSessionType(sessionType);
189
+ onCreateMenuOpenChange(false);
190
+ }}
191
+ />
192
+ </PopoverContent>
193
+ </Popover>
194
+ ) : null}
195
+ </div>
196
+ </div>
197
+ );
198
+ }
199
+
130
200
  return (
131
201
  <>
132
202
  <div className="px-4 pb-3">
@@ -136,9 +206,7 @@ export function ChatSidebarDesktopToolbar(props: ChatSidebarToolbarProps) {
136
206
  className={cn(
137
207
  "min-w-0 rounded-xl",
138
208
  actionStyle.leftClassName,
139
- supportsSessionTypeSwitch
140
- ? "flex-1 rounded-r-md"
141
- : "w-full",
209
+ supportsSessionTypeSwitch ? "flex-1 rounded-r-md" : "w-full",
142
210
  )}
143
211
  onClick={() => {
144
212
  onCreateMenuOpenChange(false);
@@ -157,7 +225,9 @@ export function ChatSidebarDesktopToolbar(props: ChatSidebarToolbarProps) {
157
225
  <IconActionButton
158
226
  icon={
159
227
  <span className="inline-flex items-center gap-0.5">
160
- <SessionTypeTriggerIcon option={selectedNewSessionTypeOption} />
228
+ <SessionTypeTriggerIcon
229
+ option={selectedNewSessionTypeOption}
230
+ />
161
231
  <ChevronDown className="h-3 w-3 opacity-60" />
162
232
  </span>
163
233
  }
@@ -171,7 +241,7 @@ export function ChatSidebarDesktopToolbar(props: ChatSidebarToolbarProps) {
171
241
  </PopoverTrigger>
172
242
  <PopoverContent
173
243
  align="end"
174
- className="w-56 rounded-2xl border border-gray-200/80 bg-white p-1.5 shadow-[0_24px_60px_-28px_rgba(15,23,42,0.38)]"
244
+ 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)]"
175
245
  >
176
246
  <ChatSessionTypeMenu
177
247
  options={sessionTypeOptions}
@@ -189,7 +259,7 @@ export function ChatSidebarDesktopToolbar(props: ChatSidebarToolbarProps) {
189
259
 
190
260
  <div className="px-4 pb-3">
191
261
  <div className="relative">
192
- <Search className="absolute left-3 top-2.5 h-3.5 w-3.5 text-gray-400" />
262
+ <Search className="absolute left-3 top-2.5 h-3.5 w-3.5 text-muted-foreground/70" />
193
263
  <Input
194
264
  value={query}
195
265
  onChange={(event) => onQueryChange(event.target.value)}
@@ -224,28 +294,31 @@ export function ChatSidebarMobileToolbar(props: ChatSidebarToolbarProps) {
224
294
  <div className="px-4 pb-2 pt-1">
225
295
  <div className="flex items-center gap-2">
226
296
  <div className="relative min-w-0 flex-1">
227
- <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400" />
297
+ <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground/70" />
228
298
  <Input
229
299
  value={query}
230
300
  onChange={(event) => onQueryChange(event.target.value)}
231
301
  placeholder={t("chatSidebarSearchPlaceholder")}
232
- className="h-9 rounded-full border-transparent bg-gray-100/80 pl-9 pr-3 text-[13px] shadow-none focus:border-gray-200/80 focus:bg-white"
302
+ className="h-9 rounded-full border-transparent bg-muted pl-9 pr-3 text-[13px] shadow-none focus:border-border focus:bg-card"
233
303
  />
234
304
  </div>
235
305
 
236
306
  {hasCreateMenu ? (
237
- <Popover open={isCreateMenuOpen} onOpenChange={onCreateMenuOpenChange}>
307
+ <Popover
308
+ open={isCreateMenuOpen}
309
+ onOpenChange={onCreateMenuOpenChange}
310
+ >
238
311
  <PopoverTrigger asChild>
239
312
  <IconActionButton
240
313
  icon={<Plus className="h-4 w-4" />}
241
314
  label={t("chatSidebarNewTask")}
242
315
  tooltip={false}
243
- className="h-9 w-9 shrink-0 rounded-full bg-gray-100/80 text-gray-700 shadow-none hover:bg-gray-200/80 hover:text-gray-900"
316
+ className="h-9 w-9 shrink-0 rounded-full bg-muted text-foreground shadow-none hover:bg-accent hover:text-accent-foreground"
244
317
  />
245
318
  </PopoverTrigger>
246
319
  <PopoverContent
247
320
  align="end"
248
- className="w-60 rounded-3xl border border-gray-200/80 bg-white p-2 shadow-[0_24px_70px_-30px_rgba(15,23,42,0.45)]"
321
+ className="w-60 rounded-3xl border border-border bg-popover p-2 text-popover-foreground shadow-[0_24px_70px_-30px_rgba(15,23,42,0.45)]"
249
322
  >
250
323
  <ChatSessionTypeMenu
251
324
  options={createOptions}
@@ -263,7 +336,7 @@ export function ChatSidebarMobileToolbar(props: ChatSidebarToolbarProps) {
263
336
  <IconActionButton
264
337
  icon={<Plus className="h-4 w-4" />}
265
338
  label={t("chatSidebarNewTask")}
266
- className="h-9 w-9 shrink-0 rounded-full bg-gray-100/80 text-gray-700 shadow-none hover:bg-gray-200/80 hover:text-gray-900"
339
+ className="h-9 w-9 shrink-0 rounded-full bg-muted text-foreground shadow-none hover:bg-accent hover:text-accent-foreground"
267
340
  onClick={() => onCreateSession(defaultSessionType)}
268
341
  />
269
342
  )}