@nextclaw/ui 0.14.1-beta.1 → 0.14.2

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 (179) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/dist/assets/{api-dQ6uQSZG.js → api-a14tR_z1.js} +7 -7
  3. package/dist/assets/channels-list-page-CFGkm4DT.js +8 -0
  4. package/dist/assets/chat-page-CEdavJXc.js +105 -0
  5. package/dist/assets/{config-split-page-CeFfbaqc.js → config-split-page-B5b9B0uE.js} +1 -1
  6. package/dist/assets/{confirm-dialog-C95Y4QPC.js → confirm-dialog-ClH_Ec7n.js} +1 -1
  7. package/dist/assets/{desktop-update-config-CcK6jiEb.js → desktop-update-config-DPNDnVpk.js} +1 -1
  8. package/dist/assets/{dist-DTGzeil6.js → dist-BtCS2Ucq.js} +1 -1
  9. package/dist/assets/{dist-fGogBmPA.js → dist-CLGGLm8b.js} +1 -1
  10. package/dist/assets/doc-browser-5nMWYKBD.js +1 -0
  11. package/dist/assets/doc-browser-BJRLhztv.js +1 -0
  12. package/dist/assets/doc-browser-context-D4JwMMxK.js +1 -0
  13. package/dist/assets/{ellipsis-D2F4KMiU.js → ellipsis-CtJXjIol.js} +1 -1
  14. package/dist/assets/{external-link-CcgtBK26.js → external-link-CdJiG13p.js} +1 -1
  15. package/dist/assets/index-BDN1zzMQ.js +105 -0
  16. package/dist/assets/index-g3uSZXoc.css +1 -0
  17. package/dist/assets/mcp-marketplace-page-BU0kIjhR.js +40 -0
  18. package/dist/assets/mcp-marketplace-page-sMNFSq_T.js +1 -0
  19. package/dist/assets/middleware-CkFT3R4v.js +1 -0
  20. package/dist/assets/model-config-page-D6hYXROd.js +1 -0
  21. package/dist/assets/plus-DPjb0piO.js +1 -0
  22. package/dist/assets/provider-scoped-model-input-DAX2HgmR.js +1 -0
  23. package/dist/assets/providers-config-page-BzAeaACA.js +1 -0
  24. package/dist/assets/{react-CTqdhFMk.js → react-C6cZgP44.js} +1 -1
  25. package/dist/assets/remote-B0G80uPr.js +1 -0
  26. package/dist/assets/rotate-cw-DnEB1Rju.js +1 -0
  27. package/dist/assets/runtime-config-page-C5xKaV3i.js +1 -0
  28. package/dist/assets/{save-C9fKWfVB.js → save-DKA0x4zk.js} +1 -1
  29. package/dist/assets/{search-D5FQ5q0X.js → search-BNlcoj5c.js} +1 -1
  30. package/dist/assets/{search-config-page-AMEJJNIS.js → search-config-page-Cq9uJ-N8.js} +1 -1
  31. package/dist/assets/{secrets-config-page-CcgJnvBO.js → secrets-config-page-CxSbZLBo.js} +2 -2
  32. package/dist/assets/{select-Cu5n0E-3.js → select-CvTlDZTQ.js} +1 -1
  33. package/dist/assets/{tag-chip-C5aOtjxu.js → tag-chip-8ffF2y2C.js} +1 -1
  34. package/dist/assets/use-config-DmT0o1gv.js +1 -0
  35. package/dist/assets/x-BiSSpgqB.js +1 -0
  36. package/dist/index.html +15 -14
  37. package/package.json +9 -9
  38. package/src/app/components/app-presenter-provider.tsx +11 -2
  39. package/src/app/components/layout/__tests__/app-layout.test.tsx +11 -2
  40. package/src/app/components/layout/__tests__/sidebar.layout.test.tsx +110 -79
  41. package/src/app/components/layout/app-layout.tsx +18 -4
  42. package/src/app/components/layout/sidebar-items.tsx +194 -71
  43. package/src/app/components/layout/sidebar-rail.styles.ts +15 -0
  44. package/src/app/components/layout/sidebar.tsx +340 -83
  45. package/src/app/managers/viewport-layout.manager.ts +10 -0
  46. package/src/app/stores/viewport-layout.store.ts +39 -3
  47. package/src/features/agents/components/__tests__/agents-page.test.tsx +62 -39
  48. package/src/features/agents/components/agents-page.tsx +10 -6
  49. package/src/features/chat/components/conversation/__tests__/chat-conversation-header-section.test.tsx +145 -0
  50. package/src/features/chat/components/conversation/__tests__/chat-conversation-panel.test.tsx +69 -762
  51. package/src/features/chat/components/conversation/__tests__/chat-conversation-workspace-section.test.tsx +132 -0
  52. package/src/features/chat/components/conversation/chat-conversation-content.tsx +22 -15
  53. package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +14 -15
  54. package/src/features/chat/components/conversation/chat-conversation-panel.tsx +18 -18
  55. package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +10 -4
  56. package/src/features/chat/components/layout/__tests__/chat-sidebar-read-state.test.tsx +52 -11
  57. package/src/features/chat/components/layout/__tests__/chat-sidebar.test.tsx +77 -12
  58. package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +247 -0
  59. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +182 -21
  60. package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +82 -25
  61. package/src/features/chat/components/layout/chat-sidebar.tsx +79 -93
  62. package/src/features/chat/components/providers/chat-presenter.provider.tsx +0 -6
  63. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +289 -0
  64. package/src/features/chat/features/conversation/components/session-conversation-input.tsx +427 -0
  65. package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +204 -0
  66. package/src/features/chat/features/conversation/hooks/use-session-conversation-input-attachments.ts +66 -0
  67. package/src/features/chat/features/{input/hooks/use-chat-input-bar-query-state.ts → conversation/hooks/use-session-conversation-input-query.ts} +32 -17
  68. package/src/features/chat/features/conversation/hooks/use-session-conversation-input-state.ts +281 -0
  69. package/src/features/chat/features/conversation/utils/session-conversation-input-toolbar.utils.ts +158 -0
  70. package/src/features/chat/features/input/hooks/__tests__/use-chat-input-surface-state.test.tsx +56 -0
  71. package/src/features/chat/features/input/hooks/use-chat-input-surface-state.ts +117 -0
  72. package/src/features/chat/features/input/hooks/use-chat-model-favorites.ts +2 -1
  73. package/src/features/chat/features/input/input-surface-plugins/__tests__/panel-app-reference-plugin.test.ts +77 -0
  74. package/src/features/chat/features/input/input-surface-plugins/__tests__/slash-command-plugin.test.ts +108 -0
  75. package/src/features/chat/features/input/input-surface-plugins/chat-input-product-plugin-adapters.types.ts +10 -0
  76. package/src/features/chat/features/input/input-surface-plugins/input-surface-search.utils.ts +108 -0
  77. package/src/features/chat/features/input/input-surface-plugins/panel-app-reference-plugin.utils.ts +108 -0
  78. package/src/features/chat/features/input/input-surface-plugins/slash-command-plugin.utils.ts +161 -0
  79. package/src/features/chat/features/input/utils/__tests__/chat-composer-state.utils.test.ts +22 -1
  80. package/src/features/chat/features/input/utils/__tests__/chat-inline-token.utils.test.ts +26 -13
  81. package/src/features/chat/features/input/utils/__tests__/ncp-chat-input-availability.utils.test.ts +7 -28
  82. package/src/features/chat/features/input/utils/chat-composer-state.utils.ts +6 -0
  83. package/src/features/chat/features/input/utils/chat-inline-token.utils.ts +26 -51
  84. package/src/features/chat/features/input/utils/chat-input-bar.utils.ts +2 -0
  85. package/src/features/chat/features/input/utils/ncp-chat-input-availability.utils.ts +5 -6
  86. package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +47 -12
  87. package/src/features/chat/features/message/components/chat-message-list.container.tsx +93 -12
  88. package/src/features/chat/features/message/utils/__tests__/chat-message.utils.test.ts +31 -12
  89. package/src/features/chat/features/message/utils/chat-message-markdown-part.utils.ts +38 -0
  90. package/src/features/chat/features/message/utils/chat-message-part.utils.ts +1 -1
  91. package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +5 -4
  92. package/src/features/chat/features/session/components/chat-sidebar-session-list.tsx +2 -2
  93. package/src/features/chat/features/session/hooks/__tests__/use-chat-session-project.test.tsx +3 -30
  94. package/src/features/chat/features/session/hooks/use-chat-session-project.ts +0 -5
  95. package/src/features/chat/features/session/utils/chat-run-metadata.utils.ts +8 -0
  96. package/src/features/chat/features/session-type/components/__tests__/{chat-sidebar-create-menu.test.tsx → chat-session-type-menu.test.tsx} +5 -5
  97. package/src/features/chat/features/session-type/components/__tests__/chat-session-type-option-item.test.tsx +29 -1
  98. package/src/features/chat/features/session-type/components/{chat-sidebar-create-menu.tsx → chat-session-type-menu.tsx} +13 -9
  99. package/src/features/chat/features/session-type/components/chat-session-type-option-item.tsx +17 -5
  100. package/src/features/chat/features/session-type/hooks/__tests__/use-chat-new-session-type-preference.test.tsx +152 -0
  101. package/src/features/chat/features/session-type/hooks/use-chat-new-session-type-preference.ts +159 -0
  102. package/src/features/chat/features/welcome/components/__tests__/chat-conversation-welcome.test.tsx +49 -31
  103. package/src/features/chat/features/welcome/components/__tests__/chat-welcome.test.tsx +2 -2
  104. package/src/features/chat/features/welcome/components/chat-conversation-welcome.tsx +21 -10
  105. package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +2 -2
  106. package/src/features/chat/features/welcome/components/chat-welcome.tsx +2 -2
  107. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +54 -0
  108. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +44 -76
  109. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +5 -1
  110. package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +7 -1
  111. package/src/features/chat/features/workspace/hooks/use-chat-conversation-workspace-state.ts +40 -31
  112. package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +59 -1
  113. package/src/features/chat/features/workspace/utils/chat-thread-workspace-session.utils.ts +109 -0
  114. package/src/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils.ts +44 -4
  115. package/src/features/chat/index.ts +0 -1
  116. package/src/features/chat/managers/__tests__/chat-session-list.manager.test.ts +51 -99
  117. package/src/features/chat/managers/__tests__/chat-thread.manager.test.ts +135 -21
  118. package/src/features/chat/managers/chat-session-list.manager.ts +12 -43
  119. package/src/features/chat/managers/chat-thread.manager.ts +108 -34
  120. package/src/features/chat/pages/__tests__/ncp-chat-page.test.ts +48 -1
  121. package/src/features/chat/pages/__tests__/ncp-chat-page.test.tsx +72 -0
  122. package/src/features/chat/pages/ncp-chat-page.tsx +0 -122
  123. package/src/features/chat/presenters/chat.presenter.ts +2 -19
  124. package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +31 -0
  125. package/src/features/chat/stores/chat-thread.store.ts +42 -26
  126. package/src/features/marketplace/components/__tests__/marketplace-page.test.tsx +24 -0
  127. package/src/features/marketplace/components/curated-shelves/marketplace-shelf-card.tsx +8 -3
  128. package/src/features/marketplace/components/marketplace-item-list-view.tsx +2 -2
  129. package/src/features/marketplace/components/marketplace-list-card.tsx +124 -98
  130. package/src/features/marketplace/components/marketplace-page-parts.tsx +11 -6
  131. package/src/features/panel-apps/hooks/use-panel-apps.ts +2 -1
  132. package/src/platforms/desktop/components/__tests__/desktop-app-shell.test.tsx +50 -10
  133. package/src/platforms/desktop/components/desktop-app-shell.tsx +34 -10
  134. package/src/platforms/desktop/components/desktop-window-chrome.tsx +41 -16
  135. package/src/shared/components/common/__tests__/agent-avatar.test.tsx +3 -1
  136. package/src/shared/components/common/agent-avatar.tsx +5 -2
  137. package/src/shared/components/ui/tab-strip/__tests__/compact-tab-strip.test.tsx +24 -1
  138. package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +8 -4
  139. package/src/shared/lib/api/index.ts +1 -0
  140. package/src/shared/lib/api/preferences/preference-keys.config.ts +9 -0
  141. package/src/shared/lib/i18n/locales/en-US/chat.json +20 -2
  142. package/src/shared/lib/i18n/locales/en-US/core.json +2 -0
  143. package/src/shared/lib/i18n/locales/en-US/marketplace.json +2 -0
  144. package/src/shared/lib/i18n/locales/zh-CN/chat.json +20 -2
  145. package/src/shared/lib/i18n/locales/zh-CN/core.json +2 -0
  146. package/src/shared/lib/i18n/locales/zh-CN/marketplace.json +2 -0
  147. package/src/shared/lib/ui-document-title/__tests__/ui-document-title.test.ts +49 -0
  148. package/src/shared/lib/ui-document-title/index.ts +50 -21
  149. package/dist/assets/channels-list-page-DfpjB8XB.js +0 -8
  150. package/dist/assets/chat-page-D3QaEqjs.js +0 -105
  151. package/dist/assets/doc-browser-CuBTcBEZ.js +0 -1
  152. package/dist/assets/doc-browser-DVHhEb96.js +0 -1
  153. package/dist/assets/doc-browser-context-BfMXwnrz.js +0 -1
  154. package/dist/assets/index-ByJCbQqr.css +0 -1
  155. package/dist/assets/index-DjXqiloY.js +0 -103
  156. package/dist/assets/mcp-marketplace-page-98-V__3u.js +0 -1
  157. package/dist/assets/mcp-marketplace-page-BNq_PNmO.js +0 -40
  158. package/dist/assets/model-config-page-aAUkZkSX.js +0 -1
  159. package/dist/assets/plus-1Rxl5FlV.js +0 -1
  160. package/dist/assets/provider-scoped-model-input-we4_Z4gP.js +0 -1
  161. package/dist/assets/providers-config-page-CtMkPSyu.js +0 -1
  162. package/dist/assets/remote-fQ7N_r8u.js +0 -1
  163. package/dist/assets/rotate-cw-CzfIeAJj.js +0 -1
  164. package/dist/assets/runtime-config-page-TD1UrTbG.js +0 -1
  165. package/dist/assets/use-config-D8TESeo6.js +0 -1
  166. package/dist/assets/x-1qETdQ70.js +0 -1
  167. package/src/features/chat/components/conversation/chat-conversation-alerts.tsx +0 -37
  168. package/src/features/chat/features/input/components/__tests__/chat-attachment-upload-limit.test.ts +0 -38
  169. package/src/features/chat/features/input/components/chat-input-bar.container.tsx +0 -496
  170. package/src/features/chat/features/message/utils/chat-message-inline-content.utils.ts +0 -95
  171. package/src/features/chat/managers/__tests__/chat-input.manager.test.ts +0 -448
  172. package/src/features/chat/managers/__tests__/chat-run-snapshot.manager.test.ts +0 -129
  173. package/src/features/chat/managers/__tests__/chat-run.manager.test.ts +0 -236
  174. package/src/features/chat/managers/__tests__/chat-session-preference-sync.manager.test.ts +0 -219
  175. package/src/features/chat/managers/chat-input.manager.ts +0 -430
  176. package/src/features/chat/managers/chat-run.manager.ts +0 -110
  177. package/src/features/chat/managers/chat-session-preference-sync.manager.ts +0 -142
  178. package/src/features/chat/stores/chat-input.store.ts +0 -104
  179. /package/dist/assets/{config-hints-CTqBnCDp.js → config-hints-BkYBc7z0.js} +0 -0
