@sentry/junior-dashboard 0.264.0 → 0.266.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 (213) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +2 -5
  3. package/dist/app.js +119 -35
  4. package/dist/client.js +145 -136
  5. package/dist/index.d.ts +0 -1
  6. package/dist/index.js +119 -35
  7. package/dist/tailwind.css +1 -1
  8. package/package.json +5 -4
  9. package/src/api/schema.ts +0 -1
  10. package/src/app.ts +5 -20
  11. package/src/client/App.tsx +29 -31
  12. package/src/client/api.ts +7 -0
  13. package/src/client/components/ActorAvatar.tsx +10 -22
  14. package/src/client/components/BottomSheet.tsx +12 -2
  15. package/src/client/components/ConnectionBanner.tsx +4 -3
  16. package/src/client/components/CopyButton.tsx +82 -0
  17. package/src/client/components/DetailsPanel.tsx +133 -0
  18. package/src/client/components/Drawer.tsx +15 -24
  19. package/src/client/components/EmptyTelemetry.tsx +5 -3
  20. package/src/client/components/FilterBar.tsx +16 -31
  21. package/src/client/components/ImageAttachment.tsx +49 -63
  22. package/src/client/components/InlineError.tsx +8 -4
  23. package/src/client/components/Metric.tsx +33 -23
  24. package/src/client/components/Notice.tsx +19 -26
  25. package/src/client/components/PageContentSkeleton.tsx +1 -1
  26. package/src/client/components/Pagination.tsx +27 -27
  27. package/src/client/components/ParticipantAvatarStack.tsx +43 -39
  28. package/src/client/components/ProfileMenu.tsx +27 -93
  29. package/src/client/components/README.md +103 -78
  30. package/src/client/components/SearchInput.tsx +51 -41
  31. package/src/client/components/SegmentedNav.tsx +1 -1
  32. package/src/client/components/ShimmerText.tsx +2 -6
  33. package/src/client/components/ThemeSwitcher.tsx +19 -15
  34. package/src/client/components/VersionDriftBanner.tsx +9 -7
  35. package/src/client/components/charts/ActivityChart.tsx +173 -288
  36. package/src/client/components/charts/CacheWrites.tsx +59 -37
  37. package/src/client/components/charts/InputCacheChart.tsx +137 -131
  38. package/src/client/components/charts/README.md +4 -4
  39. package/src/client/components/charts/SystemMetricCharts.tsx +68 -95
  40. package/src/client/components/charts/WorkspaceUsageChart.tsx +42 -62
  41. package/src/client/components/controls/DirectorySortSelect.tsx +3 -3
  42. package/src/client/components/controls/TimeRangeSelector.tsx +10 -15
  43. package/src/client/components/layout/DashboardHeader.tsx +44 -90
  44. package/src/client/components/layout/SecondaryNavigation.tsx +2 -1
  45. package/src/client/components/layout/VisualViewportShell.tsx +2 -2
  46. package/src/client/components/ui/accordion.tsx +77 -0
  47. package/src/client/components/ui/alert-dialog.tsx +89 -0
  48. package/src/client/components/ui/alert.tsx +64 -0
  49. package/src/client/components/ui/avatar.tsx +53 -0
  50. package/src/client/components/ui/button.tsx +86 -0
  51. package/src/client/components/ui/chart.tsx +74 -0
  52. package/src/client/components/ui/checkbox.tsx +26 -0
  53. package/src/client/components/ui/collapsible.tsx +22 -0
  54. package/src/client/components/ui/dialog.tsx +66 -0
  55. package/src/client/components/ui/empty.tsx +32 -0
  56. package/src/client/components/ui/field.tsx +49 -0
  57. package/src/client/components/ui/input-group.tsx +96 -0
  58. package/src/client/components/ui/input.tsx +35 -0
  59. package/src/client/components/ui/native-select.tsx +57 -0
  60. package/src/client/components/ui/pagination.tsx +60 -0
  61. package/src/client/components/ui/popover.tsx +67 -0
  62. package/src/client/components/ui/radio-group.tsx +32 -0
  63. package/src/client/components/ui/sheet.tsx +13 -3
  64. package/src/client/components/ui/skeleton.tsx +19 -0
  65. package/src/client/components/ui/spinner.tsx +21 -0
  66. package/src/client/components/ui/table.tsx +101 -0
  67. package/src/client/components/ui/tabs.tsx +75 -0
  68. package/src/client/components/ui/textarea.tsx +17 -0
  69. package/src/client/components/ui/toast.tsx +215 -0
  70. package/src/client/components/ui/toggle-group.tsx +36 -0
  71. package/src/client/components/ui/toggle.tsx +37 -0
  72. package/src/client/components/ui/tooltip.tsx +168 -0
  73. package/src/client/components/ui/trace.tsx +96 -0
  74. package/src/client/conversations/ChatLayout.tsx +7 -3
  75. package/src/client/conversations/ConversationBrief.tsx +17 -6
  76. package/src/client/conversations/ConversationChildAgents.tsx +5 -5
  77. package/src/client/conversations/ConversationComposer.tsx +26 -12
  78. package/src/client/conversations/ConversationDetails.tsx +147 -62
  79. package/src/client/conversations/ConversationEventDetails.tsx +141 -0
  80. package/src/client/conversations/ConversationEventLog.tsx +150 -129
  81. package/src/client/conversations/ConversationHeader.tsx +13 -7
  82. package/src/client/conversations/ConversationHeaderActions.tsx +97 -93
  83. package/src/client/conversations/ConversationHomeList.tsx +1 -1
  84. package/src/client/conversations/ConversationLinkedWork.tsx +118 -0
  85. package/src/client/conversations/ConversationMeta.tsx +55 -88
  86. package/src/client/conversations/ConversationPage.tsx +220 -101
  87. package/src/client/conversations/ConversationSidebar.tsx +49 -29
  88. package/src/client/conversations/ConversationUsageBreakdown.tsx +108 -65
  89. package/src/client/conversations/ConversationWatches.tsx +173 -0
  90. package/src/client/conversations/ConversationWorkspace.tsx +12 -22
  91. package/src/client/conversations/ConversationWorkspaceLoading.tsx +1 -1
  92. package/src/client/conversations/DetailsList.tsx +139 -0
  93. package/src/client/conversations/EventDetails.tsx +42 -8
  94. package/src/client/conversations/EventUsage.tsx +99 -74
  95. package/src/client/conversations/ForkConversationButton.tsx +27 -16
  96. package/src/client/conversations/ObjectCard.tsx +20 -8
  97. package/src/client/conversations/PendingMailboxStack.tsx +52 -38
  98. package/src/client/conversations/README.md +89 -13
  99. package/src/client/conversations/ShareConversationButton.tsx +28 -17
  100. package/src/client/conversations/SubagentTranscriptDrawer.tsx +21 -15
  101. package/src/client/conversations/ToolFrame.tsx +36 -52
  102. package/src/client/conversations/TranscriptActivityGroup.tsx +13 -4
  103. package/src/client/conversations/TranscriptAutomationTriggerView.tsx +5 -4
  104. package/src/client/conversations/TranscriptContextEventView.tsx +25 -11
  105. package/src/client/conversations/TranscriptEventView.tsx +35 -16
  106. package/src/client/conversations/TranscriptHeadingRow.tsx +7 -7
  107. package/src/client/conversations/TranscriptLoading.tsx +1 -1
  108. package/src/client/conversations/TranscriptMarkdown.tsx +25 -20
  109. package/src/client/conversations/TranscriptMessageContextView.tsx +35 -18
  110. package/src/client/conversations/TranscriptMessageView.tsx +6 -1
  111. package/src/client/conversations/TranscriptReasoningView.tsx +54 -68
  112. package/src/client/conversations/TranscriptStructuredEventView.tsx +25 -15
  113. package/src/client/conversations/TranscriptSummary.tsx +34 -2
  114. package/src/client/conversations/TranscriptTimestamp.tsx +9 -7
  115. package/src/client/conversations/TranscriptToolView.tsx +1 -1
  116. package/src/client/conversations/TranscriptTurnContextView.tsx +144 -65
  117. package/src/client/conversations/TranscriptView.tsx +63 -27
  118. package/src/client/conversations/eventLog.ts +58 -0
  119. package/src/client/conversations/eventTime.ts +60 -0
  120. package/src/client/conversations/queries.ts +29 -0
  121. package/src/client/conversations/transcriptBottomPinning.ts +34 -0
  122. package/src/client/conversations/transcriptMentions.tsx +18 -5
  123. package/src/client/format.ts +5 -0
  124. package/src/client/pages/ConnectionsPage.tsx +2 -2
  125. package/src/client/pages/PersonalTokensPage.tsx +4 -4
  126. package/src/client/pages/SettingsPage.tsx +9 -10
  127. package/src/client/pages/admin/ServiceAccountsSection.tsx +2 -2
  128. package/src/client/pages/automations/AutomationCostChart.tsx +50 -71
  129. package/src/client/pages/automations/AutomationDeleteDialog.tsx +87 -0
  130. package/src/client/pages/automations/AutomationDetails.tsx +193 -0
  131. package/src/client/pages/automations/AutomationEditPage.tsx +7 -8
  132. package/src/client/pages/automations/AutomationEditor.tsx +41 -29
  133. package/src/client/pages/automations/AutomationEditorLoading.tsx +1 -1
  134. package/src/client/pages/automations/AutomationEventFields.tsx +202 -119
  135. package/src/client/pages/automations/AutomationExecutionChart.tsx +51 -64
  136. package/src/client/pages/automations/AutomationExecutionStatusChart.tsx +47 -70
  137. package/src/client/pages/automations/AutomationExecutionsPage.tsx +150 -126
  138. package/src/client/pages/automations/AutomationFilters.tsx +189 -74
  139. package/src/client/pages/automations/AutomationLifecycle.tsx +109 -78
  140. package/src/client/pages/automations/AutomationOutcomeFields.tsx +26 -24
  141. package/src/client/pages/automations/AutomationRecentRuns.tsx +143 -0
  142. package/src/client/pages/automations/AutomationRow.tsx +12 -138
  143. package/src/client/pages/automations/AutomationRunDetails.tsx +307 -0
  144. package/src/client/pages/automations/AutomationRunsPage.tsx +119 -94
  145. package/src/client/pages/automations/AutomationScheduleFields.tsx +51 -51
  146. package/src/client/pages/automations/AutomationStatus.tsx +201 -0
  147. package/src/client/pages/automations/AutomationVersionsPage.tsx +65 -28
  148. package/src/client/pages/automations/AutomationsPage.tsx +80 -68
  149. package/src/client/pages/automations/AutomationsPageLayout.tsx +46 -14
  150. package/src/client/pages/automations/README.md +57 -0
  151. package/src/client/pages/automations/TriggerFilters.tsx +22 -0
  152. package/src/client/pages/automations/automationFormat.ts +37 -23
  153. package/src/client/pages/code/CodeActivityChart.tsx +59 -101
  154. package/src/client/pages/code/CodePage.tsx +52 -55
  155. package/src/client/pages/code/RepositoryPage.tsx +6 -8
  156. package/src/client/pages/locations/LocationActivityChart.tsx +53 -70
  157. package/src/client/pages/locations/LocationDirectoryActivityChart.tsx +60 -80
  158. package/src/client/pages/memory/MemoryCostChart.tsx +79 -103
  159. package/src/client/pages/memory/MemoryDetails.tsx +218 -0
  160. package/src/client/pages/memory/MemoryPage.tsx +168 -112
  161. package/src/client/pages/memory/MemoryPageLayout.tsx +33 -9
  162. package/src/client/pages/memory/MemoryTimeline.tsx +46 -69
  163. package/src/client/pages/memory/memoryRecord.ts +1 -1
  164. package/src/client/pages/people/ContributionGrid.tsx +23 -16
  165. package/src/client/pages/people/PeopleActivityChart.tsx +68 -107
  166. package/src/client/pages/people/ProfileCodeChanges.tsx +5 -5
  167. package/src/client/pages/system/BaseSandboxCard.tsx +1 -1
  168. package/src/client/pages/system/ConversationActivityChart.tsx +49 -67
  169. package/src/client/pages/system/GuardianActivity.tsx +1 -2
  170. package/src/client/pages/system/PluginBarChart.tsx +106 -87
  171. package/src/client/pages/system/PluginReportRecordSet.tsx +25 -24
  172. package/src/client/pages/system/README.md +23 -0
  173. package/src/client/pages/system/SystemNavigation.tsx +5 -1
  174. package/src/client/pages/system/WorkspaceDeleteDialog.tsx +111 -0
  175. package/src/client/pages/system/WorkspaceDetails.tsx +200 -43
  176. package/src/client/pages/system/WorkspaceEditor.tsx +59 -61
  177. package/src/client/pages/system/WorkspaceFormPage.tsx +23 -47
  178. package/src/client/pages/system/WorkspaceList.tsx +20 -30
  179. package/src/client/pages/system/WorkspacesPage.tsx +117 -119
  180. package/src/client/pages/system/sandboxSize.ts +8 -0
  181. package/src/client/pages/system/workspaceQueries.ts +53 -0
  182. package/src/client/pages/user/PluginUserPage.tsx +51 -2
  183. package/src/client/pages/user/pluginUserPageData.ts +1 -6
  184. package/src/client/styles.ts +4 -0
  185. package/src/client.tsx +7 -1
  186. package/src/mock-reporting/automation-collection.ts +4 -2
  187. package/src/mock-reporting/fixtures.ts +23 -7
  188. package/src/mock-reporting/routes.ts +12 -0
  189. package/src/mock-reporting/watches.ts +94 -0
  190. package/src/shell.ts +4 -9
  191. package/src/tailwind.css +0 -10
  192. package/src/client/components/Button.tsx +0 -118
  193. package/src/client/components/Field.tsx +0 -53
  194. package/src/client/components/SegmentedTabs.tsx +0 -119
  195. package/src/client/components/Select.tsx +0 -52
  196. package/src/client/components/Skeleton.tsx +0 -17
  197. package/src/client/components/TextInput.tsx +0 -58
  198. package/src/client/components/Tooltip.tsx +0 -216
  199. package/src/client/components/charts/useChartLayout.ts +0 -27
  200. package/src/client/components/ui/sheet.LICENSE +0 -21
  201. package/src/client/conversations/ConversationDetailsFrame.tsx +0 -119
  202. package/src/client/conversations/CopyMarkdownButton.tsx +0 -65
  203. package/src/client/pages/automations/AutomationDetailsDrawer.tsx +0 -219
  204. package/src/client/pages/dev/ChartFixtures.tsx +0 -325
  205. package/src/client/pages/dev/ComponentsPage.tsx +0 -899
  206. package/src/client/pages/dev/ConversationFixture.tsx +0 -231
  207. package/src/client/pages/dev/ObjectFixtures.tsx +0 -138
  208. package/src/client/pages/dev/SegmentedFixtures.tsx +0 -59
  209. package/src/client/pages/dev/SelectFixtures.tsx +0 -62
  210. package/src/client/pages/dev/TranscriptActivityFixtures.tsx +0 -206
  211. package/src/client/pages/memory/MemoryDetailsDrawer.tsx +0 -167
  212. package/src/client/pages/system/SandboxSizeSummary.tsx +0 -47
  213. package/src/client/pages/system/SnapshotSummary.tsx +0 -78
