@vibe-forge/client 0.11.2 → 1.0.0

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 (232) hide show
  1. package/cli.cjs +6 -11
  2. package/dist/assets/{arc-De_WjPJ3.js → arc-CbOXL0l9.js} +1 -1
  3. package/dist/assets/{blockDiagram-c4efeb88-C4aR2zTE.js → blockDiagram-c4efeb88-CqxINvsS.js} +1 -1
  4. package/dist/assets/{c4Diagram-c83219d4-BZH3rq_m.js → c4Diagram-c83219d4-BKazU0hb.js} +1 -1
  5. package/dist/assets/channel-Dnopc5A6.js +1 -0
  6. package/dist/assets/{classDiagram-beda092f-BzJgBrIK.js → classDiagram-beda092f-fAFX5BpB.js} +1 -1
  7. package/dist/assets/{classDiagram-v2-2358418a-5ZtXcnT3.js → classDiagram-v2-2358418a-w1VkNGJj.js} +1 -1
  8. package/dist/assets/clone-sQthahUA.js +1 -0
  9. package/dist/assets/{createText-1719965b-DUVvEtmR.js → createText-1719965b-CEinakVP.js} +1 -1
  10. package/dist/assets/{cssMode-GoTNjuXX.js → cssMode-DPqRki4y.js} +1 -1
  11. package/dist/assets/{edges-96097737-Dd7m4Cvs.js → edges-96097737-Cb0F1_3K.js} +1 -1
  12. package/dist/assets/{erDiagram-0228fc6a-DxqFlG_f.js → erDiagram-0228fc6a-C-N2fx-J.js} +1 -1
  13. package/dist/assets/{flowDb-c6c81e3f-DU0C5kCI.js → flowDb-c6c81e3f-D1Xz_8Gf.js} +1 -1
  14. package/dist/assets/{flowDiagram-50d868cf-Di1uDa_X.js → flowDiagram-50d868cf-DyPSZyAj.js} +1 -1
  15. package/dist/assets/flowDiagram-v2-4f6560a1-OazrdWQO.js +1 -0
  16. package/dist/assets/{flowchart-elk-definition-6af322e1-CwG8aty5.js → flowchart-elk-definition-6af322e1-Dr1DDXwE.js} +1 -1
  17. package/dist/assets/{freemarker2-j39cqTlI.js → freemarker2-C3DvPFaK.js} +1 -1
  18. package/dist/assets/{ganttDiagram-a2739b55-baO_lzL-.js → ganttDiagram-a2739b55-DmvY1GRj.js} +1 -1
  19. package/dist/assets/{gitGraphDiagram-82fe8481-COoHjYMf.js → gitGraphDiagram-82fe8481-CoXfPYYi.js} +1 -1
  20. package/dist/assets/{graph-KxESr4M5.js → graph-BkDQy7Qt.js} +1 -1
  21. package/dist/assets/{handlebars-BgjdZO8G.js → handlebars-BcTFdqjl.js} +1 -1
  22. package/dist/assets/{html-Ba7tYObe.js → html-Dg-O6XFr.js} +1 -1
  23. package/dist/assets/{htmlMode-Bztvbig1.js → htmlMode-B_wqYWvn.js} +1 -1
  24. package/dist/assets/{index-5325376f-BMTAx2mL.js → index-5325376f-kxPTR3_e.js} +1 -1
  25. package/dist/assets/index-o93dlo92.css +32 -0
  26. package/dist/assets/{index-Pm_kLJvG.js → index-wkhI4dr6.js} +350 -329
  27. package/dist/assets/{infoDiagram-8eee0895-CC74qbHY.js → infoDiagram-8eee0895-BEvqkwPI.js} +1 -1
  28. package/dist/assets/{javascript-C1e1cllX.js → javascript-DhlOH8_z.js} +1 -1
  29. package/dist/assets/{journeyDiagram-c64418c1-C4MyOdE6.js → journeyDiagram-c64418c1-gKtLYmmp.js} +1 -1
  30. package/dist/assets/{jsonMode-BC98AlvF.js → jsonMode-DxTbF9OD.js} +1 -1
  31. package/dist/assets/{layout-CxAyTlr7.js → layout-CDaZEk6E.js} +1 -1
  32. package/dist/assets/{line-DhaUfI71.js → line-DNRQu8iq.js} +1 -1
  33. package/dist/assets/{linear-MYukzldK.js → linear-Cph9Z6_j.js} +1 -1
  34. package/dist/assets/{liquid-DahfJEYl.js → liquid-ByZ6JgRG.js} +1 -1
  35. package/dist/assets/{lspLanguageFeatures-BWDJcswW.js → lspLanguageFeatures-DzvhkgnM.js} +1 -1
  36. package/dist/assets/{mdx-BELlF_FD.js → mdx-D8RGHTl6.js} +1 -1
  37. package/dist/assets/{mermaid.core-BrQnSGSY.js → mermaid.core-BgcryF__.js} +4 -4
  38. package/dist/assets/{mindmap-definition-8da855dc-B0FoxTiy.js → mindmap-definition-8da855dc-WrxK0FcB.js} +1 -1
  39. package/dist/assets/{pieDiagram-a8764435-Ddr2cjSL.js → pieDiagram-a8764435-VsZBsiQy.js} +1 -1
  40. package/dist/assets/{python--C9if_AD.js → python-CXVtk_cg.js} +1 -1
  41. package/dist/assets/{quadrantDiagram-1e28029f-BlEs7Mrl.js → quadrantDiagram-1e28029f-BVlgwOvU.js} +1 -1
  42. package/dist/assets/{razor-B9U9JxKn.js → razor-0tind7h2.js} +1 -1
  43. package/dist/assets/{requirementDiagram-08caed73-kEFOAu2v.js → requirementDiagram-08caed73-CpPMPoYp.js} +1 -1
  44. package/dist/assets/{sankeyDiagram-a04cb91d-BBghez8I.js → sankeyDiagram-a04cb91d-Cm5nnRmc.js} +1 -1
  45. package/dist/assets/{sequenceDiagram-c5b8d532-CJqgzdUE.js → sequenceDiagram-c5b8d532-DpMlJvJB.js} +1 -1
  46. package/dist/assets/{stateDiagram-1ecb1508-BER4XEI6.js → stateDiagram-1ecb1508-DU1zc7vq.js} +1 -1
  47. package/dist/assets/{stateDiagram-v2-c2b004d7-EBV2vSks.js → stateDiagram-v2-c2b004d7-D-0RgmAp.js} +1 -1
  48. package/dist/assets/{styles-b4e223ce-k0eswZsE.js → styles-b4e223ce-BSO-yNWV.js} +1 -1
  49. package/dist/assets/{styles-ca3715f6-Ckr7GA-0.js → styles-ca3715f6-CHnsn2Ro.js} +1 -1
  50. package/dist/assets/{styles-d45a18b0-C1bpSwV3.js → styles-d45a18b0-B-rVGjEq.js} +1 -1
  51. package/dist/assets/{svgDrawCommon-b86b1483-CDtKpGvy.js → svgDrawCommon-b86b1483-CA3Pl89f.js} +1 -1
  52. package/dist/assets/{timeline-definition-faaaa080-BeGR-vua.js → timeline-definition-faaaa080-BcihLR6s.js} +1 -1
  53. package/dist/assets/{tsMode-D_gJXIy3.js → tsMode-D9GGa5Ur.js} +1 -1
  54. package/dist/assets/{typescript-BoKcNXkN.js → typescript-BT9CK_EL.js} +1 -1
  55. package/dist/assets/{xml-DZvURlJ-.js → xml-DNO75J-T.js} +1 -1
  56. package/dist/assets/{xychartDiagram-f5964ef8-DxfeLuYV.js → xychartDiagram-f5964ef8-DJTwe32X.js} +1 -1
  57. package/dist/assets/{yaml-CTC8PAGY.js → yaml-7CVzhiP2.js} +1 -1
  58. package/dist/index.html +2 -2
  59. package/package.json +13 -10
  60. package/src/api/git.ts +12 -0
  61. package/src/api/sessions.ts +131 -4
  62. package/src/api/types.ts +2 -1
  63. package/src/api.ts +13 -0
  64. package/src/components/ArchiveView.scss +143 -54
  65. package/src/components/ArchiveView.tsx +181 -167
  66. package/src/components/CodeBlock.scss +5 -0
  67. package/src/components/ConfigView.scss +142 -31
  68. package/src/components/ConfigView.tsx +161 -86
  69. package/src/components/MarkdownContent.tsx +7 -0
  70. package/src/components/NavRail.scss +248 -0
  71. package/src/components/NavRail.tsx +80 -107
  72. package/src/components/NavRailCompact.tsx +107 -0
  73. package/src/components/NavRailCompactMoreSheet.tsx +141 -0
  74. package/src/components/ShortcutTooltip.tsx +4 -2
  75. package/src/components/Sidebar.scss +51 -0
  76. package/src/components/Sidebar.tsx +43 -16
  77. package/src/components/automation-view/RuleFormPanel.scss +40 -13
  78. package/src/components/automation-view/RuleSidebar.scss +73 -47
  79. package/src/components/automation-view/RuleSidebar.tsx +9 -13
  80. package/src/components/automation-view/RunHistoryPanel.scss +141 -13
  81. package/src/components/automation-view/RunHistoryPanel.tsx +203 -161
  82. package/src/components/automation-view/TaskList.scss +44 -13
  83. package/src/components/automation-view/TriggerList.scss +46 -14
  84. package/src/components/automation-view/index.scss +82 -10
  85. package/src/components/automation-view/index.tsx +108 -55
  86. package/src/components/benchmark-view/BenchmarkCasePanel.scss +36 -16
  87. package/src/components/benchmark-view/BenchmarkSidebar.scss +44 -22
  88. package/src/components/benchmark-view/BenchmarkSidebar.tsx +0 -6
  89. package/src/components/benchmark-view/BenchmarkView.scss +63 -20
  90. package/src/components/benchmark-view/index.tsx +71 -34
  91. package/src/components/chat/AGENTS.md +14 -2
  92. package/src/components/chat/ChatComposerCard.scss +77 -0
  93. package/src/components/chat/ChatComposerCard.tsx +59 -0
  94. package/src/components/chat/ChatHeader.scss +187 -0
  95. package/src/components/chat/ChatHeader.tsx +209 -57
  96. package/src/components/chat/ChatHistoryView.tsx +279 -52
  97. package/src/components/chat/ChatTimelineView.scss +94 -1
  98. package/src/components/chat/ChatTimelineView.tsx +42 -0
  99. package/src/components/chat/CurrentTodoList.scss +210 -200
  100. package/src/components/chat/CurrentTodoList.tsx +116 -48
  101. package/src/components/chat/NewSessionGuide.scss +139 -1
  102. package/src/components/chat/NewSessionGuide.tsx +57 -100
  103. package/src/components/chat/NewSessionGuideCompactPanel.tsx +130 -0
  104. package/src/components/chat/NewSessionGuideGrid.tsx +141 -0
  105. package/src/components/chat/QueuedMessagesCard.scss +195 -0
  106. package/src/components/chat/QueuedMessagesCard.tsx +170 -0
  107. package/src/components/chat/git-controls/BranchSwitcherDropdown.tsx +61 -56
  108. package/src/components/chat/git-controls/BranchSwitcherResults.tsx +167 -0
  109. package/src/components/chat/git-controls/BranchTreeEntries.tsx +99 -0
  110. package/src/components/chat/git-controls/ChatGitControls.scss +437 -5
  111. package/src/components/chat/git-controls/ChatGitControls.tsx +136 -109
  112. package/src/components/chat/git-controls/DraftGitControls.tsx +91 -0
  113. package/src/components/chat/git-controls/GitOperationsDropdown.tsx +10 -2
  114. package/src/components/chat/git-controls/GitWorktreeDropdown.tsx +301 -28
  115. package/src/components/chat/git-controls/git-branch-tree.ts +148 -0
  116. package/src/components/chat/git-controls/use-chat-draft-git-controls.ts +168 -0
  117. package/src/components/chat/git-controls/use-chat-git-controls.ts +76 -3
  118. package/src/components/chat/messages/MessageContextMenu.tsx +3 -1
  119. package/src/components/chat/messages/MessageItem.scss +78 -4
  120. package/src/components/chat/messages/MessageItem.tsx +47 -3
  121. package/src/components/chat/sender/@components/adapter-select/AdapterSelectControl.scss +23 -0
  122. package/src/components/chat/sender/@components/reference-actions/ReferenceActionsControl.scss +17 -0
  123. package/src/components/chat/sender/@components/reference-actions/ReferencePermissionActionsPopover.tsx +4 -1
  124. package/src/components/chat/sender/@components/sender-attachments/SenderAttachments.scss +167 -30
  125. package/src/components/chat/sender/@components/sender-attachments/SenderAttachments.tsx +95 -23
  126. package/src/components/chat/sender/@components/sender-body/SenderBody.tsx +10 -0
  127. package/src/components/chat/sender/@components/sender-interaction-panel/SenderInteractionPanel.scss +161 -45
  128. package/src/components/chat/sender/@components/sender-interaction-panel/SenderInteractionPanel.tsx +310 -71
  129. package/src/components/chat/sender/@components/sender-monaco-editor/SenderMonacoEditor.tsx +18 -0
  130. package/src/components/chat/sender/@components/sender-monaco-editor/use-sender-monaco-editor.ts +86 -9
  131. package/src/components/chat/sender/@components/sender-monaco-editor/use-sender-monaco-theme.ts +52 -3
  132. package/src/components/chat/sender/@components/sender-submit-action/SenderSubmitAction.scss +110 -1
  133. package/src/components/chat/sender/@components/sender-submit-action/SenderSubmitAction.tsx +137 -17
  134. package/src/components/chat/sender/@components/sender-toolbar/SenderSelectBase.scss +21 -0
  135. package/src/components/chat/sender/@components/sender-toolbar/SenderSelectShared.scss +21 -0
  136. package/src/components/chat/sender/@components/sender-toolbar/SenderToolbar.scss +63 -0
  137. package/src/components/chat/sender/@components/sender-toolbar/SenderToolbar.tsx +12 -6
  138. package/src/components/chat/sender/@core/build-sender-controller-result.ts +6 -0
  139. package/src/components/chat/sender/@core/build-sender-toolbar.ts +25 -2
  140. package/src/components/chat/sender/@core/create-sender-toolbar-handlers.ts +9 -2
  141. package/src/components/chat/sender/@core/get-sender-runtime-state.ts +1 -1
  142. package/src/components/chat/sender/@core/interaction-request.ts +2 -2
  143. package/src/components/chat/sender/@core/sender-toolbar-bindings.ts +28 -4
  144. package/src/components/chat/sender/@hooks/use-model-select-browser.tsx +4 -2
  145. package/src/components/chat/sender/@hooks/use-sender-controller.ts +56 -11
  146. package/src/components/chat/sender/@hooks/use-sender-keydown.ts +64 -0
  147. package/src/components/chat/sender/@hooks/use-sender-shortcuts.ts +16 -1
  148. package/src/components/chat/sender/@hooks/use-sender-submit.ts +16 -8
  149. package/src/components/chat/sender/@types/sender-props.ts +20 -3
  150. package/src/components/chat/sender/@types/sender-toolbar-types.ts +12 -1
  151. package/src/components/chat/sender/Sender.scss +4 -1
  152. package/src/components/chat/sender/Sender.tsx +3 -12
  153. package/src/components/chat/session-timeline-panel/EventList.scss +88 -0
  154. package/src/components/chat/session-timeline-panel/EventList.tsx +99 -47
  155. package/src/components/chat/session-timeline-panel/gantt.ts +23 -7
  156. package/src/components/chat/session-timeline-panel/git-graph.ts +6 -1
  157. package/src/components/chat/session-timeline-panel/index.scss +14 -1
  158. package/src/components/chat/session-timeline-panel/index.tsx +86 -10
  159. package/src/components/chat/session-timeline-panel/types.ts +4 -0
  160. package/src/components/chat/status-bar/ChatStatusBar.scss +27 -0
  161. package/src/components/chat/status-bar/ChatStatusBar.tsx +39 -0
  162. package/src/components/chat/terminal/ChatTerminalView.tsx +6 -0
  163. package/src/components/chat/tools/core/ToolCallBox.scss +19 -0
  164. package/src/components/chat/tools/core/ToolGroup.scss +32 -0
  165. package/src/components/chat/tools/task/components/TaskToolCard.scss +59 -1
  166. package/src/components/config/ConfigEditors.scss +20 -6
  167. package/src/components/config/ConfigFieldRow.scss +57 -17
  168. package/src/components/config/ConfigSectionForm.scss +10 -4
  169. package/src/components/config/ConfigSectionPanel.tsx +18 -11
  170. package/src/components/config/configSchema.ts +1 -0
  171. package/src/components/config/record-editors/RecordEditors.scss +42 -9
  172. package/src/components/dock-panel/DockPanel.scss +6 -2
  173. package/src/components/dock-panel/DockPanel.tsx +12 -16
  174. package/src/components/knowledge-base/KnowledgeBaseView.scss +180 -6
  175. package/src/components/knowledge-base/KnowledgeBaseView.tsx +98 -26
  176. package/src/components/knowledge-base/components/ActionButton.scss +4 -0
  177. package/src/components/knowledge-base/components/EmptyState.scss +5 -8
  178. package/src/components/knowledge-base/components/EntitiesTab.tsx +8 -2
  179. package/src/components/knowledge-base/components/EntityItem.scss +10 -3
  180. package/src/components/knowledge-base/components/FilterBar.scss +13 -2
  181. package/src/components/knowledge-base/components/FlowsTab.tsx +8 -2
  182. package/src/components/knowledge-base/components/KnowledgeBaseHeader.scss +2 -23
  183. package/src/components/knowledge-base/components/KnowledgeBaseHeader.tsx +0 -5
  184. package/src/components/knowledge-base/components/KnowledgeList.scss +15 -6
  185. package/src/components/knowledge-base/components/LoadingState.scss +4 -0
  186. package/src/components/knowledge-base/components/RuleItem.scss +86 -0
  187. package/src/components/knowledge-base/components/RuleItem.tsx +2 -0
  188. package/src/components/knowledge-base/components/RulesTab.tsx +8 -2
  189. package/src/components/knowledge-base/components/SectionHeader.scss +3 -18
  190. package/src/components/knowledge-base/components/SectionHeader.tsx +3 -7
  191. package/src/components/knowledge-base/components/SkillsTab.tsx +8 -3
  192. package/src/components/knowledge-base/components/SpecItem.scss +16 -7
  193. package/src/components/layout/@hooks/use-mobile-sidebar-modal.ts +190 -0
  194. package/src/components/layout/AppShell.scss +106 -6
  195. package/src/components/layout/AppShell.tsx +118 -10
  196. package/src/components/layout/PageShell.scss +41 -0
  197. package/src/components/layout/PageShell.tsx +32 -0
  198. package/src/components/layout/mobile-sidebar-constants.ts +1 -0
  199. package/src/components/nav-rail-compact-config.ts +114 -0
  200. package/src/components/nav-rail-items.tsx +181 -0
  201. package/src/components/sidebar/SessionContextMenu.tsx +3 -1
  202. package/src/components/sidebar/SessionItem.scss +62 -0
  203. package/src/components/sidebar/SessionItem.tsx +97 -52
  204. package/src/components/sidebar/SessionList.tsx +6 -0
  205. package/src/components/sidebar/SidebarHeader.scss +49 -0
  206. package/src/components/sidebar/SidebarHeader.tsx +27 -5
  207. package/src/components/sidebar/SidebarHeaderBatchActions.tsx +8 -4
  208. package/src/components/sidebar/SidebarHeaderSearchActions.tsx +6 -3
  209. package/src/components/sidebar/SidebarUtilityFooter.tsx +69 -0
  210. package/src/components/workspace/ContextFilePicker.tsx +12 -4
  211. package/src/hooks/chat/chat-session-workspace-draft.ts +25 -0
  212. package/src/hooks/chat/session-view-cache.ts +4 -1
  213. package/src/hooks/chat/use-chat-adapter.ts +5 -1
  214. package/src/hooks/chat/use-chat-model-adapter-selection.tsx +5 -1
  215. package/src/hooks/chat/use-chat-scroll.ts +24 -7
  216. package/src/hooks/chat/use-chat-session-actions.ts +118 -6
  217. package/src/hooks/chat/use-chat-session-messages.ts +20 -1
  218. package/src/hooks/chat/use-chat-session.ts +2 -0
  219. package/src/hooks/use-responsive-layout.ts +115 -0
  220. package/src/main.tsx +8 -0
  221. package/src/resources/adapters.ts +15 -0
  222. package/src/resources/locales/en.json +84 -1
  223. package/src/resources/locales/zh.json +84 -1
  224. package/src/routes/ChatRoute.scss +152 -9
  225. package/src/routes/ChatRoute.tsx +31 -34
  226. package/src/store/index.ts +2 -0
  227. package/dist/assets/channel-BvERb8WU.js +0 -1
  228. package/dist/assets/clone-B9_0v-6Y.js +0 -1
  229. package/dist/assets/flowDiagram-v2-4f6560a1-LpS8Kb00.js +0 -1
  230. package/dist/assets/index-C1oh0w9H.css +0 -32
  231. package/src/components/chat/ThinkingStatus.scss +0 -70
  232. package/src/components/chat/ThinkingStatus.tsx +0 -13