@@ -1,8 +1,29 @@
1
- import { NavLink } from 'react-router-dom';
2
- import { Popover, PopoverContent, PopoverTrigger } from '@/shared/components/ui/popover';
3
- import { Select, SelectContent, SelectItem, SelectTrigger } from '@/shared/components/ui/select';
4
- import { t, type I18nLanguage } from '@/shared/lib/i18n';
5
- import type { UiTheme } from '@/shared/lib/theme';
1
+ import { NavLink } from "react-router-dom";
2
+ import {
3
+ Popover,
4
+ PopoverContent,
5
+ PopoverTrigger,
6
+ } from "@/shared/components/ui/popover";
7
+ import {
8
+ Select,
9
+ SelectContent,
10
+ SelectItem,
11
+ SelectTrigger,
12
+ } from "@/shared/components/ui/select";
13
+ import {
14
+ Tooltip,
15
+ TooltipContent,
16
+ TooltipProvider,
17
+ TooltipTrigger,
18
+ } from "@/shared/components/ui/tooltip";
19
+ import { t, type I18nLanguage } from "@/shared/lib/i18n";
20
+ import type { UiTheme } from "@/shared/lib/theme";
21
+ import { cn } from "@/shared/lib/utils";
22
+ import {
23
+ SIDEBAR_RAIL_CONTROL_CLASS,
24
+ SIDEBAR_RAIL_ICON_CLASS,
25
+ SIDEBAR_RAIL_SURFACE_CLASS,
26
+ } from "@/app/components/layout/sidebar-rail.styles";
6
27
  import {
7
28
  BookOpen,
8
29
  ChevronRight,
@@ -11,7 +32,7 @@ import {
11
32
  Palette,
12
33
  Settings,
13
34
  type LucideIcon,
14
- } from 'lucide-react';
35
+ } from "lucide-react";
15
36
 