@@ -0,0 +1,168 @@
1
+ import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import {
4
+ createContext,
5
+ useContext,
6
+ useId,
7
+ useState,
8
+ useSyncExternalStore,
9
+ type ComponentProps,
10
+ } from "react";
11
+ import { cn } from "@dashboard/lib/utils";
12
+
13
+ /** Open dashboard tooltips at once and keep them open briefly for the pointer to reach them. */
14
+ function TooltipProvider({
15
+ delay = 0,
16
+ closeDelay = 150,
17
+ ...props
18
+ }: TooltipPrimitive.Provider.Props) {
19
+ return (
20
+ <TooltipPrimitive.Provider
21
+ data-slot="tooltip-provider"
22
+ delay={delay}
23
+ closeDelay={closeDelay}
24
+ {...props}
25
+ />
26
+ );
27
+ }
28
+
29
+ /** Link the open popup to its trigger. Base UI leaves this to the app. */
30
+ const TooltipDescriptionContext = createContext<string | undefined>(undefined);
31
+
32
+ /**
33
+ * Wide screens with a fine hover pointer show tooltips. On smaller or touch
34
+ * screens, a tooltip can cover the menu that its trigger opens.
35
+ */
36
+ const TOOLTIP_MEDIA_QUERY =
37
+ "(min-width: 768px) and (hover: hover) and (pointer: fine)";
38
+
39
+ function subscribeToTooltipMedia(onChange: () => void) {
40
+ const media = window.matchMedia(TOOLTIP_MEDIA_QUERY);
41
+ media.addEventListener("change", onChange);
42
+ return () => media.removeEventListener("change", onChange);
43
+ }
44
+
45
+ function tooltipMediaMatches() {
46
+ return window.matchMedia(TOOLTIP_MEDIA_QUERY).matches;
47
+ }
48
+
49
+ /** Own one tooltip's open state. It stays off where tooltips are not shown. */
50
+ function Tooltip({
51
+ disabled,
52
+ onOpenChange,
53
+ open: openProp,
54
+ ...props
55
+ }: TooltipPrimitive.Root.Props) {
56
+ const available = useSyncExternalStore(
57
+ subscribeToTooltipMedia,
58
+ tooltipMediaMatches,
59
+ () => false,
60
+ );
61
+ const id = useId();
62
+ const [openState, setOpenState] = useState(props.defaultOpen ?? false);
63
+ const open = available && (openProp ?? openState);
64
+ return (
65
+ <TooltipDescriptionContext.Provider value={open ? id : undefined}>
66
+ <TooltipPrimitive.Root
67
+ data-slot="tooltip"
68
+ disabled={disabled || !available}
69
+ onOpenChange={(next, details) => {
70
+ setOpenState(next);
71
+ onOpenChange?.(next, details);
72
+ }}
73
+ open={openProp}
74
+ {...props}
75
+ />
76
+ </TooltipDescriptionContext.Provider>
77
+ );
78
+ }
79
+
80
+ /**
81
+ * Show the tooltip on mouse hover or keyboard focus. Touch does not open it.
82
+ * A click keeps it open, so copy and share feedback stays visible.
83
+ */
84
+ function TooltipTrigger({
85
+ closeOnClick = false,
86
+ ...props
87
+ }: TooltipPrimitive.Trigger.Props) {
88
+ const describedBy = useContext(TooltipDescriptionContext);
89
+ return (
90
+ <TooltipPrimitive.Trigger
91
+ aria-describedby={describedBy}
92
+ closeOnClick={closeOnClick}
93
+ data-slot="tooltip-trigger"
94
+ {...props}
95
+ />
96
+ );
97
+ }
98
+
99
+ const tooltipContentVariants = cva(
100
+ "z-50 select-text rounded-md border border-dashboard-border-emphasis bg-dashboard-surface-raised font-sans text-xs shadow-2xl shadow-black/70 outline-none",
101
+ {
102
+ variants: {
103
+ size: {
104
+ /** Selectable detail cards, such as chart buckets and metric breakdowns. */
105
+ default:
106
+ "min-w-36 max-w-lg px-3 py-2 leading-relaxed text-dashboard-text-muted",
107
+ /** One short label for an icon-only control. */
108
+ compact: "px-2.5 py-1.5 leading-none text-dashboard-text",
109
+ },
110
+ },
111
+ defaultVariants: { size: "default" },
112
+ },
113
+ );
114
+
115
+ /** Show tooltip text beside its trigger and keep it inside the viewport. */
116
+ function TooltipContent({
117
+ className,
118
+ side = "top",
119
+ sideOffset = 10,
120
+ align = "center",
121
+ size,
122
+ children,
123
+ ...props
124
+ }: TooltipPrimitive.Popup.Props &
125
+ Pick<TooltipPrimitive.Positioner.Props, "align" | "side" | "sideOffset"> &
126
+ VariantProps<typeof tooltipContentVariants>) {
127
+ const id = useContext(TooltipDescriptionContext);
128
+ return (
129
+ <TooltipPrimitive.Portal>
130
+ <TooltipPrimitive.Positioner
131
+ align={align}
132
+ collisionPadding={8}
133
+ side={side}
134
+ sideOffset={sideOffset}
135
+ className="isolate z-50 data-anchor-hidden:invisible"
136
+ >
137
+ <TooltipPrimitive.Popup
138
+ data-slot="tooltip-content"
139
+ id={id}
140
+ role="tooltip"
141
+ className={cn(tooltipContentVariants({ size }), className)}
142
+ {...props}
143
+ >
144
+ {children}
145
+ </TooltipPrimitive.Popup>
146
+ </TooltipPrimitive.Positioner>
147
+ </TooltipPrimitive.Portal>
148
+ );
149
+ }
150
+
151
+ /** Name what a detail tooltip describes, such as a chart bucket date. */
152
+ function TooltipTitle({ className, ...props }: ComponentProps<"div">) {
153
+ return (
154
+ <div
155
+ className={cn("mb-1 font-semibold text-dashboard-text-muted", className)}
156
+ {...props}
157
+ />
158
+ );
159
+ }
160
+
161
+ export {
162
+ Tooltip,
163
+ TooltipTrigger,
164
+ TooltipContent,
165
+ TooltipTitle,
166
+ TooltipProvider,
167
+ tooltipContentVariants,
168
+ };
@@ -0,0 +1,96 @@
1
+ import * as React from "react";
2
+ import { cn } from "@dashboard/lib/utils";
3
+
4
+ import {
5
+ Collapsible,
6
+ CollapsibleContent,
7
+ CollapsibleTrigger,
8
+ } from "@dashboard/components/ui/collapsible";
9
+ import { ChevronRightIcon } from "lucide-react";
10
+
11
+ function TraceIcon({ className, ...props }: React.ComponentProps<"span">) {
12
+ return (
13
+ <span
14
+ data-slot="trace-icon"
15
+ aria-hidden="true"
16
+ className={cn(
17
+ "flex size-4 shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
18
+ className,
19
+ )}
20
+ {...props}
21
+ />
22
+ );
23
+ }
24
+
25
+ /** Keep one trace row and its details in one open state. */
26
+ function TraceCollapsible({
27
+ className,
28
+ ...props
29
+ }: Omit<React.ComponentProps<typeof Collapsible>, "open"> &
30
+ (
31
+ | { open?: undefined }
32
+ | {
33
+ open: boolean;
34
+ onOpenChange: NonNullable<
35
+ React.ComponentProps<typeof Collapsible>["onOpenChange"]
36
+ >;
37
+ }
38
+ )) {
39
+ return (
40
+ <Collapsible
41
+ data-slot="trace-collapsible"
42
+ className={cn("flex w-full min-w-0 flex-col", className)}
43
+ {...props}
44
+ />
45
+ );
46
+ }
47
+
48
+ /** Render the row button with a chevron that turns while open. */
49
+ function TraceCollapsibleTrigger({
50
+ className,
51
+ children,
52
+ ...props
53
+ }: React.ComponentProps<typeof CollapsibleTrigger>) {
54
+ return (
55
+ <CollapsibleTrigger
56
+ data-slot="trace-collapsible-trigger"
57
+ className={cn(
58
+ "group/trace-collapsible-trigger flex w-fit max-w-full min-w-0 cursor-pointer items-center gap-1 rounded-md px-2 py-1.5 text-left text-dashboard-text-muted transition-colors outline-none hover:bg-dashboard-fill-hover focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-dashboard-focus disabled:cursor-default disabled:hover:bg-transparent",
59
+ className,
60
+ )}
61
+ {...props}
62
+ >
63
+ {children}
64
+ <TraceIcon className="transition-transform group-aria-expanded/trace-collapsible-trigger:rotate-90 motion-reduce:transition-none">
65
+ <ChevronRightIcon className="size-3 text-dashboard-text-faint" />
66
+ </TraceIcon>
67
+ </CollapsibleTrigger>
68
+ );
69
+ }
70
+
71
+ /** Reveal row details in a card under the row title. */
72
+ function TraceCollapsibleContent({
73
+ className,
74
+ children,
75
+ ...props
76
+ }: React.ComponentProps<typeof CollapsibleContent>) {
77
+ return (
78
+ <CollapsibleContent
79
+ data-slot="trace-collapsible-content"
80
+ className="h-(--collapsible-panel-height) min-w-0 overflow-hidden transition-[height] duration-200 data-ending-style:h-0 data-starting-style:h-0 motion-reduce:transition-none"
81
+ {...props}
82
+ >
83
+ <div
84
+ data-slot="trace-collapsible-content-inner"
85
+ className={cn(
86
+ "mt-1.5 ml-6 min-w-0 overflow-hidden rounded-md border border-dashboard-border-subtle bg-dashboard-surface-panel",
87
+ className,
88
+ )}
89
+ >
90
+ {children}
91
+ </div>
92
+ </CollapsibleContent>
93
+ );
94
+ }
95
+
96
+ export { TraceCollapsible, TraceCollapsibleTrigger, TraceCollapsibleContent };
@@ -5,12 +5,14 @@ import { cn } from "../styles";
5
5
  /**
6
6
  * Own the conversation chat frame: one scroll region above one dock.
7
7
  *
8
- * Pages pass `scroll` and `dock` only. Do not invent footer padding, safe-area,
8
+ * Pages pass `header`, `scroll`, and `dock`. Do not invent footer padding, safe-area,
9
9
  * or shell height math outside this component and `ComposerDock`.
10
10
  */