@@ -47,6 +47,254 @@
47
47
  }
48
48
  }
49
49
 
50
+ .nav-rail--compact {
51
+ width: 100%;
52
+ height: auto;
53
+ padding: 8px max(8px, env(safe-area-inset-right))
54
+ calc(16px + env(safe-area-inset-bottom))
55
+ max(8px, env(safe-area-inset-left));
56
+ border-top: 1px solid var(--border-color);
57
+ background: color-mix(
58
+ in srgb,
59
+ var(--sub-sub-bg-color) 96%,
60
+ var(--bg-color) 4%
61
+ );
62
+ z-index: 20;
63
+
64
+ .nav-rail-compact-list {
65
+ display: grid;
66
+ grid-template-columns: repeat(6, minmax(0, 1fr));
67
+ align-items: center;
68
+ gap: 4px;
69
+ width: 100%;
70
+ }
71
+
72
+ .nav-item--compact {
73
+ width: 100%;
74
+ min-width: 0;
75
+ height: 44px;
76
+ border-radius: 8px;
77
+
78
+ .material-symbols-rounded {
79
+ font-size: 20px;
80
+ }
81
+ }
82
+ }
83
+
84
+ .nav-rail-compact-sheet-backdrop {
85
+ position: fixed;
86
+ inset: 0;
87
+ border: 0;
88
+ background: rgba(15, 23, 42, .28);
89
+ opacity: 0;
90
+ visibility: hidden;
91
+ pointer-events: none;
92
+ transition: opacity .2s ease, visibility 0s linear .2s;
93
+ z-index: 68;
94
+ }
95
+
96
+ .nav-rail-compact-sheet-backdrop.is-open {
97
+ opacity: 1;
98
+ visibility: visible;
99
+ pointer-events: auto;
100
+ transition-delay: 0s;
101
+ }
102
+
103
+ .nav-rail-compact-sheet {
104
+ position: fixed;
105
+ left: 0;
106
+ right: 0;
107
+ bottom: 0;
108
+ display: flex;
109
+ flex-direction: column;
110
+ gap: 16px;
111
+ padding: 10px 12px calc(16px + env(safe-area-inset-bottom));
112
+ border-top: 1px solid var(--border-color);
113
+ border-top-left-radius: 12px;
114
+ border-top-right-radius: 12px;
115
+ background: var(--bg-color);
116
+ box-shadow: none;
117
+ transform: translateY(100%);
118
+ visibility: hidden;
119
+ transition:
120
+ transform .24s cubic-bezier(.4, 0, .2, 1),
121
+ visibility 0s linear .24s;
122
+ z-index: 69;
123
+ }
124
+
125
+ .nav-rail-compact-sheet.is-open {
126
+ transform: translateY(0);
127
+ visibility: visible;
128
+ transition-delay: 0s;
129
+ }
130
+
131
+ .nav-rail-compact-sheet__handle {
132
+ width: 40px;
133
+ height: 4px;
134
+ margin: 0 auto;
135
+ border-radius: 999px;
136
+ background: var(--border-color);
137
+ }
138
+
139
+ .nav-rail-compact-sheet__section {
140
+ display: flex;
141
+ flex-direction: column;
142
+ gap: 8px;
143
+ }
144
+
145
+ .nav-rail-compact-sheet__section-title {
146
+ display: inline-flex;
147
+ align-items: center;
148
+ gap: 6px;
149
+ font-size: 11px;
150
+ font-weight: 600;
151
+ color: var(--sub-text-color);
152
+ }
153
+
154
+ .nav-rail-compact-sheet__section-title-icon {
155
+ font-size: 14px;
156
+ line-height: 1;
157
+ }
158
+
159
+ .nav-rail-compact-sheet__actions {
160
+ display: grid;
161
+ grid-template-columns: repeat(2, minmax(0, 1fr));
162
+ gap: 8px;
163
+ }
164
+
165
+ .nav-rail-compact-sheet__action,
166
+ .nav-rail-compact-sheet__chip {
167
+ min-width: 0;
168
+ min-height: 40px;
169
+ border: 1px solid var(--border-color);
170
+ border-radius: 8px;
171
+ background: var(--sub-bg-color);
172
+ color: var(--text-color);
173
+ transition: background-color .2s ease, border-color .2s ease, color .2s ease;
174
+ }
175
+
176
+ .nav-rail-compact-sheet__action {
177
+ display: inline-flex;
178
+ align-items: center;
179
+ justify-content: center;
180
+ gap: 8px;
181
+ padding: 0 10px;
182
+
183
+ .material-symbols-rounded {
184
+ font-size: 18px;
185
+ line-height: 1;
186
+ }
187
+
188
+ > span:last-child {
189
+ min-width: 0;
190
+ overflow: hidden;
191
+ text-overflow: ellipsis;
192
+ white-space: nowrap;
193
+ font-size: 12px;
194
+ }
195
+ }
196
+
197
+ .nav-rail-compact-sheet__chips {
198
+ display: flex;
199
+ flex-wrap: wrap;
200
+ gap: 8px;
201
+ }
202
+
203
+ .nav-rail-compact-sheet__segmented {
204
+ display: grid;
205
+ grid-template-columns: repeat(3, minmax(0, 1fr));
206
+ gap: 0;
207
+ width: 100%;
208
+ border: 1px solid var(--border-color);
209
+ border-radius: 8px;
210
+ overflow: hidden;
211
+ background: var(--sub-bg-color);
212
+ }
213
+
214
+ .nav-rail-compact-sheet__chip {
215
+ padding: 0 12px;
216
+ font-size: 12px;
217
+ }
218
+
219
+ .nav-rail-compact-sheet__segment {
220
+ min-width: 0;
221
+ min-height: 44px;
222
+ padding: 8px 6px;
223
+ border: 0;
224
+ border-right: 1px solid var(--border-color);
225
+ background: transparent;
226
+ color: var(--text-color);
227
+ display: flex;
228
+ flex-direction: column;
229
+ align-items: center;
230
+ justify-content: center;
231
+ gap: 4px;
232
+ transition: background-color .2s ease, color .2s ease;
233
+
234
+ &:last-child {
235
+ border-right: 0;
236
+ }
237
+
238
+ > span:last-child {
239
+ min-width: 0;
240
+ font-size: 11px;
241
+ line-height: 1.2;
242
+ text-align: center;
243
+ }
244
+ }
245
+
246
+ .nav-rail-compact-sheet__segment-icon {
247
+ font-size: 18px;
248
+ line-height: 1;
249
+ }
250
+
251
+ .nav-rail-compact-sheet__select-shell {
252
+ min-width: 0;
253
+ min-height: 44px;
254
+ padding: 0 12px;
255
+ border: 1px solid var(--border-color);
256
+ border-radius: 8px;
257
+ background: var(--sub-bg-color);
258
+ display: flex;
259
+ align-items: center;
260
+ gap: 10px;
261
+ }
262
+
263
+ .nav-rail-compact-sheet__select-icon,
264
+ .nav-rail-compact-sheet__select-chevron {
265
+ font-size: 18px;
266
+ line-height: 1;
267
+ color: var(--sub-text-color);
268
+ flex-shrink: 0;
269
+ }
270
+
271
+ .nav-rail-compact-sheet__select {
272
+ flex: 1;
273
+ min-width: 0;
274
+ height: 44px;
275
+ border: 0;
276
+ background: transparent;
277
+ color: var(--text-color);
278
+ display: block;
279
+ font-size: 14px;
280
+ line-height: 44px;
281
+ outline: none;
282
+ appearance: none;
283
+ -webkit-appearance: none;
284
+ }
285
+
286
+ .nav-rail-compact-sheet__select-chevron {
287
+ pointer-events: none;
288
+ }
289
+
290
+ .nav-rail-compact-sheet__action.is-active,
291
+ .nav-rail-compact-sheet__chip.is-active,
292
+ .nav-rail-compact-sheet__segment.is-active {
293
+ border-color: var(--nav-active-text, #2563eb);
294
+ background: var(--nav-active-bg, #eff6ff);
295
+ color: var(--nav-active-text, #2563eb);
296
+ }
297
+
50
298
  .nav-menu-icon {
51
299
  font-size: 16px;
52
300
  display: inline-flex;
@@ -7,133 +7,106 @@ import React from 'react'
7
7
  import { useTranslation } from 'react-i18next'
8
8
  import { useLocation, useNavigate } from 'react-router-dom'
9
9
 
10
+ import { useResponsiveLayout } from '#~/hooks/use-responsive-layout'
10
11
  import { themeAtom } from '../store'
12
+ import { NavRailCompact } from './NavRailCompact'
13
+ import {
14
+ buildCompactLanguageActions,
15
+ buildCompactMoreActions,
16
+ buildCompactThemeActions
17
+ } from './nav-rail-compact-config'
18
+ import { buildLanguageItems, buildNavItems, buildThemeItems } from './nav-rail-items'
11
19
 
12
20
  export function NavRail({
13
- collapsed,
14
- onToggleCollapse
21
+ ariaHidden = false,
22
+ isCompactLayout = false,
23
+ onOpenSidebar,
24
+ showSidebar = false
15
25
  }: {
16
- collapsed?: boolean
17
- onToggleCollapse?: () => void
26
+ ariaHidden?: boolean
27
+ isCompactLayout?: boolean
28
+ onOpenSidebar?: () => void
29
+ showSidebar?: boolean
18
30
  }) {
19
31
  const { t, i18n } = useTranslation()
20
32
  const [themeMode, setThemeMode] = useAtom(themeAtom)
21
33
  const navigate = useNavigate()
22
34
  const location = useLocation()
35
+ const { isTouchInteraction } = useResponsiveLayout()
23
36
 
24
37
  const currentPath = location.pathname
38
+ const resolveTooltipTitle = (title: string) => isTouchInteraction ? undefined : title
25
39
 
26
- const langItems: MenuProps['items'] = React.useMemo(() => [
27
- {
28
- key: 'zh',
29
- label: '简体中文',
30
- icon: i18n.language.startsWith('zh')
31
- ? (
32
- <span className='material-symbols-rounded nav-menu-icon active'>check</span>
33
- )
34
- : <div className='nav-menu-icon-placeholder' />,
35
- onClick: () => {
36
- void i18n.changeLanguage('zh')
37
- }
38
- },
39
- {
40
- key: 'en',
41
- label: 'English',
42
- icon: i18n.language.startsWith('en')
43
- ? (
44
- <span className='material-symbols-rounded nav-menu-icon active'>check</span>
45
- )
46
- : <div className='nav-menu-icon-placeholder' />,
47
- onClick: () => {
48
- void i18n.changeLanguage('en')
49
- }
50
- }
51
- ], [i18n.language])
40
+ const langItems: MenuProps['items'] = React.useMemo(() =>
41
+ buildLanguageItems({
42
+ currentLanguage: i18n.language,
43
+ onChangeLanguage: (language) => i18n.changeLanguage(language)
44
+ }), [i18n.language])
52
45
 
53
- const themeItems: MenuProps['items'] = React.useMemo(() => [
54
- {
55
- key: 'light',
56
- label: t('common.themeLight'),
57
- icon: themeMode === 'light'
58
- ? <span className='material-symbols-rounded nav-menu-icon active'>check</span>
59
- : <span className='material-symbols-rounded nav-menu-icon'>light_mode</span>,
60
- onClick: () => {
61
- setThemeMode('light')
62
- localStorage.setItem('theme', 'light')
63
- }
64
- },
65
- {
66
- key: 'dark',
67
- label: t('common.themeDark'),
68
- icon: themeMode === 'dark'
69
- ? <span className='material-symbols-rounded nav-menu-icon active'>check</span>
70
- : <span className='material-symbols-rounded nav-menu-icon'>dark_mode</span>,
71
- onClick: () => {
72
- setThemeMode('dark')
73
- localStorage.setItem('theme', 'dark')
74
- }
75
- },
76
- {
77
- key: 'system',
78
- label: t('common.themeSystem'),
79
- icon: themeMode === 'system'
80
- ? <span className='material-symbols-rounded nav-menu-icon active'>check</span>
81
- : <span className='material-symbols-rounded nav-menu-icon'>desktop_windows</span>,
82
- onClick: () => {
83
- setThemeMode('system')
84
- localStorage.setItem('theme', 'system')
46
+ const themeItems: MenuProps['items'] = React.useMemo(() =>
47
+ buildThemeItems({
48
+ setThemeMode,
49
+ t,
50
+ themeMode
51
+ }), [setThemeMode, t, themeMode])
52
+
53
+ const navItems = React.useMemo(() => buildNavItems({ currentPath, t }), [currentPath, t])
54
+
55
+ const compactMoreActions = React.useMemo(() =>
56
+ buildCompactMoreActions({
57
+ currentPath,
58
+ navigate,
59
+ onOpenSidebar,
60
+ showSidebar,
61
+ t
62
+ }), [currentPath, navigate, onOpenSidebar, showSidebar, t])
63
+
64
+ const compactThemeActions = React.useMemo(() =>
65
+ buildCompactThemeActions({
66
+ setThemeMode,
67
+ t,
68
+ themeMode
69
+ }), [setThemeMode, t, themeMode])
70
+
71
+ const compactLanguageActions = React.useMemo(() =>
72
+ buildCompactLanguageActions({
73
+ currentLanguage: i18n.language,
74
+ onChangeLanguage: (language) => {
75
+ void i18n.changeLanguage(language)
85
76
  }
86
- }
87
- ], [themeMode, t, setThemeMode])
77
+ }), [i18n.language])
78
+
79
+ const handleNavClick = (_key: string, path: string) => {
80
+ void navigate(path)
81
+ }
88
82
 
89
- const navItems = React.useMemo(() => [
90
- {
91
- key: 'sessions',
92
- icon: 'chat_bubble',
93
- label: t('common.sessions'),
94
- path: '/',
95
- active: currentPath === '/' || currentPath.startsWith('/session/')
96
- },
97
- {
98
- key: 'knowledge',
99
- icon: 'library_books',
100
- label: t('common.knowledgeBase'),
101
- path: '/knowledge',
102
- active: currentPath === '/knowledge'
103
- },
104
- {
105
- key: 'automation',
106
- icon: 'schedule',
107
- label: t('common.automation'),
108
- path: '/automation',
109
- active: currentPath === '/automation'
110
- },
111
- {
112
- key: 'benchmark',
113
- icon: 'speed',
114
- label: t('common.benchmark'),
115
- path: '/benchmark',
116
- active: currentPath === '/benchmark'
117
- },
118
- {
119
- key: 'archive',
120
- icon: 'archive',
121
- label: t('common.archivedSessions'),
122
- path: '/archive',
123
- active: currentPath === '/archive'
124
- }
125
- ], [currentPath, t])
83
+ if (isCompactLayout) {
84
+ return (
85
+ <NavRailCompact
86
+ ariaHidden={ariaHidden}
87
+ currentPath={currentPath}
88
+ languageActions={compactLanguageActions}
89
+ languageLabel={t('common.language')}
90
+ moreLabel={t('common.moreActions')}
91
+ moreSheetActions={compactMoreActions}
92
+ navItems={navItems}
93
+ themeActions={compactThemeActions}
94
+ themeLabel={t('common.theme')}
95
+ onNavClick={handleNavClick}
96
+ />
97
+ )
98
+ }
126
99
 
127
100
  return (
128
- <div className='nav-rail'>
101
+ <div className='nav-rail' aria-hidden={ariaHidden || undefined}>
129
102
  <div className='nav-rail-top'>
130
103
  {navItems.map(item => (
131
- <Tooltip key={item.key} title={item.label} placement='right'>
104
+ <Tooltip key={item.key} title={resolveTooltipTitle(item.label)} placement='right'>
132
105
  <span>
133
106
  <Button
134
107
  type='text'
135
108
  className={`nav-item ${item.active ? 'active' : ''}`}
136
- onClick={() => void navigate(item.path)}
109
+ onClick={() => handleNavClick(item.key, item.path)}
137
110
  icon={<span className='material-symbols-rounded'>{item.icon}</span>}
138
111
  />
139
112
  </span>
@@ -141,7 +114,7 @@ export function NavRail({
141
114
  ))}
142
115
  </div>
143
116
  <div className='nav-rail-bottom'>
144
- <Tooltip title={t('common.theme')} placement='right'>
117
+ <Tooltip title={resolveTooltipTitle(t('common.theme'))} placement='right'>
145
118
  <span>
146
119
  <Dropdown
147
120
  menu={{
@@ -162,7 +135,7 @@ export function NavRail({
162
135
  </Dropdown>
163
136
  </span>
164
137
  </Tooltip>
165
- <Tooltip title={t('common.language')} placement='right'>
138
+ <Tooltip title={resolveTooltipTitle(t('common.language'))} placement='right'>
166
139
  <span>
167
140
  <Dropdown
168
141
  menu={{
@@ -179,7 +152,7 @@ export function NavRail({
179
152
  </Dropdown>
180
153
  </span>
181
154
  </Tooltip>
182
- <Tooltip title={t('common.settings')} placement='right'>
155
+ <Tooltip title={resolveTooltipTitle(t('common.settings'))} placement='right'>
183
156
  <span>
184
157
  <Button
185
158
  type='text'
@@ -0,0 +1,107 @@
1
+ import { Button } from 'antd'
2
+ import { useEffect, useState } from 'react'
3
+
4
+ import { NavRailCompactMoreSheet } from './NavRailCompactMoreSheet'
5
+
6
+ export interface NavRailCompactItem {
7
+ active: boolean
8
+ icon: string
9
+ key: string
10
+ label: string
11
+ path: string
12
+ }
13
+
14
+ export interface NavRailCompactMoreAction {
15
+ active?: boolean
16
+ icon: string
17
+ key: string
18
+ label: string
19
+ onSelect: () => void
20
+ }
21
+
22
+ export interface NavRailCompactChoiceAction {
23
+ active: boolean
24
+ icon?: string
25
+ key: string
26
+ label: string
27
+ onSelect: () => void
28
+ }
29
+
30
+ export function NavRailCompact({
31
+ ariaHidden = false,
32
+ currentPath,
33
+ languageActions,
34
+ languageLabel,
35
+ moreLabel,
36
+ moreSheetActions,
37
+ navItems,
38
+ themeActions,
39
+ themeLabel,
40
+ onNavClick
41
+ }: {
42
+ ariaHidden?: boolean
43
+ currentPath: string
44
+ languageActions: NavRailCompactChoiceAction[]
45
+ languageLabel: string
46
+ moreLabel: string
47
+ moreSheetActions: NavRailCompactMoreAction[]
48
+ navItems: NavRailCompactItem[]
49
+ themeActions: NavRailCompactChoiceAction[]
50
+ themeLabel: string
51
+ onNavClick: (key: string, path: string) => void
52
+ }) {
53
+ const [isMoreSheetOpen, setIsMoreSheetOpen] = useState(false)
54
+
55
+ useEffect(() => {
56
+ setIsMoreSheetOpen(false)
57
+ }, [currentPath])
58
+
59
+ useEffect(() => {
60
+ if (ariaHidden) {
61
+ setIsMoreSheetOpen(false)
62
+ }
63
+ }, [ariaHidden])
64
+
65
+ return (
66
+ <div className='nav-rail nav-rail--compact' aria-hidden={ariaHidden || undefined}>
67
+ <div className='nav-rail-compact-list'>
68
+ {navItems.map((item) => (
69
+ <Button
70
+ key={item.key}
71
+ type='text'
72
+ className={`nav-item nav-item--compact ${item.active ? 'active' : ''}`}
73
+ title={item.label}
74
+ aria-label={item.label}
75
+ onClick={() => {
76
+ setIsMoreSheetOpen(false)
77
+ onNavClick(item.key, item.path)
78
+ }}
79
+ icon={<span className='material-symbols-rounded'>{item.icon}</span>}
80
+ />
81
+ ))}
82
+
83
+ <Button
84
+ type='text'
85
+ className={`nav-item nav-item--compact ${isMoreSheetOpen || currentPath === '/config' ? 'active' : ''}`}
86
+ title={moreLabel}
87
+ aria-expanded={isMoreSheetOpen}
88
+ aria-haspopup='dialog'
89
+ aria-label={moreLabel}
90
+ onClick={() => setIsMoreSheetOpen((prev) => !prev)}
91
+ icon={<span className='material-symbols-rounded'>more_horiz</span>}
92
+ />
93
+ </div>
94
+
95
+ <NavRailCompactMoreSheet
96
+ actions={moreSheetActions}
97
+ isOpen={isMoreSheetOpen}
98
+ languageActions={languageActions}
99
+ languageLabel={languageLabel}
100
+ moreLabel={moreLabel}
101
+ onClose={() => setIsMoreSheetOpen(false)}
102
+ themeActions={themeActions}
103
+ themeLabel={themeLabel}
104
+ />
105
+ </div>
106
+ )
107
+ }