16
37
  type ChatSidebarUtilityOption<Value extends string> = {
17
38
  value: Value;
@@ -31,6 +52,7 @@ type ChatSidebarUtilityMenuProps = {
31
52
  onSelectLanguage: (language: I18nLanguage) => void;
32
53
  onOpenDocs: () => void;
33
54
  onOpenApps: () => void;
55
+ collapsed?: boolean;
34
56
  };
35
57
 
36
58
  export function ChatSidebarUtilityMenu({
@@ -46,6 +68,7 @@ export function ChatSidebarUtilityMenu({
46
68
  onSelectLanguage,
47
69
  onOpenDocs,
48
70
  onOpenApps,
71
+ collapsed = false,
49
72
  }: ChatSidebarUtilityMenuProps) {
50
73
  const handleOpenDocs = () => {
51
74
  onOpenDocs();
@@ -59,20 +82,54 @@ export function ChatSidebarUtilityMenu({
59
82
 
60
83
  return (
61
84
  <Popover open={isOpen} onOpenChange={onOpenChange}>
62
- <PopoverTrigger asChild>
63
- <button
64
- type="button"
65
- aria-label={t('settingsMenu')}
66
- className="flex w-full items-center gap-2.5 rounded-xl px-3 py-2 text-[13px] font-medium text-gray-600 transition-all duration-base hover:bg-gray-200/60 hover:text-gray-800"
67
- >
68
- <Settings className="h-4 w-4 shrink-0 text-gray-400" />
69
- <span className="min-w-0 flex-1 text-left">{t('settings')}</span>
70
- <span className="max-w-[112px] truncate text-[13px] text-gray-500">
71
- {currentThemeLabel} / {currentLanguageLabel}
72
- </span>
73
- </button>
74
- </PopoverTrigger>
75
- <PopoverContent side="top" align="start" className="w-64 p-2">
85
+ {collapsed ? (
86
+ <TooltipProvider delayDuration={250}>
87
+ <Tooltip>
88
+ <TooltipTrigger asChild>
89
+ <PopoverTrigger asChild>
90
+ <button
91
+ type="button"
92
+ aria-label={t("settingsMenu")}
93
+ className={cn(
94
+ "flex items-center justify-center",
95
+ SIDEBAR_RAIL_CONTROL_CLASS,
96
+ SIDEBAR_RAIL_SURFACE_CLASS,
97
+ )}
98
+ >
99
+ <Settings
100
+ className={cn(
101
+ SIDEBAR_RAIL_ICON_CLASS,
102
+ "shrink-0 text-gray-500",
103
+ )}
104
+ />
105
+ </button>
106
+ </PopoverTrigger>
107
+ </TooltipTrigger>
108
+ <TooltipContent side="right" className="text-xs">
109
+ {t("settingsMenu")}
110
+ </TooltipContent>
111
+ </Tooltip>
112
+ </TooltipProvider>
113
+ ) : (
114
+ <PopoverTrigger asChild>
115
+ <button
116
+ type="button"
117
+ aria-label={t("settingsMenu")}
118
+ className="flex w-full items-center gap-2.5 rounded-xl px-3 py-2 text-[13px] font-medium text-gray-600 transition-all duration-base hover:bg-gray-200/60 hover:text-gray-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/35"
119
+ >
120
+ <Settings className="h-4 w-4 shrink-0 text-gray-400" />
121
+ <span className="min-w-0 flex-1 text-left">{t("settings")}</span>
122
+ <span className="max-w-[112px] truncate text-[13px] text-gray-500">
123
+ {currentThemeLabel} / {currentLanguageLabel}
124
+ </span>
125
+ </button>
126
+ </PopoverTrigger>
127
+ )}
128
+ <PopoverContent
129
+ side={collapsed ? "right" : "top"}
130
+ align={collapsed ? "end" : "start"}
131
+ className="w-64 p-2"
132
+ >
76
133
  <div className="space-y-1">
77
134
  <NavLink
78
135
  to="/settings"
@@ -80,7 +137,7 @@ export function ChatSidebarUtilityMenu({
80
137
  className="flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-[13px] font-medium text-gray-700 transition-colors hover:bg-gray-100"
81
138
  >
82
139
  <Settings className="h-4 w-4 text-gray-400" />
83
- <span className="flex-1 text-left">{t('settings')}</span>
140
+ <span className="flex-1 text-left">{t("settings")}</span>
84
141
  </NavLink>
85
142
  <button
86
143
  type="button"
@@ -88,7 +145,7 @@ export function ChatSidebarUtilityMenu({
88
145
  className="flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-[13px] font-medium text-gray-700 transition-colors hover:bg-gray-100"
89
146
  >
90
147
  <BookOpen className="h-4 w-4 text-gray-400" />
91
- <span className="flex-1 text-left">{t('docBrowserHelp')}</span>
148
+ <span className="flex-1 text-left">{t("docBrowserHelp")}</span>
92
149
  </button>
93
150
  <button
94
151
  type="button"
@@ -96,7 +153,7 @@ export function ChatSidebarUtilityMenu({
96
153
  className="flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-[13px] font-medium text-gray-700 transition-colors hover:bg-gray-100"
97
154
  >
98
155
  <Boxes className="h-4 w-4 text-gray-400" />
99
- <span className="flex-1 text-left">{t('appsTitle')}</span>
156
+ <span className="flex-1 text-left">{t("appsTitle")}</span>
100
157
  </button>
101
158
  </div>
102
159
 
@@ -104,7 +161,7 @@ export function ChatSidebarUtilityMenu({
104
161
 
105
162
  <ChatSidebarUtilitySelect
106
163
  icon={Palette}
107
- label={t('theme')}
164
+ label={t("theme")}
108
165
  options={themeOptions}
109
166
  value={currentTheme}
110
167
  valueLabel={currentThemeLabel}
@@ -114,7 +171,7 @@ export function ChatSidebarUtilityMenu({
114
171
 
115
172
  <ChatSidebarUtilitySelect
116
173
  icon={Languages}
117
- label={t('language')}
174
+ label={t("language")}
118
175
  options={languageOptions}
119
176
  value={currentLanguage}
120
177
  valueLabel={currentLanguageLabel}
@@ -1,7 +1,4 @@
1
1
  import { useEffect, useMemo, useState } from "react";
2
- import { BrandHeader } from "@/shared/components/common/brand-header";
3
- import { StatusBadge } from "@/shared/components/common/status-badge";
4
- import { ChatSidebarListModeSwitch } from "@/features/chat/components/chat-sidebar-list-mode-switch";
5
2
  import {
6
3
  getSessionTitle,
7
4
  groupChildSessionsByParentKey,
@@ -25,36 +22,26 @@ import { THEME_OPTIONS } from "@/shared/lib/theme";
25
22
  import { useI18n } from "@/app/components/i18n-provider";
26
23
  import { useTheme } from "@/app/components/theme-provider";
27
24
  import { useDocBrowser } from "@/shared/components/doc-browser";
28
- import { SidebarNavLinkItem } from "@/app/components/layout/sidebar-items";
29
- import { AlarmClock, Bot, BrainCircuit } from "lucide-react";
30
25
  import { ChatSidebarSessionEntry } from "@/features/chat/features/session/components/chat-sidebar-session-entry";
31
- import { ChatSidebarSessionList } from "@/features/chat/features/session/components/chat-sidebar-session-list";
32
26
  import {
33
27
  ChatSidebarDesktopToolbar,
34
28
  ChatSidebarMobileToolbar,
35
29
  } from "@/features/chat/components/layout/chat-sidebar-toolbar";
36
- import { ChatSidebarUtilityMenu } from "@/features/chat/components/layout/chat-sidebar-utility-menu";
30
+ import {
31
+ ChatSidebarDesktopFooter,
32
+ ChatSidebarDesktopHeader,
33
+ ChatSidebarDesktopNav,
34
+ ChatSidebarSessionArea,
35
+ } from "@/features/chat/components/layout/chat-sidebar-desktop-layout";
37
36
  import { openApps } from "@/features/panel-apps";
38
- import { isWindowsDesktopHost } from "@/platforms/desktop";
39
37
  import {
40
38
  buildSessionTypeOptions,
41
39
  DEFAULT_SESSION_TYPE,
42
40
  normalizeSessionType,
43
41
  } from "@/features/chat/features/session-type/utils/chat-session-type.utils";
44
-
45
- const navItems = [
46
- {
47
- target: "/cron",
48
- label: () => t("chatSidebarScheduledTasks"),
49
- icon: AlarmClock,
50
- },
51
- {
52
- target: "/skills",
53
- label: () => t("chatSidebarSkills"),
54
- icon: BrainCircuit,
55
- },
56
- { target: "/agents", label: () => t("agentsPageTitle"), icon: Bot },
57
- ];
42
+ import { useChatNewSessionTypePreference } from "@/features/chat/features/session-type/hooks/use-chat-new-session-type-preference";
43
+ import { useViewportLayoutStore } from "@/app/stores/viewport-layout.store";
44
+ import { SIDEBAR_RAIL_WIDTH_CLASS } from "@/app/components/layout/sidebar-rail.styles";
58
45
 
59
46
  type ChatSidebarVariant = "desktop" | "mobile";
60
47
 
@@ -103,6 +90,9 @@ export function ChatSidebar({
103
90
  const isMobileVariant = variant === "mobile";
104
91
  const presenter = usePresenter();
105
92
  const docBrowser = useDocBrowser();
93
+ const isSidebarCollapsed = useViewportLayoutStore(
94
+ (state) => state.isSidebarCollapsed,
95
+ );
106
96
  const [isCreateMenuOpen, setIsCreateMenuOpen] = useState(false);
107
97
  const [isUtilityMenuOpen, setIsUtilityMenuOpen] = useState(false);
108
98
  const listSnapshot = useChatSessionListStore((state) => state.snapshot);
@@ -173,7 +163,12 @@ export function ChatSidebar({
173
163
  ),
174
164
  [defaultSessionType, sessionTypeOptions],
175
165
  );
166
+ const newSessionTypePreference = useChatNewSessionTypePreference({
167
+ defaultSessionType,
168
+ sessionTypeOptions,
169
+ });
176
170
  const isProjectFirstView = listSnapshot.listMode === "project-first";
171
+ const shouldCollapse = !isMobileVariant && isSidebarCollapsed;
177
172
  const optimisticReadAtBySessionKey = useChatSessionUnreadState(
178
173
  items,
179
174
  listSnapshot.selectedSessionKey,
@@ -232,30 +227,41 @@ export function ChatSidebar({
232
227
  return (
233
228
  <aside
234
229
  className={cn(
235
- "flex h-full min-h-0 flex-col bg-secondary",
230
+ "flex h-full min-h-0 flex-col bg-secondary transition-[width] duration-200 ease-out",
236
231
  isMobileVariant
237
232
  ? "flex-1 overflow-hidden"
238
- : "w-[280px] shrink-0 border-r border-gray-200/60",
233
+ : shouldCollapse
234
+ ? cn(
235
+ SIDEBAR_RAIL_WIDTH_CLASS,
236
+ "shrink-0 border-r border-gray-200/60",
237
+ )
238
+ : "w-[280px] shrink-0 border-r border-gray-200/60",
239
239
  )}
240
+ data-sidebar-collapsed={shouldCollapse ? "true" : "false"}
240
241
  >
241
- {!isMobileVariant && !isWindowsDesktopHost() ? (
242
- <div className="px-5 py-2.5">
243
- <BrandHeader
244
- className="flex min-w-0 items-center gap-2"
245
- suffix={<StatusBadge status={systemStatus.connectionStatus} />}
246
- />
247
- </div>
242
+ {!isMobileVariant ? (
243
+ <ChatSidebarDesktopHeader
244
+ connectionStatus={systemStatus.connectionStatus}
245
+ isCollapsed={shouldCollapse}
246
+ />
248
247
  ) : null}
249
248
 
250
249
  {isMobileVariant ? (
251
250
  <ChatSidebarMobileToolbar
252
251
  query={listSnapshot.query}
253
- defaultSessionType={defaultSessionType}
252
+ defaultSessionType={newSessionTypePreference.selectedSessionType}
254
253
  sessionTypeOptions={sessionTypeOptions}
255
254
  nonDefaultSessionTypeOptions={nonDefaultSessionTypeOptions}
255
+ selectedNewSessionType={newSessionTypePreference.selectedSessionType}
256
+ selectedNewSessionTypeOption={
257
+ newSessionTypePreference.selectedSessionTypeOption
258
+ }
256
259
  isCreateMenuOpen={isCreateMenuOpen}
257
260
  onCreateMenuOpenChange={setIsCreateMenuOpen}
258
261
  onCreateSession={createSessionAndOpenIfNeeded}
262
+ onSelectNewSessionType={
263
+ newSessionTypePreference.setSelectedSessionType
264
+ }
259
265
  onQueryChange={presenter.chatSessionListManager.setQuery}
260
266
  />
261
267
  ) : (
@@ -264,79 +270,59 @@ export function ChatSidebar({
264
270
  defaultSessionType={defaultSessionType}
265
271
  sessionTypeOptions={sessionTypeOptions}
266
272
  nonDefaultSessionTypeOptions={nonDefaultSessionTypeOptions}
273
+ selectedNewSessionType={newSessionTypePreference.selectedSessionType}
274
+ selectedNewSessionTypeOption={
275
+ newSessionTypePreference.selectedSessionTypeOption
276
+ }
267
277
  isCreateMenuOpen={isCreateMenuOpen}
268
278
  onCreateMenuOpenChange={setIsCreateMenuOpen}
269
279
  onCreateSession={createSessionAndOpenIfNeeded}
280
+ onSelectNewSessionType={
281
+ newSessionTypePreference.setSelectedSessionType
282
+ }
270
283
  onQueryChange={presenter.chatSessionListManager.setQuery}
284
+ collapsed={shouldCollapse}
271
285
  />
272
286
  )}
273
287
 
274
288
  {!isMobileVariant ? (
275
- <div className="px-3 pb-2">
276
- <ul className="space-y-0.5">
277
- {navItems.map((item) => (
278
- <li key={item.target}>
279
- <SidebarNavLinkItem
280
- to={item.target}
281
- label={item.label()}
282
- icon={item.icon}
283
- density="compact"
284
- />
285
- </li>
286
- ))}
287
- </ul>
288
- </div>
289
- ) : null}
290
-
291
- {!isMobileVariant ? (
292
- <div className="mx-4 border-t border-gray-200/60" />
289
+ <ChatSidebarDesktopNav isCollapsed={shouldCollapse} />
293
290
  ) : null}
294
291
 
295
- <div className="flex items-center justify-between px-5 pb-2 pt-3">
296
- <div className="text-[11px] font-medium uppercase tracking-wider text-gray-400">
297
- {t("chatSidebarTaskRecords")}
298
- </div>
299
- <ChatSidebarListModeSwitch
300
- isProjectFirstView={isProjectFirstView}
301
- onSelectMode={presenter.chatSessionListManager.setListMode}
302
- />
303
- </div>
304
-
305
- <div className="flex-1 min-h-0 overflow-y-auto custom-scrollbar px-3 py-2">
306
- <ChatSidebarSessionList
307
- isLoading={isLoading}
308
- isProjectFirstView={isProjectFirstView}
309
- groups={groups}
310
- projectGroups={projectGroups}
311
- defaultSessionType={defaultSessionType}
312
- sessionTypeOptions={sessionTypeOptions}
313
- renderSessionItem={renderSessionItem}
314
- onCreateSession={createSessionAndOpenIfNeeded}
315
- />
316
- </div>
292
+ <ChatSidebarSessionArea
293
+ defaultSessionType={newSessionTypePreference.selectedSessionType}
294
+ groups={groups}
295
+ isCollapsed={shouldCollapse}
296
+ isLoading={isLoading}
297
+ isProjectFirstView={isProjectFirstView}
298
+ onCreateSession={createSessionAndOpenIfNeeded}
299
+ onSelectMode={presenter.chatSessionListManager.setListMode}
300
+ projectGroups={projectGroups}
301
+ renderSessionItem={renderSessionItem}
302
+ sessionTypeOptions={sessionTypeOptions}
303
+ />
317
304
 
318
305
  {!isMobileVariant ? (
319
- <div className="px-3 py-3 border-t border-gray-200/60">
320
- <ChatSidebarUtilityMenu
321
- isOpen={isUtilityMenuOpen}
322
- onOpenChange={setIsUtilityMenuOpen}
323
- currentTheme={theme}
324
- currentThemeLabel={currentThemeLabel}
325
- themeOptions={utilityThemeOptions}
326
- onSelectTheme={setTheme}
327
- currentLanguage={language}
328
- currentLanguageLabel={currentLanguageLabel}
329
- languageOptions={utilityLanguageOptions}
330
- onSelectLanguage={handleLanguageSwitch}
331
- onOpenDocs={() =>
332
- docBrowser.open(undefined, {
333
- kind: "docs",
334
- title: t("docBrowserHelp"),
335
- })
336
- }
337
- onOpenApps={() => openApps(docBrowser)}
338
- />
339
- </div>
306
+ <ChatSidebarDesktopFooter
307
+ currentLanguage={language}
308
+ currentLanguageLabel={currentLanguageLabel}
309
+ currentTheme={theme}
310
+ currentThemeLabel={currentThemeLabel}
311
+ isCollapsed={shouldCollapse}
312
+ isOpen={isUtilityMenuOpen}
313
+ languageOptions={utilityLanguageOptions}
314
+ onOpenApps={() => openApps(docBrowser)}
315
+ onOpenChange={setIsUtilityMenuOpen}
316
+ onOpenDocs={() =>
317
+ docBrowser.open(undefined, {
318
+ kind: "docs",
319
+ title: t("docBrowserHelp"),
320
+ })
321
+ }
322
+ onSelectLanguage={handleLanguageSwitch}
323
+ onSelectTheme={setTheme}
324
+ themeOptions={utilityThemeOptions}
325
+ />
340
326
  ) : null}
341
327
  </aside>
342
328
  );
@@ -2,25 +2,19 @@ import { createContext, useContext, type ReactNode } from 'react';
2
2
  import type {
3
3
  ChatSessionListManager,
4
4
  } from '@/features/chat/managers/chat-session-list.manager';
5
- import type { ChatRunManager } from '@/features/chat/managers/chat-run.manager';
6
5
  import type { ChatUiManager } from '@/features/chat/managers/chat-ui.manager';
7
- import type { ChatInputManager } from '@/features/chat/managers/chat-input.manager';
8
6
  import type { ChatQueryManager } from '@/features/chat/managers/chat-query.manager';
9
7
  import type { ChatThreadManager } from '@/features/chat/managers/chat-thread.manager';
10
8
 
11
9
  type PublicManager<T extends object> = Pick<T, keyof T>;
12
10
 
13
- export type ChatInputManagerLike = PublicManager<ChatInputManager>;
14
11
  export type ChatThreadManagerLike = PublicManager<ChatThreadManager>;
15
12
 
16
13
  export type ChatPresenterLike = {
17
14
  chatUiManager: ChatUiManager;
18
- chatRunManager: ChatRunManager;
19
- chatInputManager: ChatInputManagerLike;
20
15
  chatQueryManager: ChatQueryManager;
21
16
  chatSessionListManager: ChatSessionListManager;
22
17
  chatThreadManager: ChatThreadManagerLike;
23
- startAgentCreationDraft: (prompt: string) => void;
24
18
  };
25
19
 
26
20
  const ChatPresenterContext = createContext<ChatPresenterLike | null>(null);