@nextclaw/ui 0.26.2 → 0.26.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/.vite/manifest.json +366 -365
  3. package/dist/assets/{account-panel-ZM2qzKF4.js → account-panel-DVi_jhkG.js} +1 -1
  4. package/dist/assets/{api-Cjq-o1VN.js → api-BZvNpFOS.js} +2 -2
  5. package/dist/assets/app-presenter-provider-BcYL-VNe.js +124 -0
  6. package/dist/assets/{appearance-settings-page-B4zouKzg.js → appearance-settings-page-AZNBzLmT.js} +1 -1
  7. package/dist/assets/{book-open-AteA89HX.js → book-open-CmRdT3N1.js} +1 -1
  8. package/dist/assets/card-CdRBL1E0.js +1 -0
  9. package/dist/assets/{channels-list-page-fj8kMo-T.js → channels-list-page-eZN74FN3.js} +2 -2
  10. package/dist/assets/{circle-dashed-LSYZTzM7.js → circle-dashed-HOgt3gIJ.js} +1 -1
  11. package/dist/assets/{client-DudCRJw4.js → client-DKKbdJ6Q.js} +1 -1
  12. package/dist/assets/config-split-page-BA3V6b3Q.js +1 -0
  13. package/dist/assets/{confirm-dialog-DShT64F6.js → confirm-dialog-8vqYZ0wy.js} +1 -1
  14. package/dist/assets/context-menu-DHVVdHzN.js +1 -0
  15. package/dist/assets/{createLucideIcon-D7hvIHV-.js → createLucideIcon-DE0sB9Nu.js} +1 -1
  16. package/dist/assets/{desktop-capabilities-page-CzqzFZUY.js → desktop-capabilities-page-B9-B9k1A.js} +1 -1
  17. package/dist/assets/{desktop-update-config-CgeQ0Ffo.js → desktop-update-config-Cfr3IRUe.js} +1 -1
  18. package/dist/assets/{dialog-C7glmAQJ.js → dialog-BUfWO8hr.js} +2 -2
  19. package/dist/assets/{doc-browser-context-BlhBAOLH.js → doc-browser-context-ClLgMbxd.js} +1 -1
  20. package/dist/assets/doc-browser-w8q1j0jL.js +1 -0
  21. package/dist/assets/{download-BYgECE0n.js → download-CKqS1Ksj.js} +1 -1
  22. package/dist/assets/{es2015-CsjAAQ6X.js → es2015-BiB05Sav.js} +1 -1
  23. package/dist/assets/{extensions-qYL-NpL3.js → extensions-vPD4dGqt.js} +1 -1
  24. package/dist/assets/{eye-BBuTzJ53.js → eye-bKzylu3p.js} +1 -1
  25. package/dist/assets/{form-actions-CLGWO52v.js → form-actions-CCoxz33Q.js} +1 -1
  26. package/dist/assets/{i18n-qBGEbcW6.js → i18n-OGmF0Ws_.js} +2 -2
  27. package/dist/assets/{keyboard-shortcuts-settings-page-B-wK_6zG.js → keyboard-shortcuts-settings-page-D8rosOVh.js} +1 -1
  28. package/dist/assets/loader-circle-Clq1Gtb1.js +1 -0
  29. package/dist/assets/{login-page-Cd84lpVV.js → login-page-BT3GV3Sb.js} +1 -1
  30. package/dist/assets/login-page-DKId3By8.js +1 -0
  31. package/dist/assets/main-bEWCGDHr.js +2 -0
  32. package/dist/assets/main-i18n-catalog.config-Bpu5GcwF.js +1 -0
  33. package/dist/assets/main-kqMRTwOs.css +1 -0
  34. package/dist/assets/mcp-marketplace-page-CZIP6j3L.js +1 -0
  35. package/dist/assets/{model-config-page-D0DQlSDa.js → model-config-page-D21a-BO0.js} +1 -1
  36. package/dist/assets/{navigation-link-32iM1-e6.js → navigation-link-DC-Pku0Y.js} +1 -1
  37. package/dist/assets/panel-app-BYfQu_TS.js +1 -0
  38. package/dist/assets/panel-app-i18n-catalog.config-D44qmtfk.js +1 -0
  39. package/dist/assets/panelStandalone-BRg7B1EI.css +1 -0
  40. package/dist/assets/{panelStandalone-C9EKaApN.js → panelStandalone-CX8X2hjh.js} +2 -2
  41. package/dist/assets/{privacy-settings-page-Bxxx12OO.js → privacy-settings-page-e0LFHZJm.js} +1 -1
  42. package/dist/assets/projects-Rki7Fmth.js +1 -0
  43. package/dist/assets/provider-models-DFQgF4hS.js +1 -0
  44. package/dist/assets/provider-scoped-model-input-DaONL0j_.js +1 -0
  45. package/dist/assets/providers-config-page-CEOhQlMe.js +1 -0
  46. package/dist/assets/{puzzle-CWHfFyYN.js → puzzle-D_TiFXOv.js} +1 -1
  47. package/dist/assets/{pwa-CiGUjpcd.js → pwa-C9ac_1dg.js} +1 -1
  48. package/dist/assets/{refresh-cw-y3L6PyLt.js → refresh-cw-BG8VfcdA.js} +1 -1
  49. package/dist/assets/remote-DkSx5x4R.js +1 -0
  50. package/dist/assets/{rotate-cw-CNE9qSHi.js → rotate-cw-DPEegUU2.js} +1 -1
  51. package/dist/assets/{runtime-config-page-5o98T-TD.js → runtime-config-page-DDT1dVLt.js} +1 -1
  52. package/dist/assets/{save-B0p5a0ET.js → save-CPlctBjT.js} +1 -1
  53. package/dist/assets/{search-config-page-CpGcnIzi.js → search-config-page-CDwmd6eX.js} +1 -1
  54. package/dist/assets/{secrets-config-page-C4VTiW3r.js → secrets-config-page-1OvgmwPv.js} +1 -1
  55. package/dist/assets/security-config-Pv4CM-kw.js +1 -0
  56. package/dist/assets/{select-CctTN205.js → select-Y9IEbx9x.js} +1 -1
  57. package/dist/assets/service-apps-panel-DPrLeF3N.js +1 -0
  58. package/dist/assets/{settings-2-EPflrNk6.js → settings-2-CrGx9_De.js} +1 -1
  59. package/dist/assets/{status-dot-CensgJZC.js → status-dot-Cb8ewlUr.js} +1 -1
  60. package/dist/assets/{tag-chip-Bjzb4-qW.js → tag-chip-D-6aPuuh.js} +1 -1
  61. package/dist/assets/{theme-provider-hlle7Skk.js → theme-provider-BjF1Eowc.js} +1 -1
  62. package/dist/assets/{trash-2-C5KH5Rw9.js → trash-2-DER2EJKK.js} +1 -1
  63. package/dist/assets/{use-config-CPl_F79t.js → use-config-BM5jC65L.js} +1 -1
  64. package/dist/assets/{use-desktop-capabilities-CEg9-DrQ.js → use-desktop-capabilities-ezKJwKqg.js} +1 -1
  65. package/dist/assets/{use-viewport-layout-CPZUmTPi.js → use-viewport-layout-vmbQUNT6.js} +1 -1
  66. package/dist/assets/x-DSz9cGhy.js +1 -0
  67. package/dist/index.html +34 -34
  68. package/dist/panel-standalone.html +11 -11
  69. package/package.json +3 -3
  70. package/src/app/components/layout/__tests__/sidebar.layout.test.tsx +2 -2
  71. package/src/app/components/layout/page-layout.tsx +5 -2
  72. package/src/app/components/layout/sidebar-rail.styles.ts +3 -3
  73. package/src/app/configs/__tests__/app-navigation.config.test.ts +10 -0
  74. package/src/app/configs/app-navigation.config.ts +6 -2
  75. package/src/app/styles/charcoal-theme.css +0 -3
  76. package/src/app/styles/design-system.css +18 -6
  77. package/src/app/styles/island-theme.css +2 -15
  78. package/src/features/agents/components/agent-details-dialog.tsx +1 -1
  79. package/src/features/agents/components/agents-page.tsx +5 -3
  80. package/src/features/app-data/components/app-data-removal-choice.tsx +1 -1
  81. package/src/features/apps/components/app-package-card.tsx +7 -6
  82. package/src/features/channels/pages/channels-list-page.tsx +1 -1
  83. package/src/features/chat/components/chat-sidebar-list-mode-switch.tsx +1 -1
  84. package/src/features/chat/components/conversation/__tests__/chat-conversation-header-section.test.tsx +28 -16
  85. package/src/features/chat/components/conversation/chat-conversation-content.tsx +8 -2
  86. package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +3 -3
  87. package/src/features/chat/components/conversation/chat-conversation-header.tsx +4 -4
  88. package/src/features/chat/components/layout/__tests__/chat-sidebar-session-area.test.tsx +6 -4
  89. package/src/features/chat/components/layout/__tests__/chat-sidebar-toolbar.test.tsx +22 -1
  90. package/src/features/chat/components/layout/chat-page-shell.tsx +1 -1
  91. package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +10 -14
  92. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +50 -12
  93. package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +4 -4
  94. package/src/features/chat/components/layout/chat-sidebar.tsx +2 -2
  95. package/src/features/chat/features/conversation/components/session-queued-input-rows.tsx +1 -1
  96. package/src/features/chat/features/message/components/chat-message-list.container.tsx +12 -1
  97. package/src/features/chat/features/message/components/chat-tool-call-stress-harness.tsx +32 -2
  98. package/src/features/chat/features/message/hooks/__tests__/use-chat-message-virtualizer.test.tsx +7 -5
  99. package/src/features/chat/features/message/hooks/use-chat-message-virtualizer.ts +7 -3
  100. package/src/features/chat/features/session/components/__tests__/chat-sidebar-project-groups.test.tsx +1 -1
  101. package/src/features/chat/features/session/components/chat-mobile-session-row.tsx +2 -2
  102. package/src/features/chat/features/session/components/chat-sidebar-context-card.tsx +1 -1
  103. package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +1 -1
  104. package/src/features/chat/features/session/components/chat-sidebar-session-item.tsx +7 -5
  105. package/src/features/chat/features/session/components/chat-sidebar-session-list.tsx +45 -10
  106. package/src/features/chat/features/session/components/session-header/__tests__/chat-session-header-actions.test.tsx +1 -1
  107. package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +3 -5
  108. package/src/features/chat/features/session/components/session-header/chat-session-header-menu-item.tsx +4 -3
  109. package/src/features/chat/features/session/components/session-header/chat-session-more-actions-menu.tsx +3 -0
  110. package/src/features/chat/features/session/components/session-header/chat-session-switcher-groups.tsx +6 -6
  111. package/src/features/chat/features/session/components/session-header/chat-session-title-switcher.tsx +6 -5
  112. package/src/features/chat/features/session-type/components/chat-session-type-option-item.tsx +1 -1
  113. package/src/features/chat/features/welcome/components/chat-welcome-agent-picker.tsx +0 -1
  114. package/src/features/chat/features/welcome/components/chat-welcome-project-picker.tsx +1 -1
  115. package/src/features/chat/features/welcome/components/chat-welcome-prompt-suggestions.tsx +1 -1
  116. package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +1 -1
  117. package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumb-browser.tsx +2 -2
  118. package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +2 -2
  119. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +1 -1
  120. package/src/features/chat/features/workspace/components/child-sessions/chat-session-child-sessions.tsx +2 -2
  121. package/src/features/chat/features/workspace/components/file-content-preview/workspace-spreadsheet-preview.tsx +2 -2
  122. package/src/features/chat/features/workspace/components/overview/chat-session-continuous-attention.tsx +3 -3
  123. package/src/features/chat/features/workspace/components/overview/chat-session-token-usage.tsx +1 -1
  124. package/src/features/chat/features/workspace/components/project-files/workspace-directory-tree.tsx +4 -3
  125. package/src/features/chat/features/workspace/components/project-files/workspace-new-folder-tree-item.tsx +2 -1
  126. package/src/features/chat/features/workspace/components/project-files/workspace-project-files-toolbar.tsx +3 -1
  127. package/src/features/chat/features/workspace/components/session-cron-job-content.tsx +3 -3
  128. package/src/features/chat/features/workspace/components/workspace-file-content-preview.tsx +2 -2
  129. package/src/features/chat/features/workspace/components/workspace-markdown-outline.tsx +1 -1
  130. package/src/features/cron/components/cron-config.tsx +3 -2
  131. package/src/features/cron/components/cron-job-detail-dialog.tsx +1 -1
  132. package/src/features/cron/components/cron-job-row.tsx +7 -7
  133. package/src/features/cron/components/cron-task-discovery.tsx +1 -1
  134. package/src/features/inbox/components/inbox-delivery-content.tsx +1 -1
  135. package/src/features/inbox/pages/inbox-page.tsx +25 -29
  136. package/src/features/marketplace/components/curated-shelves/marketplace-curated-shelves.tsx +2 -2
  137. package/src/features/marketplace/components/curated-shelves/marketplace-shelf-card.tsx +2 -2
  138. package/src/features/marketplace/components/marketplace-list-card.tsx +4 -4
  139. package/src/features/marketplace/components/marketplace-page-parts.tsx +4 -3
  140. package/src/features/marketplace/components/marketplace-page.tsx +4 -4
  141. package/src/features/marketplace/components/mcp/mcp-marketplace-card.tsx +2 -2
  142. package/src/features/marketplace/components/mcp/mcp-marketplace-page.tsx +3 -3
  143. package/src/features/panel-apps/components/panel-app-list-item.tsx +3 -3
  144. package/src/features/panel-apps/components/panel-app-open-standalone-menu-item.tsx +3 -1
  145. package/src/features/projects/components/project-overview.tsx +1 -1
  146. package/src/features/projects/pages/project-home-page.tsx +11 -2
  147. package/src/features/projects/pages/projects-page.test.tsx +4 -2
  148. package/src/features/pwa/components/pwa-install-entry.tsx +1 -1
  149. package/src/features/right-panel-resources/components/__tests__/page-resource-sidebar-nav.test.tsx +9 -1
  150. package/src/features/right-panel-resources/components/page-resource-sidebar-nav.tsx +1 -1
  151. package/src/features/right-panel-resources/components/right-panel-resource-home-page.tsx +1 -1
  152. package/src/features/service-apps/components/service-action-row.tsx +3 -3
  153. package/src/features/service-apps/components/service-app-list-item.tsx +4 -4
  154. package/src/features/service-apps/components/service-apps-panel.tsx +1 -1
  155. package/src/features/settings/components/config/provider-model-list.tsx +5 -5
  156. package/src/features/settings/components/config/provider-model-suggestions-panel.tsx +4 -4
  157. package/src/features/settings/components/config/provider-pill-selector.tsx +1 -1
  158. package/src/features/settings/pages/appearance-settings-page.tsx +2 -2
  159. package/src/features/settings/pages/providers-config-page.tsx +6 -6
  160. package/src/features/side-dock/components/side-dock.tsx +4 -4
  161. package/src/index.css +4 -0
  162. package/src/platforms/desktop/components/desktop-window-chrome.tsx +1 -1
  163. package/src/platforms/mobile/components/mobile-app-shell.tsx +1 -1
  164. package/src/platforms/mobile/components/mobile-bottom-nav.tsx +10 -9
  165. package/src/platforms/mobile/components/mobile-settings-shell.tsx +24 -23
  166. package/src/platforms/mobile/components/mobile-topbar.tsx +10 -11
  167. package/src/shared/components/common/brand-header.tsx +1 -1
  168. package/src/shared/components/common/searchable-model-input.tsx +2 -2
  169. package/src/shared/components/config-split-page.tsx +3 -3
  170. package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +34 -2
  171. package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +38 -7
  172. package/src/shared/components/doc-browser/doc-browser.tsx +5 -1
  173. package/src/shared/components/path-picker/server-path-picker-locations.tsx +1 -1
  174. package/src/shared/components/settings/settings-page.tsx +1 -1
  175. package/src/shared/components/ui/actions/__tests__/icon-action-button.test.tsx +5 -5
  176. package/src/shared/components/ui/actions/action-feedback.ts +8 -0
  177. package/src/shared/components/ui/actions/icon-action-button.tsx +13 -12
  178. package/src/shared/components/ui/button.tsx +3 -3
  179. package/src/shared/components/ui/card.tsx +1 -1
  180. package/src/shared/components/ui/context-menu/context-menu-items.tsx +6 -5
  181. package/src/shared/components/ui/dialog.tsx +4 -3
  182. package/src/shared/components/ui/input.tsx +7 -2
  183. package/src/shared/components/ui/overlays/sheet.tsx +1 -1
  184. package/src/shared/components/ui/popover.tsx +1 -1
  185. package/src/shared/components/ui/select.tsx +3 -2
  186. package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +8 -6
  187. package/src/shared/components/ui/tabs.tsx +3 -3
  188. package/src/shared/components/ui/textarea.tsx +1 -0
  189. package/src/shared/components/workbench/workbench-surface-toolbar.tsx +3 -4
  190. package/src/shared/components/workbench/workbench-surface.tsx +2 -2
  191. package/src/shared/lib/i18n/locales/en-US/agents.json +2 -0
  192. package/src/shared/lib/i18n/locales/en-US/core.json +1 -0
  193. package/src/shared/lib/i18n/locales/en-US/desktop-update.json +1 -1
  194. package/src/shared/lib/i18n/locales/zh-CN/agents.json +2 -0
  195. package/src/shared/lib/i18n/locales/zh-CN/core.json +1 -0
  196. package/src/shared/lib/i18n/locales/zh-CN/desktop-update.json +1 -1
  197. package/dist/assets/app-presenter-provider-C02YPoMr.js +0 -124
  198. package/dist/assets/card-BLXvBstA.js +0 -1
  199. package/dist/assets/config-split-page-G7Kt2BnV.js +0 -1
  200. package/dist/assets/context-menu-rd7b_kVD.js +0 -1
  201. package/dist/assets/doc-browser-dBiR9Qi0.js +0 -1
  202. package/dist/assets/loader-circle-BA7EMkih.js +0 -1
  203. package/dist/assets/login-page-VdMyNkFf.js +0 -1
  204. package/dist/assets/main-CR0SrTBf.js +0 -2
  205. package/dist/assets/main-DXH6EdXI.css +0 -1
  206. package/dist/assets/main-i18n-catalog.config-Btp_OowF.js +0 -1
  207. package/dist/assets/mcp-marketplace-page-jacRwiI-.js +0 -1
  208. package/dist/assets/panel-app-CC0bVSu4.js +0 -1
  209. package/dist/assets/panel-app-i18n-catalog.config-LUSBp5Ce.js +0 -1
  210. package/dist/assets/panelStandalone-Y91OJkgV.css +0 -1
  211. package/dist/assets/projects-D56yAPNT.js +0 -1
  212. package/dist/assets/provider-models-C3frdXeW.js +0 -1
  213. package/dist/assets/provider-scoped-model-input-CYetrPYZ.js +0 -1
  214. package/dist/assets/providers-config-page-DESB1h8g.js +0 -1
  215. package/dist/assets/remote-DiGFV8nP.js +0 -1
  216. package/dist/assets/security-config-C5-RQVpS.js +0 -1
  217. package/dist/assets/service-apps-panel-CKE5HKNY.js +0 -1
  218. package/dist/assets/x--xxUvHKW.js +0 -1
