@neurocode-ai/session-ui 1.18.8

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 (114) hide show
  1. package/package.json +71 -0
  2. package/src/components/apply-patch-file.test.ts +43 -0
  3. package/src/components/apply-patch-file.ts +78 -0
  4. package/src/components/basic-tool.css +358 -0
  5. package/src/components/basic-tool.stories.tsx +133 -0
  6. package/src/components/basic-tool.tsx +343 -0
  7. package/src/components/dock-prompt.stories.tsx +62 -0
  8. package/src/components/dock-prompt.tsx +23 -0
  9. package/src/components/file-media.tsx +291 -0
  10. package/src/components/file-search.tsx +72 -0
  11. package/src/components/file-ssr.tsx +197 -0
  12. package/src/components/file.css +46 -0
  13. package/src/components/file.tsx +1202 -0
  14. package/src/components/line-comment-annotations.tsx +637 -0
  15. package/src/components/line-comment-styles.ts +292 -0
  16. package/src/components/line-comment.stories.tsx +115 -0
  17. package/src/components/line-comment.tsx +439 -0
  18. package/src/components/markdown-cache.tsx +78 -0
  19. package/src/components/markdown-code-state.test.ts +32 -0
  20. package/src/components/markdown-code-state.ts +22 -0
  21. package/src/components/markdown-inline-code-kind.test.ts +46 -0
  22. package/src/components/markdown-inline-code-kind.ts +1915 -0
  23. package/src/components/markdown-preload.test.ts +18 -0
  24. package/src/components/markdown-shiki.worker.ts +104 -0
  25. package/src/components/markdown-stream.test.ts +194 -0
  26. package/src/components/markdown-stream.ts +110 -0
  27. package/src/components/markdown-worker-protocol.test.ts +81 -0
  28. package/src/components/markdown-worker-protocol.ts +48 -0
  29. package/src/components/markdown-worker-queue.test.ts +49 -0
  30. package/src/components/markdown-worker-queue.ts +64 -0
  31. package/src/components/markdown-worker-transport.test.ts +56 -0
  32. package/src/components/markdown-worker-transport.ts +41 -0
  33. package/src/components/markdown-worker.ts +122 -0
  34. package/src/components/markdown.css +377 -0
  35. package/src/components/markdown.stories.tsx +53 -0
  36. package/src/components/markdown.tsx +678 -0
  37. package/src/components/message-file.test.ts +63 -0
  38. package/src/components/message-file.ts +34 -0
  39. package/src/components/message-nav.css +127 -0
  40. package/src/components/message-nav.stories.tsx +7 -0
  41. package/src/components/message-nav.tsx +102 -0
  42. package/src/components/message-part-text.ts +3 -0
  43. package/src/components/message-part.css +1569 -0
  44. package/src/components/message-part.stories.tsx +7 -0
  45. package/src/components/message-part.test.ts +28 -0
  46. package/src/components/message-part.tsx +2662 -0
  47. package/src/components/session-diff.test.ts +135 -0
  48. package/src/components/session-diff.ts +145 -0
  49. package/src/components/session-retry.tsx +74 -0
  50. package/src/components/session-review.css +247 -0
  51. package/src/components/session-review.stories.tsx +7 -0
  52. package/src/components/session-review.tsx +657 -0
  53. package/src/components/session-turn.css +241 -0
  54. package/src/components/session-turn.stories.tsx +7 -0
  55. package/src/components/session-turn.tsx +543 -0
  56. package/src/components/shell-submessage-motion.stories.tsx +346 -0
  57. package/src/components/shell-submessage.css +23 -0
  58. package/src/components/timeline-playground.stories.tsx +2090 -0
  59. package/src/components/tool-count-label.css +57 -0
  60. package/src/components/tool-count-label.tsx +58 -0
  61. package/src/components/tool-count-summary.css +102 -0
  62. package/src/components/tool-count-summary.stories.tsx +238 -0
  63. package/src/components/tool-count-summary.tsx +52 -0
  64. package/src/components/tool-error-card.css +91 -0
  65. package/src/components/tool-error-card.stories.tsx +92 -0
  66. package/src/components/tool-error-card.tsx +157 -0
  67. package/src/components/tool-status-title.css +89 -0
  68. package/src/components/tool-status-title.tsx +133 -0
  69. package/src/context/data.tsx +64 -0
  70. package/src/context/index.ts +1 -0
  71. package/src/pierre/comment-hover.ts +83 -0
  72. package/src/pierre/commented-lines.ts +91 -0
  73. package/src/pierre/diff-selection.ts +71 -0
  74. package/src/pierre/file-find.ts +485 -0
  75. package/src/pierre/file-runtime.ts +114 -0
  76. package/src/pierre/file-selection.ts +85 -0
  77. package/src/pierre/index.ts +186 -0
  78. package/src/pierre/media.ts +110 -0
  79. package/src/pierre/selection-bridge.ts +132 -0
  80. package/src/pierre/virtualizer.ts +100 -0
  81. package/src/pierre/worker.ts +52 -0
  82. package/src/styles/index.css +14 -0
  83. package/src/v2/components/attachment-card-v2.css +70 -0
  84. package/src/v2/components/attachment-card-v2.tsx +33 -0
  85. package/src/v2/components/basic-tool-v2.css +163 -0
  86. package/src/v2/components/basic-tool-v2.stories.tsx +137 -0
  87. package/src/v2/components/basic-tool-v2.tsx +139 -0
  88. package/src/v2/components/comment-card-v2.tsx +64 -0
  89. package/src/v2/components/line-comment-annotations-v2.tsx +220 -0
  90. package/src/v2/components/prompt-input/attachments.ts +266 -0
  91. package/src/v2/components/prompt-input/index.tsx +706 -0
  92. package/src/v2/components/prompt-input/interaction.ts +482 -0
  93. package/src/v2/components/prompt-input/machine.test.ts +164 -0
  94. package/src/v2/components/prompt-input/machine.ts +261 -0
  95. package/src/v2/components/prompt-input/prompt-input.stories.tsx +221 -0
  96. package/src/v2/components/prompt-input/store.test.ts +116 -0
  97. package/src/v2/components/prompt-input/store.ts +152 -0
  98. package/src/v2/components/prompt-input/types.ts +106 -0
  99. package/src/v2/components/session-file-panel-v2.tsx +43 -0
  100. package/src/v2/components/session-progress-indicator-v2.css +875 -0
  101. package/src/v2/components/session-progress-indicator-v2.stories.tsx +66 -0
  102. package/src/v2/components/session-progress-indicator-v2.tsx +32 -0
  103. package/src/v2/components/session-review-empty-changes-v2.tsx +17 -0
  104. package/src/v2/components/session-review-empty-no-git-v2.tsx +28 -0
  105. package/src/v2/components/session-review-file-preview-v2-virtualize.test.ts +13 -0
  106. package/src/v2/components/session-review-file-preview-v2-virtualize.ts +5 -0
  107. package/src/v2/components/session-review-file-preview-v2.tsx +290 -0
  108. package/src/v2/components/session-review-v2.css +458 -0
  109. package/src/v2/components/session-review-v2.tsx +340 -0
  110. package/src/v2/components/tool-error-card-v2.css +200 -0
  111. package/src/v2/components/tool-error-card-v2.stories.tsx +91 -0
  112. package/src/v2/components/tool-error-card-v2.tsx +166 -0
  113. package/sst-env.d.ts +10 -0
  114. package/tsconfig.json +19 -0
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@neurocode-ai/session-ui",
3
+ "version": "1.18.8",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "exports": {
7
+ "./*": "./src/components/*.tsx",
8
+ "./session-diff": "./src/components/session-diff.ts",
9
+ "./message-file": "./src/components/message-file.ts",
10
+ "./message-part-text": "./src/components/message-part-text.ts",
11
+ "./markdown-stream": "./src/components/markdown-stream.ts",
12
+ "./markdown-cache": "./src/components/markdown-cache.tsx",
13
+ "./line-comment-styles": "./src/components/line-comment-styles.ts",
14
+ "./pierre": "./src/pierre/index.ts",
15
+ "./pierre/*": "./src/pierre/*.ts",
16
+ "./context": "./src/context/index.ts",
17
+ "./context/*": "./src/context/*.tsx",
18
+ "./styles": "./src/styles/index.css",
19
+ "./v2/*.css": "./src/v2/components/*.css",
20
+ "./v2/*": "./src/v2/components/*.tsx",
21
+ "./v2/prompt-input": "./src/v2/components/prompt-input/index.tsx",
22
+ "./v2/prompt-input/interaction": "./src/v2/components/prompt-input/interaction.ts",
23
+ "./v2/prompt-input/store": "./src/v2/components/prompt-input/store.ts",
24
+ "./v2/prompt-input/types": "./src/v2/components/prompt-input/types.ts"
25
+ },
26
+ "scripts": {
27
+ "typecheck": "tsgo --noEmit",
28
+ "test": "bun test src --only-failures"
29
+ },
30
+ "devDependencies": {
31
+ "@tsconfig/node22": "22.0.2",
32
+ "@types/bun": "1.3.13",
33
+ "@types/katex": "0.16.7",
34
+ "@types/luxon": "3.7.1",
35
+ "@typescript/native-preview": "7.0.0-dev.20251207.1",
36
+ "typescript": "5.8.2",
37
+ "vite": "7.1.4"
38
+ },
39
+ "dependencies": {
40
+ "@kobalte/core": "0.13.11",
41
+ "@neurocode-ai/client": "file:../app/vendor/opencode-ai-client-1.17.13.tgz",
42
+ "@neurocode-ai/core": "1.18.8",
43
+ "@neurocode-ai/sdk": "1.18.8",
44
+ "@neurocode-ai/ui": "1.18.8",
45
+ "@pierre/diffs": "1.2.10",
46
+ "@shikijs/stream": "4.2.0",
47
+ "@shikijs/transformers": "3.9.2",
48
+ "@solid-primitives/bounds": "0.1.3",
49
+ "@solid-primitives/event-listener": "2.4.5",
50
+ "@solid-primitives/media": "2.3.3",
51
+ "@solid-primitives/resize-observer": "2.1.3",
52
+ "@solidjs/meta": "0.29.4",
53
+ "@solidjs/router": "0.15.4",
54
+ "diff": "8.0.2",
55
+ "dompurify": "3.3.1",
56
+ "fuzzysort": "3.1.0",
57
+ "katex": "0.16.27",
58
+ "luxon": "3.6.1",
59
+ "marked": "17.0.6",
60
+ "marked-katex-extension": "5.1.6",
61
+ "marked-shiki": "1.2.1",
62
+ "morphdom": "2.7.8",
63
+ "motion": "12.34.5",
64
+ "remeda": "2.26.0",
65
+ "remend": "1.3.0",
66
+ "shiki": "4.2.0",
67
+ "solid-js": "1.9.10",
68
+ "solid-list": "0.3.0",
69
+ "strip-ansi": "7.1.2"
70
+ }
71
+ }
@@ -0,0 +1,43 @@
1
+ import { describe, expect, test } from "bun:test"
2
+ import { patchFiles } from "./apply-patch-file"
3
+ import { text } from "./session-diff"
4
+
5
+ describe("apply patch file", () => {
6
+ test("parses patch metadata from the server", () => {
7
+ const file = patchFiles([
8
+ {
9
+ filePath: "/tmp/a.ts",
10
+ relativePath: "a.ts",
11
+ type: "update",
12
+ patch:
13
+ "Index: a.ts\n===================================================================\n--- a.ts\t\n+++ a.ts\t\n@@ -1,2 +1,2 @@\n one\n-two\n+three\n",
14
+ additions: 1,
15
+ deletions: 1,
16
+ },
17
+ ])[0]
18
+
19
+ expect(file).toBeDefined()
20
+ expect(file?.view.fileDiff.name).toBe("a.ts")
21
+ expect(file?.view.fileDiff.isPartial).toBe(false)
22
+ expect(text(file!.view, "deletions")).toBe("one\ntwo\n")
23
+ expect(text(file!.view, "additions")).toBe("one\nthree\n")
24
+ })
25
+
26
+ test("keeps legacy before and after payloads working", () => {
27
+ const file = patchFiles([
28
+ {
29
+ filePath: "/tmp/a.ts",
30
+ relativePath: "a.ts",
31
+ type: "update",
32
+ before: "one\n",
33
+ after: "two\n",
34
+ additions: 1,
35
+ deletions: 1,
36
+ },
37
+ ])[0]
38
+
39
+ expect(file).toBeDefined()
40
+ expect(text(file!.view, "deletions")).toBe("one\n")
41
+ expect(text(file!.view, "additions")).toBe("two\n")
42
+ })
43
+ })
@@ -0,0 +1,78 @@
1
+ import { normalize, type ViewDiff } from "./session-diff"
2
+
3
+ type Kind = "add" | "update" | "delete" | "move"
4
+
5
+ type Raw = {
6
+ filePath?: string
7
+ relativePath?: string
8
+ type?: Kind
9
+ patch?: string
10
+ diff?: string
11
+ before?: string
12
+ after?: string
13
+ additions?: number
14
+ deletions?: number
15
+ movePath?: string
16
+ }
17
+
18
+ export type ApplyPatchFile = {
19
+ filePath: string
20
+ relativePath: string
21
+ type: Kind
22
+ additions: number
23
+ deletions: number
24
+ movePath?: string
25
+ view: ViewDiff
26
+ }
27
+
28
+ function kind(value: unknown) {
29
+ if (value === "add" || value === "update" || value === "delete" || value === "move") return value
30
+ }
31
+
32
+ function status(type: Kind): "added" | "deleted" | "modified" {
33
+ if (type === "add") return "added"
34
+ if (type === "delete") return "deleted"
35
+ return "modified"
36
+ }
37
+
38
+ export function patchFile(raw: unknown): ApplyPatchFile | undefined {
39
+ if (!raw || typeof raw !== "object") return
40
+
41
+ const value = raw as Raw
42
+ const type = kind(value.type)
43
+ const filePath = typeof value.filePath === "string" ? value.filePath : undefined
44
+ const relativePath = typeof value.relativePath === "string" ? value.relativePath : filePath
45
+ const patch = typeof value.patch === "string" ? value.patch : typeof value.diff === "string" ? value.diff : undefined
46
+ const before = typeof value.before === "string" ? value.before : undefined
47
+ const after = typeof value.after === "string" ? value.after : undefined
48
+
49
+ if (!type || !filePath || !relativePath) return
50
+ if (!patch && before === undefined && after === undefined) return
51
+
52
+ const additions = typeof value.additions === "number" ? value.additions : 0
53
+ const deletions = typeof value.deletions === "number" ? value.deletions : 0
54
+ const movePath = typeof value.movePath === "string" ? value.movePath : undefined
55
+
56
+ return {
57
+ filePath,
58
+ relativePath,
59
+ type,
60
+ additions,
61
+ deletions,
62
+ movePath,
63
+ view: normalize({
64
+ file: relativePath,
65
+ patch,
66
+ before,
67
+ after,
68
+ additions,
69
+ deletions,
70
+ status: status(type),
71
+ }),
72
+ }
73
+ }
74
+
75
+ export function patchFiles(raw: unknown) {
76
+ if (!Array.isArray(raw)) return []
77
+ return raw.map(patchFile).filter((file): file is ApplyPatchFile => !!file)
78
+ }
@@ -0,0 +1,358 @@
1
+ [data-component="tool-trigger"] {
2
+ content-visibility: auto;
3
+ width: 100%;
4
+ display: flex;
5
+ align-items: center;
6
+ align-self: stretch;
7
+ gap: 0px;
8
+ justify-content: flex-start;
9
+
10
+ &[data-clickable="true"] {
11
+ cursor: pointer;
12
+ }
13
+
14
+ [data-slot="basic-tool-tool-trigger-content"] {
15
+ flex: 0 1 auto;
16
+ width: auto;
17
+ max-width: calc(100% - 24px);
18
+ min-width: 0;
19
+ display: flex;
20
+ align-items: center;
21
+ align-self: stretch;
22
+ gap: 8px;
23
+ }
24
+
25
+ [data-slot="basic-tool-tool-indicator"] {
26
+ width: 16px;
27
+ height: 16px;
28
+ display: inline-flex;
29
+ align-items: center;
30
+ justify-content: center;
31
+ flex-shrink: 0;
32
+
33
+ [data-component="spinner"] {
34
+ width: 16px;
35
+ height: 16px;
36
+ }
37
+ }
38
+
39
+ [data-slot="basic-tool-tool-spinner"] {
40
+ width: 16px;
41
+ height: 16px;
42
+ display: inline-flex;
43
+ align-items: center;
44
+ justify-content: center;
45
+ flex-shrink: 0;
46
+ color: var(--v2-text-text-faint);
47
+
48
+ [data-component="spinner"] {
49
+ width: 16px;
50
+ height: 16px;
51
+ }
52
+ }
53
+
54
+ [data-slot="icon-svg"] {
55
+ flex-shrink: 0;
56
+ }
57
+
58
+ [data-slot="basic-tool-tool-info"] {
59
+ flex: 0 1 auto;
60
+ min-width: 0;
61
+ max-width: 100%;
62
+ font-size: 14px;
63
+ }
64
+
65
+ [data-slot="basic-tool-tool-info-structured"] {
66
+ flex: 0 1 auto;
67
+ width: auto;
68
+ max-width: 100%;
69
+ min-width: 0;
70
+ display: inline-flex;
71
+ align-items: center;
72
+ gap: 8px;
73
+ justify-content: flex-start;
74
+ }
75
+
76
+ [data-slot="basic-tool-tool-info-main"] {
77
+ display: flex;
78
+ align-items: baseline;
79
+ gap: 8px;
80
+ min-width: 0;
81
+ overflow: hidden;
82
+ }
83
+
84
+ [data-slot="basic-tool-tool-title"] {
85
+ flex-shrink: 0;
86
+ font-family: var(--font-family-sans);
87
+ font-size: 14px;
88
+ font-style: normal;
89
+ font-weight: var(--font-weight-medium);
90
+ line-height: var(--line-height-large);
91
+ letter-spacing: var(--letter-spacing-normal);
92
+ color: var(--v2-text-text-base);
93
+
94
+ &.capitalize {
95
+ text-transform: capitalize;
96
+ }
97
+
98
+ &.agent-title {
99
+ color: var(--v2-text-text-base);
100
+ font-weight: var(--font-weight-medium);
101
+ }
102
+ }
103
+
104
+ [data-slot="basic-tool-tool-subtitle"] {
105
+ flex-shrink: 1;
106
+ min-width: 0;
107
+ overflow: hidden;
108
+ text-overflow: ellipsis;
109
+ white-space: nowrap;
110
+ font-family: var(--font-family-sans);
111
+ font-variant-numeric: tabular-nums;
112
+ font-size: 14px;
113
+ font-style: normal;
114
+ font-weight: var(--font-weight-regular);
115
+ line-height: var(--line-height-large);
116
+ letter-spacing: var(--letter-spacing-normal);
117
+ color: var(--v2-text-text-muted);
118
+
119
+ &.clickable {
120
+ cursor: pointer;
121
+ text-decoration: underline;
122
+ transition: color 0.15s ease;
123
+
124
+ &:hover {
125
+ color: var(--v2-text-text-muted);
126
+ }
127
+ }
128
+
129
+ &.subagent-link {
130
+ color: var(--text-interactive-base);
131
+ text-decoration: none;
132
+ text-underline-offset: 2px;
133
+ font-weight: var(--font-weight-regular);
134
+
135
+ &:hover {
136
+ color: var(--text-interactive-base);
137
+ text-decoration: underline;
138
+ }
139
+
140
+ &:active {
141
+ color: var(--text-interactive-base);
142
+ }
143
+
144
+ &:visited {
145
+ color: var(--text-interactive-base);
146
+ }
147
+ }
148
+ }
149
+
150
+ [data-slot="basic-tool-tool-arg"] {
151
+ flex-shrink: 1;
152
+ min-width: 0;
153
+ overflow: hidden;
154
+ text-overflow: ellipsis;
155
+ white-space: nowrap;
156
+ font-family: var(--font-family-sans);
157
+ font-variant-numeric: tabular-nums;
158
+ font-size: 14px;
159
+ font-style: normal;
160
+ font-weight: var(--font-weight-regular);
161
+ line-height: var(--line-height-large);
162
+ letter-spacing: var(--letter-spacing-normal);
163
+ color: var(--v2-text-text-muted);
164
+ }
165
+
166
+ [data-slot="basic-tool-tool-action"] {
167
+ display: inline-flex;
168
+ align-items: center;
169
+ flex-shrink: 0;
170
+ }
171
+ }
172
+
173
+ [data-component="task-tool-card"] {
174
+ width: 100%;
175
+ min-width: 0;
176
+ display: flex;
177
+ align-items: center;
178
+ gap: 8px;
179
+ padding: 8px 12px;
180
+ border-radius: 6px;
181
+ border: 0.5px solid var(--border-weak-base, rgba(255, 255, 255, 0.08));
182
+ background: color-mix(in srgb, var(--background-base) 92%, transparent);
183
+ transition:
184
+ border-color 0.15s ease,
185
+ background-color 0.15s ease,
186
+ color 0.15s ease;
187
+
188
+ [data-component="task-tool-surface"] {
189
+ display: flex;
190
+ align-items: center;
191
+ gap: 8px;
192
+ min-width: 0;
193
+ flex: 1 1 auto;
194
+ }
195
+
196
+ [data-slot="basic-tool-tool-info-structured"] {
197
+ flex: 1 1 auto;
198
+ min-width: 0;
199
+ }
200
+
201
+ [data-slot="basic-tool-tool-info-main"] {
202
+ flex: 1 1 auto;
203
+ min-width: 0;
204
+ align-items: center;
205
+ }
206
+
207
+ [data-component="task-tool-spinner"] {
208
+ display: inline-flex;
209
+ align-items: center;
210
+ justify-content: center;
211
+ flex-shrink: 0;
212
+
213
+ [data-component="spinner"] {
214
+ width: 16px;
215
+ height: 16px;
216
+ }
217
+ }
218
+
219
+ [data-component="task-tool-action"] {
220
+ display: inline-flex;
221
+ align-items: center;
222
+ justify-content: center;
223
+ flex-shrink: 0;
224
+ color: var(--v2-text-text-faint);
225
+ margin-left: auto;
226
+ opacity: 0;
227
+ transition:
228
+ opacity 0.15s ease,
229
+ color 0.15s ease;
230
+ }
231
+
232
+ [data-component="task-tool-title"] {
233
+ flex-shrink: 0;
234
+ font-family: var(--font-family-sans);
235
+ font-size: 14px;
236
+ font-style: normal;
237
+ font-weight: var(--font-weight-medium);
238
+ line-height: var(--line-height-large);
239
+ letter-spacing: var(--letter-spacing-normal);
240
+ text-transform: capitalize;
241
+ color: var(--task-agent-legacy-color, var(--text-strong));
242
+ }
243
+
244
+ [data-slot="basic-tool-tool-subtitle"] {
245
+ color: var(--v2-text-text-base);
246
+ }
247
+
248
+ &:hover,
249
+ &:focus-visible {
250
+ border-color: var(--border-weak-base, rgba(255, 255, 255, 0.08));
251
+ background: color-mix(in srgb, var(--background-stronger) 88%, transparent);
252
+
253
+ [data-component="task-tool-action"] {
254
+ opacity: 1;
255
+ }
256
+ }
257
+ }
258
+
259
+ body[data-new-layout] {
260
+ [data-component="task-tool-card"] {
261
+ gap: 8px;
262
+ padding: 0;
263
+ border-radius: 0;
264
+ border: 0;
265
+ border-color: transparent;
266
+ background: transparent;
267
+ box-shadow: none;
268
+
269
+ [data-component="task-tool-surface"] {
270
+ padding: 8px 12px;
271
+ border-radius: 8px;
272
+ background: var(--v2-background-bg-layer-01);
273
+ }
274
+
275
+ [data-component="task-tool-spinner"],
276
+ [data-component="task-tool-icon"] {
277
+ display: inline-flex;
278
+ align-items: center;
279
+ justify-content: center;
280
+ flex-shrink: 0;
281
+
282
+ [data-component="icon"] {
283
+ color: var(--task-agent-color, var(--v2-icon-icon-base));
284
+ }
285
+ }
286
+
287
+ [data-component="task-tool-title"] {
288
+ height: 20px;
289
+ font-family: var(--v2-font-family-sans, "Inter", sans-serif);
290
+ font-style: normal;
291
+ font-weight: 530;
292
+ font-size: 13px;
293
+ line-height: 20px;
294
+ letter-spacing: -0.04px;
295
+ color: var(--v2-text-text-base);
296
+ flex: none;
297
+ flex-grow: 0;
298
+ }
299
+
300
+ [data-slot="basic-tool-tool-subtitle"] {
301
+ font-family: var(--v2-font-family-sans, "Inter", sans-serif);
302
+ font-style: normal;
303
+ font-weight: 440;
304
+ font-size: 13px;
305
+ line-height: 20px;
306
+ letter-spacing: -0.04px;
307
+ color: var(--v2-text-text-base);
308
+ font-variation-settings: "slnt" 0;
309
+ flex: none;
310
+ flex-grow: 0;
311
+ }
312
+
313
+ [data-component="session-progress-indicator-v2"] {
314
+ color: var(--task-agent-color, light-dark(var(--v2-text-text-base), #ffffff));
315
+ }
316
+
317
+ &:hover,
318
+ &:focus-visible {
319
+ border-color: transparent;
320
+ background: transparent;
321
+
322
+ [data-component="task-tool-surface"] {
323
+ background: var(--v2-background-bg-layer-01);
324
+ }
325
+ }
326
+ }
327
+ }
328
+
329
+ body:not([data-new-layout]) {
330
+ [data-component="tool-trigger"] {
331
+ [data-slot="basic-tool-tool-spinner"] {
332
+ color: var(--text-weak);
333
+ }
334
+
335
+ [data-slot="basic-tool-tool-title"],
336
+ [data-slot="basic-tool-tool-title"].agent-title {
337
+ color: var(--text-strong);
338
+ }
339
+
340
+ [data-slot="basic-tool-tool-subtitle"],
341
+ [data-slot="basic-tool-tool-subtitle"].clickable:hover,
342
+ [data-slot="basic-tool-tool-arg"] {
343
+ color: var(--text-base);
344
+ }
345
+ }
346
+
347
+ [data-component="task-tool-card"] {
348
+ border-width: 1px;
349
+
350
+ [data-component="task-tool-action"] {
351
+ color: var(--icon-weak);
352
+ }
353
+
354
+ [data-slot="basic-tool-tool-subtitle"] {
355
+ color: var(--text-strong);
356
+ }
357
+ }
358
+ }
@@ -0,0 +1,133 @@
1
+ // @ts-nocheck
2
+ import { createSignal } from "solid-js"
3
+ import * as mod from "./basic-tool"
4
+ import { create } from "@neurocode-ai/ui/storybook/scaffold"
5
+
6
+ const docs = `### Overview
7
+ Expandable tool panel with a structured trigger and optional details.
8
+
9
+ Use structured triggers for consistent layout; custom triggers allowed.
10
+
11
+ ### API
12
+ - Required: \`icon\` and \`trigger\` (structured or custom JSX).
13
+ - Optional: \`status\`, \`defaultOpen\`, \`forceOpen\`, \`defer\`, \`locked\`.
14
+
15
+ ### Variants and states
16
+ - Pending/running status animates the title via TextShimmer.
17
+
18
+ ### Behavior
19
+ - Uses Collapsible; can defer content rendering until open.
20
+ - Locked state prevents closing.
21
+
22
+ ### Accessibility
23
+ - TODO: confirm trigger semantics and aria labeling.
24
+
25
+ ### Theming/tokens
26
+ - Uses \`data-component="tool-trigger"\` and related slots.
27
+
28
+ `
29
+
30
+ const story = create({
31
+ title: "UI/Basic Tool",
32
+ mod,
33
+ args: {
34
+ icon: "mcp",
35
+ defaultOpen: true,
36
+ trigger: {
37
+ title: "Basic Tool",
38
+ subtitle: "Example subtitle",
39
+ args: ["--flag", "value"],
40
+ },
41
+ children: "Details content",
42
+ },
43
+ })
44
+
45
+ export default {
46
+ title: "UI/Basic Tool",
47
+ id: "components-basic-tool",
48
+ component: story.meta.component,
49
+ tags: ["autodocs"],
50
+ parameters: {
51
+ docs: {
52
+ description: {
53
+ component: docs,
54
+ },
55
+ },
56
+ },
57
+ }
58
+
59
+ export const Basic = story.Basic
60
+
61
+ export const Pending = {
62
+ args: {
63
+ status: "pending",
64
+ trigger: {
65
+ title: "Running tool",
66
+ subtitle: "Working...",
67
+ },
68
+ children: "Progress details",
69
+ },
70
+ }
71
+
72
+ export const Locked = {
73
+ args: {
74
+ locked: true,
75
+ trigger: {
76
+ title: "Locked tool",
77
+ subtitle: "Cannot close",
78
+ },
79
+ children: "Locked details",
80
+ },
81
+ }
82
+
83
+ export const Deferred = {
84
+ args: {
85
+ defer: true,
86
+ defaultOpen: false,
87
+ trigger: {
88
+ title: "Deferred tool",
89
+ subtitle: "Content mounts on open",
90
+ },
91
+ children: "Deferred content",
92
+ },
93
+ }
94
+
95
+ export const ForceOpen = {
96
+ args: {
97
+ forceOpen: true,
98
+ trigger: {
99
+ title: "Forced open",
100
+ subtitle: "Cannot close",
101
+ },
102
+ children: "Forced content",
103
+ },
104
+ }
105
+
106
+ export const HideDetails = {
107
+ args: {
108
+ hideDetails: true,
109
+ trigger: {
110
+ title: "Summary only",
111
+ subtitle: "Details hidden",
112
+ },
113
+ children: "Hidden content",
114
+ },
115
+ }
116
+
117
+ export const SubtitleAction = {
118
+ render: () => {
119
+ const [message, setMessage] = createSignal("Subtitle not clicked")
120
+ return (
121
+ <div style={{ display: "grid", gap: "8px" }}>
122
+ <div style={{ "font-size": "12px", color: "var(--text-weak)" }}>{message()}</div>
123
+ <mod.BasicTool
124
+ icon="mcp"
125
+ trigger={{ title: "Clickable subtitle", subtitle: "Click me" }}
126
+ onSubtitleClick={() => setMessage("Subtitle clicked")}
127
+ >
128
+ Subtitle action details
129
+ </mod.BasicTool>
130
+ </div>
131
+ )
132
+ },
133
+ }