11
11
  export function ChatLayout(props: {
12
12
  className?: string;
13
13
  dock?: ReactNode;
14
+ /** Keep conversation chrome outside the scrolling content. */
15
+ header?: ReactNode;
14
16
  /** When true, keep a taller minimum scroll region for long transcripts. */
15
17
  scrollMinTall?: boolean;
16
18
  scroll: ReactNode;
@@ -20,11 +22,13 @@ export function ChatLayout(props: {
20
22
  return (
21
23
  <div
22
24
  className={cn(
23
- "grid h-full min-h-0 min-w-0 grid-rows-[minmax(0,1fr)_minmax(0,auto)]",
24
- props.scrollMinTall && "grid-rows-[minmax(7rem,1fr)_minmax(0,auto)]",
25
+ "grid h-full min-h-0 min-w-0 grid-rows-[auto_minmax(0,1fr)_minmax(0,auto)]",
26
+ props.scrollMinTall &&
27
+ "grid-rows-[auto_minmax(7rem,1fr)_minmax(0,auto)]",
25
28
  props.className,
26
29
  )}
27
30
  >
31
+ <div className="min-w-0">{props.header}</div>
28
32
  <div
29
33
  aria-label={props.scrollAriaLabel}
30
34
  className={cn(
@@ -4,7 +4,13 @@ import type { ConversationDetailReport } from "@sentry/junior/api/schema";
4
4
 
5
5
  import { Detail, DetailList } from "../components/DetailList";
6
6
  import { StatusChip, type StatusChipTone } from "../components/StatusChip";
7
+ import {
8
+ Collapsible,
9
+ CollapsibleContent,
10
+ CollapsibleTrigger,
11
+ } from "../components/ui/collapsible";
7
12
  import { formatTime } from "../format";
13
+ import { cn, dashboardDisclosureChevronClass } from "../styles";
8
14
  import { MentionPeopleProvider, renderMentionText } from "./transcriptMentions";
9
15
 
10
16
  type ConversationBriefReport = NonNullable<ConversationDetailReport["brief"]>;
@@ -160,16 +166,21 @@ function BriefContentView(props: {
160
166
 
161
167
  function BriefSection(props: { children: ReactNode; title: string }) {
162
168
  return (
163
- <details className="group min-w-0 border-t border-dashboard-border pt-3">
164
- <summary className="flex cursor-pointer list-none items-center gap-2 text-sm font-medium text-dashboard-text [&::-webkit-details-marker]:hidden focus-visible:outline focus-visible:outline-2 focus-visible:outline-dashboard-focus">
169
+ <Collapsible className="min-w-0 border-t border-dashboard-border pt-3">
170
+ <CollapsibleTrigger className="group flex w-full cursor-pointer items-center gap-2 text-left text-sm font-medium text-dashboard-text focus-visible:outline focus-visible:outline-2 focus-visible:outline-dashboard-focus">
165
171
  <ChevronRight
166
172
  aria-hidden="true"
167
- className="size-3.5 shrink-0 text-dashboard-text-muted transition-transform group-open:rotate-90"
173
+ className={cn(
174
+ dashboardDisclosureChevronClass,
175
+ "text-dashboard-text-muted",
176
+ )}
168
177
  />
169
178
  {props.title}
170
- </summary>
171
- <div className="mt-3">{props.children}</div>
172
- </details>
179
+ </CollapsibleTrigger>
180
+ <CollapsibleContent hiddenUntilFound>
181
+ <div className="mt-3">{props.children}</div>
182
+ </CollapsibleContent>
183
+ </Collapsible>
173
184
  );
174
185
  }
175
186
 
@@ -7,7 +7,6 @@ import {
7
7
  CircleDot,
8
8
  CirclePause,
9
9
  CircleX,
10
- LoaderCircle,
11
10
  LockKeyhole,
12
11
  type LucideIcon,
13
12
  } from "lucide-react";
@@ -17,6 +16,7 @@ import {
17
16
  } from "@sentry/junior/api/schema";
18
17
 
19
18
  import type { StatusChipTone } from "../components/StatusChip";
19
+ import { Spinner } from "../components/ui/spinner";
20
20
  import {
21
21
  formatConversationCostTotal,
22
22
  formatRuntime,
@@ -115,7 +115,6 @@ const statusIcons: Partial<Record<string, LucideIcon>> = {
115
115
  error: CircleX,
116
116
  failed: CircleX,
117
117
  paused: CirclePause,
118
- running: LoaderCircle,
119
118
  };
120
119
 
121
120
  const statusIconToneClass: Record<StatusChipTone, string> = {
@@ -129,7 +128,10 @@ const statusIconToneClass: Record<StatusChipTone, string> = {
129
128
 
130
129
  /** Mark a child agent status with one icon and an audible label. */
131
130
  function ChildAgentStatusIcon(props: { status: string }) {
132
- const Icon = statusIcons[props.status] ?? Circle;
131
+ const Icon =
132
+ props.status === "running"
133
+ ? Spinner
134
+ : (statusIcons[props.status] ?? Circle);
133
135
  return (
134
136
  <span className="mt-px grid size-4 shrink-0 place-items-center">
135
137
  <Icon
@@ -137,8 +139,6 @@ function ChildAgentStatusIcon(props: { status: string }) {
137
139
  className={cn(
138
140
  "size-3.5",
139
141
  statusIconToneClass[subagentStatusTone(props.status)],
140
- props.status === "running" &&
141
- "animate-spin motion-reduce:animate-none",
142
142
  )}
143
143
  />
144
144
  <span className="sr-only">{props.status}</span>
@@ -12,7 +12,12 @@ import {
12
12
  } from "react";
13
13
  import { ImagePlus, Send, Square } from "lucide-react";
14
14
 
15
- import { Button } from "../components/Button";
15
+ import { Button } from "../components/ui/button";
16
+ import {
17
+ Tooltip,
18
+ TooltipContent,
19
+ TooltipTrigger,
20
+ } from "../components/ui/tooltip";
16
21
  import { useDashboardOnline } from "../connection";
17
22
  import { cn, dashboardComposerSurfaceClass } from "../styles";
18
23
 
@@ -447,16 +452,25 @@ export const ConversationComposer = memo(function ConversationComposer(
447
452
  )}
448
453
  >
449
454
  <div className="flex min-w-0 items-center gap-3">
450
- <Button
451
- aria-label="Attach images"
452
- disabled={sendLocked || readingImages}
453
- onClick={() => fileInputRef.current?.click()}
454
- size="icon"
455
- title="Attach images (up to 3 MB total)"
456
- type="button"
457
- >
458
- <ImagePlus aria-hidden="true" size={16} />
459
- </Button>
455
+ <Tooltip>
456
+ <TooltipTrigger
457
+ render={
458
+ <Button
459
+ focusableWhenDisabled
460
+ aria-label="Attach images"
461
+ disabled={sendLocked || readingImages}
462
+ onClick={() => fileInputRef.current?.click()}
463
+ size="icon"
464
+ type="button"
465
+ >
466
+ <ImagePlus aria-hidden="true" size={16} />
467
+ </Button>
468
+ }
469
+ />
470
+ <TooltipContent size="compact">
471
+ Attach images (up to 3 MB total)
472
+ </TooltipContent>
473
+ </Tooltip>
460
474
  {props.footerStart}
461
475
  {props.footerStart ? null : (
462
476
  <div className="hidden min-w-0 font-sans text-xs leading-relaxed text-dashboard-text-muted md:block">
@@ -488,7 +502,7 @@ export const ConversationComposer = memo(function ConversationComposer(
488
502
  readingImages
489
503
  }
490
504
  title={sendLocked ? "Sending message" : props.submitLabel}
491
- tone="primary"
505
+ variant="primary"
492
506
  type="submit"
493
507
  >
494
508
  <Send aria-hidden="true" size={14} />