@@ -6,6 +6,7 @@ import {
6
6
  TooltipTrigger,
7
7
  } from '@/shared/components/ui/tooltip';
8
8
  import { cn } from '@/shared/lib/utils';
9
+ import { ACTION_FEEDBACK } from './action-feedback';
9
10
 
10
11
  type IconActionButtonSize = 'sm' | 'md' | 'lg';
11
12
  type IconActionButtonTone = 'default' | 'surface' | 'strong';
@@ -17,7 +18,7 @@ type IconActionButtonProps = Omit<
17
18
  icon: React.ReactNode;
18
19
  label: string;
19
20
  size?: IconActionButtonSize;
20
- /** default: global interaction hover. surface: relative feedback on the current surface. strong: denser feedback for nested hover surfaces. */
21
+ /** @deprecated All neutral icon actions now share the theme feedback color. */
21
22
  tone?: IconActionButtonTone;
22
23
  tooltip?: string | false | null;
23
24
  tooltipSide?: 'top' | 'right' | 'bottom' | 'left';
@@ -29,14 +30,9 @@ const SIZE_CLASS: Record<IconActionButtonSize, string> = {
29
30
  lg: 'h-8 w-8 rounded-lg p-1.5',
30
31
  };
31
32
 
32
- const TONE_CLASS: Record<IconActionButtonTone, string> = {
33
- default:
34
- 'text-muted-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground disabled:text-muted-foreground/45 disabled:hover:bg-transparent disabled:hover:text-muted-foreground/45',
35
- surface:
36
- 'text-muted-foreground hover:bg-gray-200/60 hover:text-gray-900 active:bg-gray-200/80 disabled:text-muted-foreground/45 disabled:hover:bg-transparent disabled:hover:text-muted-foreground/45',
37
- strong:
38
- 'text-muted-foreground hover:bg-black/10 hover:text-foreground disabled:text-muted-foreground/45 disabled:hover:bg-transparent disabled:hover:text-muted-foreground/45',
39
- };
33
+ export function IconActionGroup({ children, className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
34
+ return <div {...props} className={cn('flex shrink-0 items-center gap-1 max-md:gap-0', className)}>{children}</div>;
35
+ }
40
36
 
41
37
  const IconActionButton = React.forwardRef<HTMLButtonElement, IconActionButtonProps>(
42
38
  (
@@ -60,14 +56,19 @@ const IconActionButton = React.forwardRef<HTMLButtonElement, IconActionButtonPro
60
56
  type="button"
61
57
  disabled={disabled}
62
58
  aria-label={label}
59
+ data-tone={tone}
63
60
  className={cn(
64
- 'inline-flex shrink-0 items-center justify-center transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:cursor-not-allowed',
61
+ 'relative inline-flex shrink-0 items-center justify-center transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:cursor-not-allowed',
65
62
  SIZE_CLASS[size],
66
- TONE_CLASS[tone],
63
+ 'text-muted-foreground hover:text-accent-foreground disabled:text-muted-foreground/45 disabled:hover:text-muted-foreground/45',
64
+ ACTION_FEEDBACK.icon,
65
+ size === 'sm' ? 'max-md:h-8 max-md:w-8' : 'max-md:h-[var(--icon-control-size)] max-md:w-[var(--icon-control-size)]',
66
+ "before:pointer-events-none before:absolute before:inset-0 before:rounded-[inherit] before:transition-colors before:content-[''] max-md:before:inset-auto max-md:before:h-[var(--icon-feedback-size)] max-md:before:w-[var(--icon-feedback-size)]",
67
+ size === 'sm' && 'max-md:before:h-7 max-md:before:w-7',
67
68
  className
68
69
  )}
69
70
  >
70
- {icon}
71
+ <span className="relative inline-flex items-center justify-center">{icon}</span>
71
72
  </button>
72
73
  );
73
74
  const content = tooltip === false ? null : tooltip ?? label;
@@ -7,13 +7,13 @@ const buttonVariants = cva(
7
7
  {
8
8
  variants: {
9
9
  variant: {
10
- default: 'bg-primary text-primary-foreground hover:bg-primary-600 active:bg-primary-700 shadow-sm',
10
+ default: 'bg-primary text-primary-foreground hover:bg-[hsl(var(--primary-hover))] active:bg-[hsl(var(--primary-active))] shadow-sm',
11
11
  destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
12
12
  outline: 'border border-border bg-card text-muted-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground',
13
13
  secondary: 'bg-muted text-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground',
14
14
  ghost: 'text-muted-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground',
15
15
  link: 'text-primary underline-offset-4 hover:underline',
16
- primary: 'bg-primary text-primary-foreground hover:bg-primary-600 active:bg-primary-700 shadow-sm',
16
+ primary: 'bg-primary text-primary-foreground hover:bg-[hsl(var(--primary-hover))] active:bg-[hsl(var(--primary-active))] shadow-sm',
17
17
  subtle: 'bg-muted text-muted-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground',
18
18
  'primary-outline': 'border border-primary/30 text-primary hover:bg-primary hover:text-primary-foreground'
19
19
  },
@@ -42,7 +42,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
42
42
  ({ className, variant, size, ...props }, ref) => {
43
43
  return (
44
44
  <button
45
- className={cn(buttonVariants({ variant, size, className }))}
45
+ className={cn(buttonVariants({ variant, size, className }), size !== 'icon' && 'max-md:min-h-[var(--control-touch-size)]')}
46
46
  ref={ref}
47
47
  {...props}
48
48
  />
@@ -17,7 +17,7 @@ const Card = React.forwardRef<
17
17
  ? 'border-border shadow-card'
18
18
  : 'border-border/75 shadow-none',
19
19
  hover && surface === 'raised' && 'hover:border-primary/25 hover:shadow-card-hover',
20
- hover && surface === 'flat' && 'hover:bg-muted/40',
20
+ hover && surface === 'flat' && 'hover:bg-[var(--interaction-hover)]',
21
21
  className
22
22
  )}
23
23
  {...props}
@@ -2,10 +2,11 @@ import { useCallback, useEffect, useRef, useState, type ReactNode } from "react"
2
2
  import * as Popover from "@radix-ui/react-popover";
3
3
  import { ChevronRight } from "lucide-react";
4
4
  import { cn } from "@/shared/lib/utils";
5
+ import { ACTION_FEEDBACK, ACTION_MENU_ITEM_CLASS } from '@/shared/components/ui/actions/action-feedback';
5
6
  import type { ContextMenuGroup, ContextMenuItem } from "./context-menu";
6
7
 
7
8
  export const CONTEXT_MENU_SURFACE_CLASS =
8
- "w-max min-w-52 max-w-[min(18rem,calc(100vw-16px))] overflow-y-auto rounded-xl border border-border bg-popover p-1 text-popover-foreground shadow-[0_18px_48px_-20px_rgba(15,23,42,0.42)] outline-none";
9
+ "w-max min-w-52 max-w-[min(18rem,calc(100vw-16px))] overflow-y-auto rounded-xl border border-border/40 bg-popover p-1 text-popover-foreground shadow-floating outline-none";
9
10
 
10
11
  function MenuItemContent({ item }: { item: ContextMenuItem }) {
11
12
  return <>
@@ -59,7 +60,7 @@ function ContextSubmenu({ item, open, onOpenChange, onClose, className, children
59
60
  aria-expanded={open}
60
61
  disabled={item.disabled}
61
62
  data-menu-key={item.key}
62
- className={cn(className, open && "bg-muted")}
63
+ className={cn(className, open && "bg-[var(--interaction-hover)]")}
63
64
  onPointerEnter={(event) => {
64
65
  if (event.pointerType === "touch") return;
65
66
  keyboardOpen.current = false;
@@ -151,11 +152,11 @@ export function ContextMenuItems({ groups, onClose }: {
151
152
  }}
152
153
  >
153
154
  {groups.filter((group) => group.items.length).map((group, index) => <div key={group.key} role="group">
154
- {index > 0 ? <div className="my-1 h-px bg-border" /> : null}
155
+ {index > 0 ? <div className="mx-2 my-1 h-px bg-border/50" /> : null}
155
156
  {group.items.map((item) => {
156
157
  const className = cn(
157
- "flex h-8 w-full items-center gap-2 rounded-lg px-2.5 text-left text-[13px] font-medium outline-none transition-colors disabled:pointer-events-none disabled:opacity-45",
158
- item.destructive ? "text-destructive hover:bg-destructive/10 focus-visible:bg-destructive/10" : "text-foreground hover:bg-muted focus-visible:bg-muted",
158
+ ACTION_MENU_ITEM_CLASS,
159
+ item.destructive ? ACTION_FEEDBACK.destructive : `text-foreground ${ACTION_FEEDBACK.item}`,
159
160
  );
160
161
  const content = <MenuItemContent item={item} />;
161
162
  if (item.children) return <ContextSubmenu key={item.key} item={item} open={openKey === item.key}
@@ -40,6 +40,7 @@ const DialogContent = React.forwardRef<
40
40
  data-theme-overlay="dialog"
41
41
  className={cn(
42
42
  "fixed left-[50%] top-[50%] z-[var(--z-modal,10050)] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-2xl border border-border bg-popover p-6 text-popover-foreground shadow-xl duration-base data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
43
+ "max-md:max-w-[calc(100vw-1.5rem)] max-h-[calc(100dvh-1.5rem)] max-md:max-h-[calc(100dvh-env(safe-area-inset-top,0px)-env(safe-area-inset-bottom,0px)-1.5rem)] overflow-y-auto overscroll-contain",
43
44
  className
44
45
  )}
45
46
  {...props}
@@ -48,7 +49,7 @@ const DialogContent = React.forwardRef<
48
49
  }}
49
50
  >
50
51
  {children}
51
- <DialogPrimitive.Close className="absolute right-4 top-4 rounded-lg p-1 opacity-70 transition-all duration-fast hover:bg-[var(--interaction-hover)] hover:text-accent-foreground hover:opacity-100 focus:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:pointer-events-none">
52
+ <DialogPrimitive.Close className="absolute right-1 top-1 flex h-11 w-11 items-center justify-center rounded-lg opacity-70 transition-all duration-fast hover:bg-[var(--interaction-hover)] hover:text-accent-foreground hover:opacity-100 focus:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:pointer-events-none sm:right-4 sm:top-4 sm:h-6 sm:w-6">
52
53
  <X className="h-4 w-4 text-muted-foreground" />
53
54
  <span className="sr-only">Close</span>
54
55
  </DialogPrimitive.Close>
@@ -63,7 +64,7 @@ const DialogHeader = ({
63
64
  }: React.HTMLAttributes<HTMLDivElement>) => (
64
65
  <div
65
66
  className={cn(
66
- "flex flex-col space-y-2 text-center sm:text-left",
67
+ "flex flex-col space-y-2 pr-7 text-left",
67
68
  className
68
69
  )}
69
70
  {...props}
@@ -77,7 +78,7 @@ const DialogFooter = ({
77
78
  }: React.HTMLAttributes<HTMLDivElement>) => (
78
79
  <div
79
80
  className={cn(
80
- "flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-3",
81
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end sm:gap-3",
81
82
  className
82
83
  )}
83
84
  {...props}
@@ -1,15 +1,20 @@
1
1
  import * as React from 'react';
2
2
  import { cn } from '@/shared/lib/utils';
3
3
 
4
- export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
4
+ export type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
5
+ density?: 'default' | 'compact';
6
+ };
5
7
 
6
8
  const Input = React.forwardRef<HTMLInputElement, InputProps>(
7
- ({ className, type, ...props }, ref) => {
9
+ ({ className, density = 'default', type, ...props }, ref) => {
8
10
  return (
9
11
  <input
10
12
  type={type}
11
13
  className={cn(
12
14
  'flex h-9 w-full rounded-xl border border-border/75 bg-card px-3.5 py-2 text-sm text-foreground file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground/55 placeholder:font-normal transition-colors focus:outline-none focus:ring-0 disabled:cursor-not-allowed disabled:opacity-50',
15
+ density === 'default'
16
+ ? 'max-md:min-h-[var(--control-touch-size)] max-md:text-base'
17
+ : 'text-[13px] max-md:min-h-0 max-md:text-[13px]',
13
18
  className
14
19
  )}
15
20
  ref={ref}
@@ -69,7 +69,7 @@ const SheetContent = React.forwardRef<
69
69
  }}
70
70
  >
71
71
  {children}
72
- <SheetPrimitive.Close className="absolute right-4 top-4 rounded-lg p-1.5 text-muted-foreground opacity-75 transition-colors hover:bg-muted hover:text-foreground hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:pointer-events-none">
72
+ <SheetPrimitive.Close className="absolute right-4 top-4 rounded-lg p-1.5 text-muted-foreground opacity-75 transition-colors hover:bg-[var(--interaction-hover)] hover:text-foreground hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:pointer-events-none">
73
73
  <X className="h-4 w-4" />
74
74
  <span className="sr-only">{closeLabel}</span>
75
75
  </SheetPrimitive.Close>
@@ -31,7 +31,7 @@ const PopoverContent = React.forwardRef<
31
31
  align={align}
32
32
  collisionPadding={collisionPadding}
33
33
  className={cn(
34
- 'z-[var(--z-popover,10100)] w-72 overflow-x-hidden overflow-y-auto rounded-2xl border border-border bg-popover p-4 text-popover-foreground shadow-lg animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
34
+ 'z-[var(--z-popover,10100)] w-72 overflow-x-hidden overflow-y-auto rounded-xl border border-border/40 bg-popover p-4 text-popover-foreground shadow-floating animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
35
35
  className,
36
36
  variant === 'menu' && CONTEXT_MENU_SURFACE_CLASS
37
37
  )}
@@ -26,6 +26,7 @@ const SelectTrigger = React.forwardRef<
26
26
  ref={ref}
27
27
  className={cn(
28
28
  "flex h-9 w-full items-center justify-between whitespace-nowrap rounded-xl border border-border/75 bg-card px-3 py-2 text-sm text-foreground ring-offset-background placeholder:text-muted-foreground transition-colors focus:outline-none focus:ring-0 focus:border-border disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
29
+ 'max-md:min-h-[var(--control-touch-size)]',
29
30
  className
30
31
  )}
31
32
  {...props}
@@ -79,7 +80,7 @@ const SelectContent = React.forwardRef<
79
80
  ref={ref}
80
81
  data-theme-overlay="select"
81
82
  className={cn(
82
- "relative z-[var(--z-popover,10100)] flex max-h-96 min-w-[8rem] flex-col overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
83
+ "relative z-[var(--z-popover,10100)] flex max-h-96 min-w-[8rem] flex-col overflow-hidden rounded-xl border border-border/40 bg-popover text-popover-foreground shadow-floating data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
83
84
  position === "popper" &&
84
85
  "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
85
86
  className
@@ -120,7 +121,7 @@ const SelectItem = React.forwardRef<
120
121
  <SelectPrimitive.Item
121
122
  ref={ref}
122
123
  className={cn(
123
- "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-[var(--interaction-hover)]",
124
+ "relative flex max-md:min-h-[var(--control-touch-size)] w-full cursor-default select-none items-center rounded-lg py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-[var(--interaction-hover)] focus:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-[var(--interaction-hover)]",
124
125
  className
125
126
  )}
126
127
  {...props}
@@ -2,6 +2,7 @@ import * as React from "react";
2
2
  import { MoreVertical, X } from "lucide-react";
3
3
  import {
4
4
  IconActionButton,
5
+ IconActionGroup,
5
6
  type IconActionButtonProps,
6
7
  } from "@/shared/components/ui/actions/icon-action-button";
7
8
  import {
@@ -235,9 +236,9 @@ function CompactTabItem({
235
236
  "flex max-w-[180px] cursor-pointer items-center gap-1.5 border-r border-gray-200/70 border-b-2 px-2.5 py-2 transition-colors",
236
237
  "group relative",
237
238
  tab.active
238
- ? (activeTabClassName ?? "border-b-primary bg-white text-gray-900")
239
+ ? (activeTabClassName ?? "border-b-primary bg-[var(--interaction-selection)] text-foreground")
239
240
  : (inactiveTabClassName ??
240
- "border-b-transparent bg-gray-50/85 text-gray-500 hover:bg-gray-100"),
241
+ "border-b-transparent bg-transparent text-muted-foreground hover:bg-[var(--interaction-hover)]"),
241
242
  )}
242
243
  >
243
244
  <CompactTabLabelButton tab={tab} labelClassName={labelClassName} />
@@ -286,7 +287,7 @@ export function CompactTabStrip({
286
287
  >
287
288
  <div
288
289
  className={cn(
289
- "min-w-0 flex-1 overflow-x-auto overflow-y-hidden",
290
+ "flex min-w-0 flex-1 items-stretch overflow-x-auto overflow-y-hidden",
290
291
  scrollClassName,
291
292
  )}
292
293
  onPointerDown={onScrollPointerDown}
@@ -305,13 +306,14 @@ export function CompactTabStrip({
305
306
  ))}
306
307
  </div>
307
308
  </div>
308
- <div
309
- className={cn("flex shrink-0 items-center gap-1", actionsClassName)}
309
+ <IconActionGroup
310
+ className={actionsClassName}
310
311
  data-testid={actionsTestId}
311
312
  onPointerDown={(event) => event.stopPropagation()}
312
313
  >
313
314
  {actions.map((action) => (
314
315
  <IconActionButton
316
+ size="sm"
315
317
  key={action.key}
316
318
  icon={action.icon}
317
319
  label={action.label}
@@ -320,7 +322,7 @@ export function CompactTabStrip({
320
322
  className={actionButtonClassName}
321
323
  />
322
324
  ))}
323
- </div>
325
+ </IconActionGroup>
324
326
  </div>
325
327
  );
326
328
  }
@@ -63,7 +63,7 @@ export function TabsList({ children, className }: TabsListProps) {
63
63
  role="tablist"
64
64
  onKeyDown={handleKeyDown}
65
65
  className={cn(
66
- 'inline-flex h-9 items-center justify-center rounded-xl bg-muted p-1 text-muted-foreground',
66
+ 'inline-flex h-9 max-md:h-auto items-center justify-center rounded-xl bg-muted p-1 text-muted-foreground',
67
67
  className
68
68
  )}
69
69
  >
@@ -87,9 +87,9 @@ export function TabsTrigger({ value, children, className }: TabsTriggerProps) {
87
87
  tabIndex={isActive ? 0 : -1}
88
88
  data-state={isActive ? 'active' : 'inactive'}
89
89
  className={cn(
90
- 'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-[13px] font-medium transition-all duration-fast focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:pointer-events-none disabled:opacity-50',
90
+ 'inline-flex max-md:min-h-[var(--control-touch-size)] items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-[13px] font-medium transition-all duration-fast focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:pointer-events-none disabled:opacity-50',
91
91
  isActive
92
- ? 'bg-card text-foreground shadow-sm'
92
+ ? 'bg-[var(--interaction-selection)] text-foreground'
93
93
  : 'text-muted-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground',
94
94
  className
95
95
  )}
@@ -8,6 +8,7 @@ export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
8
8
  <textarea
9
9
  className={cn(
10
10
  "flex min-h-28 w-full rounded-xl border border-border/75 bg-card px-3.5 py-2.5 text-sm text-foreground placeholder:text-muted-foreground/55 placeholder:font-normal transition-colors focus:outline-none focus:ring-0 disabled:cursor-not-allowed disabled:opacity-50",
11
+ 'max-md:text-base',
11
12
  className,
12
13
  )}
13
14
  ref={ref}
@@ -7,7 +7,7 @@ import {
7
7
  PictureInPicture2,
8
8
  X,
9
9
  } from "lucide-react";
10
- import { IconActionButton } from "@/shared/components/ui/actions/icon-action-button";
10
+ import { IconActionButton, IconActionGroup } from "@/shared/components/ui/actions/icon-action-button";
11
11
  import { t } from "@/shared/lib/i18n";
12
12
  import type { WorkbenchSurfaceState } from "./types/workbench-surface.types";
13
13
 
@@ -33,8 +33,7 @@ export function WorkbenchSurfaceToolbar({
33
33
  onOpenMain?: () => void;
34
34
  }) {
35
35
  return (
36
- <div
37
- className="flex shrink-0 items-center gap-0.5"
36
+ <IconActionGroup
38
37
  data-workbench-actions=""
39
38
  >
40
39
  {onOpenMain && (
@@ -97,6 +96,6 @@ export function WorkbenchSurfaceToolbar({
97
96
  label={closeLabel}
98
97
  onClick={onClose}
99
98
  />
100
- </div>
99
+ </IconActionGroup>
101
100
  );
102
101
  }
@@ -265,8 +265,8 @@ export function WorkbenchSurface({
265
265
  }}
266
266
  >
267
267
  <header
268
- className="flex min-h-10 shrink-0 select-none items-center gap-2 border-b border-border/60 bg-muted/30 px-2"
269
- style={{ touchAction: floating ? "none" : undefined }}
268
+ className="flex min-h-10 shrink-0 select-none items-center gap-1 border-b border-border/60 bg-muted/30 px-2"
269
+ style={{ touchAction: floating ? "none" : undefined, paddingTop: isCompact ? "env(safe-area-inset-top, 0px)" : undefined }}
270
270
  onPointerDown={(event) => startInteraction(event)}
271
271
  onDoubleClick={(event) => {
272
272
  if (!isCompact && !blocksDrag(event.target))
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "agentsPageTitle": "Agents",
3
+ "mobileAgents": "Agents",
4
+ "mobileNavigation": "Main navigation",
3
5
  "agentsPageDescription": "Manage conversational agent identities. Each agent owns its home directory, setup, memory, and skills.",
4
6
  "agentsHeroEyebrow": "Agent Gallery",
5
7
  "agentsHeroTitle": "Give every agent the presence of a real collaborator",
@@ -1,4 +1,5 @@
1
1
  {
2
+ "refresh": "Refresh",
2
3
  "chat": "Chat",
3
4
  "model": "Model",
4
5
  "searchChannels": "Search Channels",
@@ -4,7 +4,7 @@
4
4
  "runtimeUpdatesPageDescription": "NextClaw checks every two hours; you choose when to start each update.",
5
5
  "runtimeUpdatesUnavailableTitle": "Updates Are Currently Unavailable",
6
6
  "runtimeUpdatesUnavailableDescription": "This runtime environment does not currently expose an update host.",
7
- "runtimeUpdatesUnavailableHint": "The update entry appears automatically once the host supports updates.",
7
+ "runtimeUpdatesUnavailableHint": "Update using the method you used to install NextClaw. An update button will appear when in-app updates are supported.",
8
8
  "runtimeUpdatesHostVersion": "Host Version",
9
9
  "runtimeUpdatesDownloadedBannerDescription": "Version {version} has finished downloading and is ready to finish updating.",
10
10
  "runtimeUpdatesActionsDescription": "Check manually, then complete the update in one action whenever you are ready.",
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "agentsPageTitle": "Agent 管理",
3
+ "mobileAgents": "Agent",
4
+ "mobileNavigation": "主导航",
3
5
  "agentsPageDescription": "管理可对话的 Agent 身份。每个 Agent 都有自己的主目录、设定、记忆与技能。",
4
6
  "agentsHeroEyebrow": "Agent 管理台",
5
7
  "agentsHeroTitle": "让每个 Agent 都像真正的协作者一样存在",
@@ -1,4 +1,5 @@
1
1
  {
2
+ "refresh": "刷新",
2
3
  "chat": "对话",
3
4
  "model": "模型",
4
5
  "searchChannels": "搜索渠道",
@@ -4,7 +4,7 @@
4
4
  "runtimeUpdatesPageDescription": "系统每两小时自动检查新版本;发现更新后,由你决定何时开始更新。",
5
5
  "runtimeUpdatesUnavailableTitle": "当前环境暂不支持更新",
6
6
  "runtimeUpdatesUnavailableDescription": "这个运行环境暂时没有可用的更新宿主。",
7
- "runtimeUpdatesUnavailableHint": "更新入口会在宿主支持后自动出现,不需要前端单独区分环境。",
7
+ "runtimeUpdatesUnavailableHint": "请使用安装 NextClaw 时的方式更新;支持应用内更新后,更新按钮会自动出现。",
8
8
  "runtimeUpdatesHostVersion": "宿主版本",
9
9
  "runtimeUpdatesDownloadedBannerDescription": "版本 {version} 已下载完成,可以继续完成更新。",
10
10
  "runtimeUpdatesActionsDescription": "你可以手动检查,并在准备好之后一次完成更新。",