@sentry/junior-dashboard 0.263.0 → 0.265.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 (197) 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 +148 -135
  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 +9 -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/BottomSheet.tsx +26 -18
  14. package/src/client/components/CopyButton.tsx +83 -0
  15. package/src/client/components/DetailsPanel.tsx +133 -0
  16. package/src/client/components/Drawer.tsx +34 -33
  17. package/src/client/components/FilterBar.tsx +16 -31
  18. package/src/client/components/Metric.tsx +33 -23
  19. package/src/client/components/PageContentSkeleton.tsx +1 -1
  20. package/src/client/components/Pagination.tsx +1 -1
  21. package/src/client/components/ParticipantAvatarStack.tsx +40 -36
  22. package/src/client/components/ProfileMenu.tsx +27 -93
  23. package/src/client/components/README.md +101 -64
  24. package/src/client/components/SegmentedNav.tsx +1 -1
  25. package/src/client/components/ShimmerText.tsx +2 -6
  26. package/src/client/components/ThemeSwitcher.tsx +19 -15
  27. package/src/client/components/charts/ActivityChart.tsx +173 -288
  28. package/src/client/components/charts/CacheWrites.tsx +63 -50
  29. package/src/client/components/charts/InputCacheChart.tsx +137 -131
  30. package/src/client/components/charts/README.md +4 -4
  31. package/src/client/components/charts/SystemMetricCharts.tsx +68 -95
  32. package/src/client/components/charts/WorkspaceUsageChart.tsx +42 -62
  33. package/src/client/components/controls/DirectorySortSelect.tsx +3 -3
  34. package/src/client/components/controls/TimeRangeSelector.tsx +10 -15
  35. package/src/client/components/layout/DashboardHeader.tsx +44 -90
  36. package/src/client/components/layout/SecondaryNavigation.tsx +2 -1
  37. package/src/client/components/layout/VisualViewportShell.tsx +2 -2
  38. package/src/client/components/ui/accordion.tsx +77 -0
  39. package/src/client/components/ui/alert-dialog.tsx +89 -0
  40. package/src/client/components/ui/button.tsx +85 -0
  41. package/src/client/components/ui/chart.tsx +74 -0
  42. package/src/client/components/ui/checkbox.tsx +26 -0
  43. package/src/client/components/ui/collapsible.tsx +22 -0
  44. package/src/client/components/ui/field.tsx +49 -0
  45. package/src/client/components/ui/input.tsx +35 -0
  46. package/src/client/components/ui/native-select.tsx +57 -0
  47. package/src/client/components/ui/popover.tsx +67 -0
  48. package/src/client/components/ui/radio-group.tsx +32 -0
  49. package/src/client/components/ui/sheet.tsx +151 -0
  50. package/src/client/components/ui/skeleton.tsx +19 -0
  51. package/src/client/components/ui/table.tsx +80 -0
  52. package/src/client/components/ui/tabs.tsx +75 -0
  53. package/src/client/components/ui/textarea.tsx +17 -0
  54. package/src/client/components/ui/toast.tsx +215 -0
  55. package/src/client/components/ui/toggle-group.tsx +36 -0
  56. package/src/client/components/ui/toggle.tsx +37 -0
  57. package/src/client/components/ui/tooltip.tsx +168 -0
  58. package/src/client/components/ui/trace.tsx +96 -0
  59. package/src/client/components/ui/useSheet.ts +74 -0
  60. package/src/client/conversations/ChatLayout.tsx +7 -3
  61. package/src/client/conversations/ConversationBrief.tsx +17 -6
  62. package/src/client/conversations/ConversationChildAgents.tsx +87 -58
  63. package/src/client/conversations/ConversationComposer.tsx +26 -12
  64. package/src/client/conversations/ConversationDetails.tsx +198 -95
  65. package/src/client/conversations/ConversationEventDetails.tsx +141 -0
  66. package/src/client/conversations/ConversationEventLog.tsx +150 -129
  67. package/src/client/conversations/ConversationHeader.tsx +8 -3
  68. package/src/client/conversations/ConversationHeaderActions.tsx +90 -82
  69. package/src/client/conversations/ConversationHomeList.tsx +1 -1
  70. package/src/client/conversations/ConversationLinkedWork.tsx +118 -0
  71. package/src/client/conversations/ConversationMeta.tsx +111 -92
  72. package/src/client/conversations/ConversationPage.tsx +241 -110
  73. package/src/client/conversations/ConversationSidebar.tsx +48 -29
  74. package/src/client/conversations/ConversationUsageBreakdown.tsx +16 -3
  75. package/src/client/conversations/ConversationWatches.tsx +165 -0
  76. package/src/client/conversations/ConversationWorkspace.tsx +12 -22
  77. package/src/client/conversations/ConversationWorkspaceLoading.tsx +1 -1
  78. package/src/client/conversations/DetailsList.tsx +124 -0
  79. package/src/client/conversations/EventDetails.tsx +42 -8
  80. package/src/client/conversations/ForkConversationButton.tsx +27 -16
  81. package/src/client/conversations/ObjectCard.tsx +20 -8
  82. package/src/client/conversations/PendingMailboxStack.tsx +52 -33
  83. package/src/client/conversations/README.md +93 -19
  84. package/src/client/conversations/ShareConversationButton.tsx +28 -3
  85. package/src/client/conversations/SubagentTranscriptDrawer.tsx +21 -15
  86. package/src/client/conversations/ToolFrame.tsx +36 -52
  87. package/src/client/conversations/TranscriptActivityGroup.tsx +13 -4
  88. package/src/client/conversations/TranscriptAutomationTriggerView.tsx +5 -4
  89. package/src/client/conversations/TranscriptContextEventView.tsx +25 -11
  90. package/src/client/conversations/TranscriptHeadingRow.tsx +7 -7
  91. package/src/client/conversations/TranscriptLoading.tsx +1 -1
  92. package/src/client/conversations/TranscriptMarkdown.tsx +25 -20
  93. package/src/client/conversations/TranscriptMessageContextView.tsx +8 -2
  94. package/src/client/conversations/TranscriptMessageView.tsx +6 -1
  95. package/src/client/conversations/TranscriptReasoningView.tsx +54 -68
  96. package/src/client/conversations/TranscriptSubagentView.tsx +3 -3
  97. package/src/client/conversations/TranscriptTimestamp.tsx +9 -7
  98. package/src/client/conversations/TranscriptToolView.tsx +1 -1
  99. package/src/client/conversations/TranscriptTurnContextView.tsx +99 -27
  100. package/src/client/conversations/TranscriptView.tsx +63 -27
  101. package/src/client/conversations/eventLog.ts +57 -0
  102. package/src/client/conversations/eventTime.ts +60 -0
  103. package/src/client/conversations/queries.ts +29 -0
  104. package/src/client/conversations/transcriptBottomPinning.ts +34 -0
  105. package/src/client/format.ts +5 -0
  106. package/src/client/lib/utils.ts +1 -0
  107. package/src/client/pages/ConnectionsPage.tsx +2 -2
  108. package/src/client/pages/PersonalTokensPage.tsx +4 -4
  109. package/src/client/pages/SettingsPage.tsx +9 -10
  110. package/src/client/pages/admin/ServiceAccountsSection.tsx +2 -2
  111. package/src/client/pages/automations/AutomationCostChart.tsx +50 -71
  112. package/src/client/pages/automations/AutomationDeleteDialog.tsx +87 -0
  113. package/src/client/pages/automations/AutomationDetails.tsx +193 -0
  114. package/src/client/pages/automations/AutomationEditPage.tsx +7 -8
  115. package/src/client/pages/automations/AutomationEditor.tsx +41 -29
  116. package/src/client/pages/automations/AutomationEditorLoading.tsx +1 -1
  117. package/src/client/pages/automations/AutomationEventFields.tsx +202 -119
  118. package/src/client/pages/automations/AutomationExecutionChart.tsx +51 -64
  119. package/src/client/pages/automations/AutomationExecutionStatusChart.tsx +47 -70
  120. package/src/client/pages/automations/AutomationExecutionsPage.tsx +150 -126
  121. package/src/client/pages/automations/AutomationFilters.tsx +189 -74
  122. package/src/client/pages/automations/AutomationLifecycle.tsx +109 -78
  123. package/src/client/pages/automations/AutomationOutcomeFields.tsx +26 -24
  124. package/src/client/pages/automations/AutomationRecentRuns.tsx +143 -0
  125. package/src/client/pages/automations/AutomationRow.tsx +12 -138
  126. package/src/client/pages/automations/AutomationRunDetails.tsx +307 -0
  127. package/src/client/pages/automations/AutomationRunsPage.tsx +119 -94
  128. package/src/client/pages/automations/AutomationScheduleFields.tsx +51 -51
  129. package/src/client/pages/automations/AutomationStatus.tsx +201 -0
  130. package/src/client/pages/automations/AutomationVersionsPage.tsx +65 -28
  131. package/src/client/pages/automations/AutomationsPage.tsx +80 -68
  132. package/src/client/pages/automations/AutomationsPageLayout.tsx +46 -14
  133. package/src/client/pages/automations/README.md +57 -0
  134. package/src/client/pages/automations/TriggerFilters.tsx +22 -0
  135. package/src/client/pages/automations/automationFormat.ts +37 -23
  136. package/src/client/pages/code/CodeActivityChart.tsx +59 -101
  137. package/src/client/pages/code/CodePage.tsx +52 -55
  138. package/src/client/pages/code/RepositoryPage.tsx +6 -8
  139. package/src/client/pages/locations/LocationActivityChart.tsx +53 -70
  140. package/src/client/pages/locations/LocationDirectoryActivityChart.tsx +60 -80
  141. package/src/client/pages/memory/MemoryCostChart.tsx +79 -103
  142. package/src/client/pages/memory/MemoryDetails.tsx +218 -0
  143. package/src/client/pages/memory/MemoryPage.tsx +168 -112
  144. package/src/client/pages/memory/MemoryPageLayout.tsx +33 -9
  145. package/src/client/pages/memory/MemoryTimeline.tsx +46 -69
  146. package/src/client/pages/memory/memoryRecord.ts +1 -1
  147. package/src/client/pages/people/ContributionGrid.tsx +23 -16
  148. package/src/client/pages/people/PeopleActivityChart.tsx +68 -107
  149. package/src/client/pages/people/ProfileCodeChanges.tsx +5 -5
  150. package/src/client/pages/system/BaseSandboxCard.tsx +1 -1
  151. package/src/client/pages/system/ConversationActivityChart.tsx +49 -67
  152. package/src/client/pages/system/GuardianActivity.tsx +1 -2
  153. package/src/client/pages/system/PluginBarChart.tsx +106 -87
  154. package/src/client/pages/system/PluginReportRecordSet.tsx +25 -24
  155. package/src/client/pages/system/README.md +23 -0
  156. package/src/client/pages/system/SystemNavigation.tsx +5 -1
  157. package/src/client/pages/system/WorkspaceDeleteDialog.tsx +111 -0
  158. package/src/client/pages/system/WorkspaceDetails.tsx +200 -43
  159. package/src/client/pages/system/WorkspaceEditor.tsx +59 -61
  160. package/src/client/pages/system/WorkspaceFormPage.tsx +23 -47
  161. package/src/client/pages/system/WorkspaceList.tsx +20 -30
  162. package/src/client/pages/system/WorkspacesPage.tsx +117 -119
  163. package/src/client/pages/system/sandboxSize.ts +8 -0
  164. package/src/client/pages/system/workspaceQueries.ts +53 -0
  165. package/src/client/pages/user/PluginUserPage.tsx +51 -2
  166. package/src/client/pages/user/pluginUserPageData.ts +1 -6
  167. package/src/client/styles.ts +4 -0
  168. package/src/client.tsx +7 -1
  169. package/src/mock-reporting/automation-collection.ts +4 -2
  170. package/src/mock-reporting/fixtures.ts +23 -7
  171. package/src/mock-reporting/routes.ts +12 -0
  172. package/src/mock-reporting/watches.ts +94 -0
  173. package/src/shell.ts +4 -9
  174. package/src/tailwind.css +77 -10
  175. package/src/client/components/Button.tsx +0 -118
  176. package/src/client/components/Field.tsx +0 -53
  177. package/src/client/components/SegmentedTabs.tsx +0 -119
  178. package/src/client/components/Select.tsx +0 -52
  179. package/src/client/components/Sheet.LICENSE +0 -21
  180. package/src/client/components/Sheet.tsx +0 -141
  181. package/src/client/components/Skeleton.tsx +0 -17
  182. package/src/client/components/TextInput.tsx +0 -58
  183. package/src/client/components/Tooltip.tsx +0 -216
  184. package/src/client/components/charts/useChartLayout.ts +0 -27
  185. package/src/client/conversations/ConversationDetailsFrame.tsx +0 -91
  186. package/src/client/conversations/CopyMarkdownButton.tsx +0 -65
  187. package/src/client/pages/automations/AutomationDetailsDrawer.tsx +0 -219
  188. package/src/client/pages/dev/ChartFixtures.tsx +0 -325
  189. package/src/client/pages/dev/ComponentsPage.tsx +0 -899
  190. package/src/client/pages/dev/ConversationFixture.tsx +0 -231
  191. package/src/client/pages/dev/ObjectFixtures.tsx +0 -138
  192. package/src/client/pages/dev/SegmentedFixtures.tsx +0 -59
  193. package/src/client/pages/dev/SelectFixtures.tsx +0 -62
  194. package/src/client/pages/dev/TranscriptActivityFixtures.tsx +0 -206
  195. package/src/client/pages/memory/MemoryDetailsDrawer.tsx +0 -167
  196. package/src/client/pages/system/SandboxSizeSummary.tsx +0 -47
  197. package/src/client/pages/system/SnapshotSummary.tsx +0 -78
@@ -1,899 +0,0 @@
1
- import { FormNotice } from "../../components/FormNotice";
2
- import { SearchInput } from "../../components/SearchInput";
3
- import { Select } from "../../components/Select";
4
- import { SelectFixtures } from "./SelectFixtures";
5
- import { ObjectFixtures } from "./ObjectFixtures";
6
- import { ChartFixtures } from "./ChartFixtures";
7
- import { SegmentedNavFixture, SegmentedTabsFixture } from "./SegmentedFixtures";
8
- import {
9
- ConversationFixture,
10
- MessageAttachmentsFixture,
11
- } from "./ConversationFixture";
12
- import {
13
- SubagentCardFixture,
14
- ToolCallGallery,
15
- } from "./TranscriptActivityFixtures";
16
- import { ObjectCard } from "../../conversations/ObjectCard";
17
- import { AutomationCard } from "../../components/AutomationCard";
18
- import {
19
- Activity,
20
- ArchiveRestore,
21
- Bot,
22
- ChevronRight,
23
- CircleAlert,
24
- Copy,
25
- MessageSquare,
26
- Timer,
27
- Trash2,
28
- } from "lucide-react";
29
- import { useState, type ReactNode } from "react";
30
- import { createPortal } from "react-dom";
31
- import { Link, Navigate, Route, Routes } from "react-router";
32
-
33
- import { Button, ToggleButton } from "../../components/Button";
34
- import {
35
- TimeRangeSelector,
36
- type TimeRangeDays,
37
- } from "../../components/controls/TimeRangeSelector";
38
- import { EmptyTelemetry } from "../../components/EmptyTelemetry";
39
- import { Drawer } from "../../components/Drawer";
40
- import { BottomSheet } from "../../components/BottomSheet";
41
- import { Field } from "../../components/Field";
42
- import { Card } from "../../components/layout/Card";
43
- import { DashboardChromeProvider } from "../../components/layout/DashboardChrome";
44
- import { DashboardHeader } from "../../components/layout/DashboardHeader";
45
- import { PageHeader } from "../../components/layout/PageHeader";
46
- import { MetricList, MetricValue } from "../../components/Metric";
47
- import { Notice, NoticeAction } from "../../components/Notice";
48
- import { PageContentSkeleton } from "../../components/PageContentSkeleton";
49
- import { ActorAvatar } from "../../components/ActorAvatar";
50
- import { ParticipantAvatarStack } from "../../components/ParticipantAvatarStack";
51
- import { StatCard } from "../../components/metrics/StatCard";
52
- import { StatusChip } from "../../components/StatusChip";
53
- import { StatusDot } from "../../components/StatusDot";
54
- import { TextArea, TextInput } from "../../components/TextInput";
55
- import { ThemeSwitcher } from "../../components/ThemeSwitcher";
56
- import { TranscriptMarkdown } from "../../conversations/TranscriptMarkdown";
57
- import { TranscriptText } from "../../conversations/TranscriptText";
58
- import { TranscriptMessageShell } from "../../conversations/TranscriptMessageShell";
59
- import { cn, dashboardContainerClass } from "../../styles";
60
-
61
- export type GallerySectionId = "foundations" | "charts" | "transcripts";
62
-
63
- export type GallerySectionMeta = {
64
- description: string;
65
- id: GallerySectionId;
66
- title: string;
67
- };
68
-
69
- /** Catalog of gallery sections used by the index and visual scenarios. */
70
- export const GALLERY_SECTIONS: readonly GallerySectionMeta[] = [
71
- {
72
- description: "Buttons, forms, status chips, metrics, and empty states.",
73
- id: "foundations",
74
- title: "Foundations",
75
- },
76
- {
77
- description: "Production chart components with deterministic fixtures.",
78
- id: "charts",
79
- title: "Charts",
80
- },
81
- {
82
- description: "Markdown, event notifications, and transcript tool states.",
83
- id: "transcripts",
84
- title: "Transcripts",
85
- },
86
- ] as const;
87
-
88
- const EVENT_NOTIFICATION = `[event notification]
89
-
90
- A subscribed resource changed.
91
-
92
- Handling:
93
- - This is a subscribed conversation update, not a user-authored command.
94
- - Use the subscription intent to decide whether this event warrants action or a visible reply. Otherwise, stay silent.
95
-
96
- Subscription:
97
- - resource: GitHub PR getsentry/junior#999
98
- - event: checks.failed
99
- - intent: watch CI and report regressions
100
-
101
- Trusted event summary:
102
- CI failed on workflow test.`;
103
-
104
- const GFM_SAMPLE = `## Hard breaks
105
-
106
- line one
107
- line two
108
- line three
109
-
110
- ## Lists and emphasis
111
-
112
- - **bold item**
113
- - _italic item_
114
- - inline \`code\` and a [safe link](https://docs.sentry.io)
115
-
116
- 1. first
117
- 2. second
118
-
119
- ## Table
120
-
121
- | Service | Status | p95 |
122
- | --- | :---: | ---: |
123
- | **relay** | healthy | 42ms |
124
- | snuba | degraded | 180ms |
125
- | \`ingest\` | healthy | 31ms |
126
-
127
- ## Wide table
128
-
129
- | Service | Region | Owner | Deploy | Status | p50 | p95 | p99 | Errors | Notes |
130
- | --- | --- | --- | --- | :---: | ---: | ---: | ---: | ---: | --- |
131
- | **relay** | us-central1 | platform | payments-v42 | healthy | 18ms | 42ms | 91ms | 0.1% | baseline |
132
- | snuba | us-central1 | data | snuba-nightly | degraded | 64ms | 180ms | 420ms | 0.8% | queue pressure |
133
- | \`ingest\` | europe-west3 | pipeline | ingest-2026.08 | healthy | 12ms | 31ms | 77ms | 0.2% | within budget |
134
- | checkout | us-west1 | payments | payments-v42 | degraded | 210ms | **890ms** | 1.4s | 0.5% | post-deploy spike |
135
-
136
- Paragraph after a blank line stays a paragraph.`;
137
-
138
- const MIXED_ASSISTANT = `I checked the PR.
139
-
140
- Findings:
141
- - the notifier stores real newlines
142
- - the dashboard preserves single breaks as \`<br>\`
143
-
144
- See https://docs.sentry.io for product docs.`;
145
-
146
- /** Config-gated component gallery with one page per category. */
147
- export function ComponentsPage() {
148
- return (
149
- <Routes>
150
- <Route element={<GalleryIndexPage />} index />
151
- <Route element={<FoundationsGalleryPage />} path="foundations" />
152
- <Route element={<ChartsGalleryPage />} path="charts" />
153
- <Route element={<TranscriptsGalleryPage />} path="transcripts" />
154
- <Route element={<Navigate replace to="/dev" />} path="*" />
155
- </Routes>
156
- );
157
- }
158
-
159
- function GalleryIndexPage() {
160
- return (
161
- <GalleryShell
162
- description="Reusable dashboard fixtures. Open one section for manual checks or focused visual review."
163
- title="Component gallery"
164
- >
165
- <div className="grid gap-3">
166
- {GALLERY_SECTIONS.map((section) => (
167
- <Link
168
- className="group grid min-w-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-3 rounded-lg border border-dashboard-border bg-dashboard-fill-faint px-4 py-4 no-underline transition-colors hover:border-dashboard-border-emphasis hover:bg-dashboard-fill-soft"
169
- key={section.id}
170
- to={`/dev/${section.id}`}
171
- >
172
- <div className="min-w-0">
173
- <div className="font-display text-lg font-medium text-dashboard-text">
174
- {section.title}
175
- </div>
176
- <p className="mt-1 mb-0 text-sm text-dashboard-text-muted">
177
- {section.description}
178
- </p>
179
- </div>
180
- <ChevronRight
181
- aria-hidden="true"
182
- className="shrink-0 text-dashboard-text-muted transition-transform group-hover:translate-x-0.5 group-hover:text-dashboard-text"
183
- size={18}
184
- />
185
- </Link>
186
- ))}
187
- </div>
188
- </GalleryShell>
189
- );
190
- }
191
-
192
- function FoundationsGalleryPage() {
193
- const [range, setRange] = useState<TimeRangeDays>(30);
194
- const [pressed, setPressed] = useState(true);
195
- const [navigationOpen, setNavigationOpen] = useState(false);
196
- const [drawerOpen, setDrawerOpen] = useState(false);
197
- const [sheetOpen, setSheetOpen] = useState(false);
198
- const [nestedDrawerOpen, setNestedDrawerOpen] = useState(false);
199
- const [searchQuery, setSearchQuery] = useState("deploy failure");
200
-
201
- return (
202
- <GalleryShell
203
- description="Shared actions, forms, status chips, metrics, and empty states."
204
- sectionId="foundations"
205
- title="Foundations"
206
- >
207
- <Fixture title="Editor controls">
208
- <Field
209
- label="Instruction"
210
- htmlFor="gallery-instruction"
211
- error="Enter an instruction."
212
- >
213
- <TextArea
214
- prose
215
- id="gallery-instruction"
216
- aria-invalid
217
- aria-describedby="gallery-instruction-error"
218
- />
219
- </Field>
220
- <Field label="Repeat" htmlFor="gallery-repeat">
221
- <TextInput
222
- size="comfortable"
223
- aria-label="Resource identifier"
224
- defaultValue="getsentry/junior#42"
225
- />
226
- <Select id="gallery-repeat">
227
- <option>Every week</option>
228
- </Select>
229
- </Field>
230
- <Button tone="primary">Save changes</Button>
231
- <FormNotice title="This automation changed while you were editing.">
232
- Your edits are still here. Review the latest version before saving.
233
- </FormNotice>
234
- </Fixture>
235
- <Fixture title="Select controls">
236
- <SelectFixtures />
237
- </Fixture>
238
- <Fixture title="Conversation navigation">
239
- <DashboardChromeProvider>
240
- <DashboardHeader
241
- mobileNavigationOpen={navigationOpen}
242
- navItems={[
243
- { key: "code", label: "Code", to: "/code" },
244
- { key: "system", label: "System", to: "/system" },
245
- ]}
246
- onMobileNavigationOpenChange={setNavigationOpen}
247
- workspaceActive
248
- />
249
- </DashboardChromeProvider>
250
- </Fixture>
251
- <Fixture title="Segmented tabs">
252
- <SegmentedTabsFixture />
253
- </Fixture>
254
- <Fixture title="Segmented page links">
255
- <SegmentedNavFixture />
256
- </Fixture>
257
- <Fixture title="Narrow details drawer">
258
- <Button onClick={() => setDrawerOpen(true)}>Open details</Button>
259
- {drawerOpen ? (
260
- <Drawer
261
- closeLabel="Close gallery details"
262
- header={
263
- <h2
264
- id="gallery-drawer-title"
265
- className="m-0 text-lg font-semibold"
266
- >
267
- Conversation details
268
- </h2>
269
- }
270
- onClose={() => setDrawerOpen(false)}
271
- openKey="gallery-details"
272
- titleId="gallery-drawer-title"
273
- width="narrow"
274
- >
275
- <p className="m-0 text-sm leading-relaxed text-dashboard-text-muted">
276
- Linked work, the Brief, participants, and usage.
277
- </p>
278
- <Button onClick={() => setNestedDrawerOpen(true)}>
279
- Open nested details
280
- </Button>
281
- {nestedDrawerOpen
282
- ? createPortal(
283
- <Drawer
284
- closeLabel="Close nested details"
285
- header={
286
- <h2
287
- id="gallery-nested-title"
288
- className="m-0 text-lg font-semibold"
289
- >
290
- Event details
291
- </h2>
292
- }
293
- onClose={() => setNestedDrawerOpen(false)}
294
- openKey="gallery-nested"
295
- titleId="gallery-nested-title"
296
- >
297
- <p className="m-0 text-sm text-dashboard-text-muted">
298
- Escape closes this drawer and returns focus to the parent
299
- drawer.
300
- </p>
301
- </Drawer>,
302
- document.body,
303
- )
304
- : null}
305
- </Drawer>
306
- ) : null}
307
- </Fixture>
308
- <Fixture title="Bottom sheet">
309
- <Button onClick={() => setSheetOpen(true)}>Open bottom sheet</Button>
310
- {sheetOpen ? (
311
- <BottomSheet
312
- label="Gallery details"
313
- onClose={() => setSheetOpen(false)}
314
- >
315
- <p className="m-0 p-4 pb-[max(1rem,env(safe-area-inset-bottom))] text-sm text-dashboard-text-muted">
316
- Swipe the handle down, tap outside, or press Escape to return to
317
- the page.
318
- </p>
319
- </BottomSheet>
320
- ) : null}
321
- </Fixture>
322
- <Fixture title="Theme">
323
- <ThemeSwitcher className="max-w-64" />
324
- </Fixture>
325
- <Fixture title="Color tokens">
326
- <div className="grid gap-4">
327
- <TokenSwatchRow
328
- label="Canvas / surface"
329
- swatches={[
330
- { className: "bg-dashboard-bg", label: "bg" },
331
- { className: "bg-dashboard-bg-elevated", label: "elevated" },
332
- { className: "bg-dashboard-surface-panel", label: "panel" },
333
- { className: "bg-dashboard-surface-active", label: "active" },
334
- { className: "bg-dashboard-surface-raised", label: "raised" },
335
- { className: "bg-dashboard-surface-hover", label: "hover" },
336
- { className: "bg-dashboard-control", label: "control" },
337
- { className: "bg-dashboard-ink", label: "ink" },
338
- ]}
339
- />
340
- <TokenSwatchRow
341
- label="Text"
342
- swatches={[
343
- { className: "bg-dashboard-text", label: "text" },
344
- { className: "bg-dashboard-text-muted", label: "muted" },
345
- { className: "bg-dashboard-text-subtle", label: "subtle" },
346
- { className: "bg-dashboard-text-faint", label: "faint" },
347
- ]}
348
- />
349
- <TokenSwatchRow
350
- label="Accent"
351
- swatches={[
352
- { className: "bg-dashboard-accent", label: "accent" },
353
- { className: "bg-dashboard-accent-text", label: "accent text" },
354
- { className: "bg-dashboard-accent/10", label: "accent / 10" },
355
- { className: "bg-dashboard-focus", label: "focus" },
356
- ]}
357
- />
358
- <TokenSwatchRow
359
- label="Border"
360
- swatches={[
361
- {
362
- className:
363
- "bg-transparent border-2 border-dashboard-border-subtle",
364
- label: "subtle",
365
- },
366
- {
367
- className: "bg-transparent border-2 border-dashboard-border",
368
- label: "border",
369
- },
370
- {
371
- className:
372
- "bg-transparent border-2 border-dashboard-border-strong",
373
- label: "strong",
374
- },
375
- {
376
- className:
377
- "bg-transparent border-2 border-dashboard-border-emphasis",
378
- label: "emphasis",
379
- },
380
- {
381
- className:
382
- "bg-transparent border-2 border-dashboard-border-interactive",
383
- label: "interactive",
384
- },
385
- ]}
386
- />
387
- <TokenSwatchRow
388
- label="Fill / overlay"
389
- swatches={[
390
- { className: "bg-dashboard-fill-faint", label: "faint" },
391
- { className: "bg-dashboard-fill-soft", label: "soft" },
392
- { className: "bg-dashboard-fill-hover", label: "hover" },
393
- { className: "bg-dashboard-fill-strong", label: "strong" },
394
- { className: "bg-dashboard-overlay-soft", label: "overlay soft" },
395
- { className: "bg-dashboard-overlay", label: "overlay" },
396
- ]}
397
- />
398
- </div>
399
- </Fixture>
400
- <Fixture title="Buttons and controls">
401
- <div className="grid gap-4">
402
- <div className="flex flex-wrap items-center gap-3">
403
- <Button>
404
- <Copy aria-hidden="true" size={14} />
405
- Copy
406
- </Button>
407
- <Button disabled>Disabled</Button>
408
- <Button tone="danger">
409
- <Trash2 aria-hidden="true" size={14} />
410
- Remove
411
- </Button>
412
- <Button disabled tone="danger">
413
- Remove disabled
414
- </Button>
415
- <Button aria-label="Bot action" size="icon">
416
- <Bot aria-hidden="true" size={16} />
417
- </Button>
418
- <Button aria-label="Delete action" size="icon" tone="danger">
419
- <Trash2 aria-hidden="true" size={16} />
420
- </Button>
421
- </div>
422
- <div className="flex flex-wrap items-center gap-3">
423
- <ToggleButton
424
- pressed={pressed}
425
- variant="pill"
426
- onClick={() => setPressed((value) => !value)}
427
- >
428
- Toggle
429
- </ToggleButton>
430
- <ToggleButton
431
- pressed={!pressed}
432
- variant="text"
433
- onClick={() => setPressed((value) => !value)}
434
- >
435
- Alternate
436
- </ToggleButton>
437
- <ToggleButton pressed variant="segment">
438
- 30d
439
- </ToggleButton>
440
- <ToggleButton pressed={false} variant="segment">
441
- 90d
442
- </ToggleButton>
443
- <TimeRangeSelector onChange={setRange} value={range} />
444
- </div>
445
- </div>
446
- </Fixture>
447
- <Fixture title="Forms">
448
- <div className="grid max-w-xl gap-4">
449
- <Card className="mb-0" padding="md" variant="raised">
450
- <Field
451
- help="Lowercase name used when agents switch into this Workspace."
452
- htmlFor="gallery-workspace-name"
453
- label="Name"
454
- >
455
- <TextInput
456
- defaultValue="sentry"
457
- id="gallery-workspace-name"
458
- placeholder="sentry"
459
- />
460
- </Field>
461
- </Card>
462
- <div className="grid gap-3 sm:grid-cols-[minmax(0,8.5rem)_minmax(0,1fr)]">
463
- <Field htmlFor="gallery-provider" label="Provider" size="compact">
464
- <TextInput
465
- defaultValue="github"
466
- id="gallery-provider"
467
- placeholder="github"
468
- />
469
- </Field>
470
- <Field
471
- htmlFor="gallery-repository"
472
- label="Repository"
473
- size="compact"
474
- >
475
- <TextInput
476
- defaultValue="getsentry/sentry"
477
- id="gallery-repository"
478
- placeholder="getsentry/sentry"
479
- />
480
- </Field>
481
- </div>
482
- <Field
483
- help="Runs once while Junior builds the reusable snapshot."
484
- htmlFor="gallery-setup-script"
485
- label="Setup script"
486
- >
487
- <TextArea
488
- defaultValue={'pnpm install --dir "$JUNIOR_REPOS_ROOT/sentry"'}
489
- id="gallery-setup-script"
490
- />
491
- </Field>
492
- <TextInput
493
- aria-label="Disabled text input"
494
- disabled
495
- value="read only"
496
- />
497
- <SearchInput
498
- label="Search conversations"
499
- onChange={setSearchQuery}
500
- placeholder="Search conversations…"
501
- value={searchQuery}
502
- />
503
- </div>
504
- </Fixture>
505
- <Fixture title="Status labels">
506
- <div className="flex flex-wrap items-center gap-x-5 gap-y-3">
507
- <StatusChip tone="neutral">private</StatusChip>
508
- <StatusChip tone="success">completed</StatusChip>
509
- <StatusChip tone="danger">failed</StatusChip>
510
- <StatusChip tone="warning">blocked</StatusChip>
511
- <StatusChip tone="info">preference</StatusChip>
512
- <StatusChip tone="accent">knowledge</StatusChip>
513
- <StatusChip size="compact" tone="warning">
514
- Trigger unavailable
515
- </StatusChip>
516
- </div>
517
- </Fixture>
518
- <Fixture title="Notices">
519
- <div className="grid max-w-md gap-2">
520
- <Notice
521
- action={<NoticeAction>Undo</NoticeAction>}
522
- detail="Investigate checkout latency"
523
- icon={ArchiveRestore}
524
- title="Conversation archived"
525
- />
526
- <Notice
527
- action={<NoticeAction tone="error">Dismiss</NoticeAction>}
528
- detail="Investigate checkout latency"
529
- icon={CircleAlert}
530
- title="Could not archive"
531
- tone="error"
532
- />
533
- </div>
534
- </Fixture>
535
- <Fixture title="Actor avatars">
536
- <div className="flex items-center gap-4">
537
- <ActorAvatar
538
- name="Ada Lovelace"
539
- imageUrl="/_junior/dashboard/avatar.png"
540
- size="detail"
541
- />
542
- <ActorAvatar name="Grace Hopper" size="detail" />
543
- <ActorAvatar
544
- name="Alan Turing"
545
- imageUrl="/missing-avatar.png"
546
- size="list"
547
- />
548
- </div>
549
- </Fixture>
550
- <Fixture title="Participant avatars">
551
- <div className="flex flex-wrap items-center gap-8">
552
- <ParticipantAvatarStack
553
- participants={[
554
- { email: "ada@example.com", fullName: "Ada Lovelace" },
555
- { email: "grace@example.com", fullName: "Grace Hopper" },
556
- { email: "alan@example.com", fullName: "Alan Turing" },
557
- { email: "katherine@example.com", fullName: "Katherine Johnson" },
558
- ]}
559
- size="list"
560
- />
561
- <ParticipantAvatarStack
562
- participants={[
563
- { email: "ada@example.com", fullName: "Ada Lovelace" },
564
- { email: "grace@example.com", fullName: "Grace Hopper" },
565
- { email: "alan@example.com", fullName: "Alan Turing" },
566
- { email: "katherine@example.com", fullName: "Katherine Johnson" },
567
- ]}
568
- size="detail"
569
- />
570
- </div>
571
- </Fixture>
572
- <Fixture title="Status dots">
573
- <div className="flex flex-wrap items-center gap-3">
574
- <StatusDot label="completed" tone="success" />
575
- <StatusDot label="failed" tone="danger" />
576
- <StatusDot label="blocked" tone="warning" />
577
- <StatusDot label="idle" tone="neutral" />
578
- <StatusDot label="info" tone="info" />
579
- <StatusDot label="accent" tone="accent" />
580
- </div>
581
- </Fixture>
582
- <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
583
- <StatCard
584
- detail="Across the selected period"
585
- icon={MessageSquare}
586
- label="Conversations"
587
- value="1,284"
588
- />
589
- <StatCard
590
- detail="94% completed successfully"
591
- icon={Activity}
592
- label="Completed"
593
- value="1,207"
594
- />
595
- <StatCard
596
- detail="Cumulative agent runtime"
597
- icon={Timer}
598
- label="Runtime"
599
- value="18.4h"
600
- />
601
- <StatCard
602
- detail="Model and tool workers"
603
- icon={Bot}
604
- label="Active agents"
605
- value="7"
606
- />
607
- </div>
608
- <Fixture title="Page loading">
609
- <PageContentSkeleton label="Loading example" variant="stats" />
610
- </Fixture>
611
- <Fixture title="Metadata and empty state">
612
- <div className="grid gap-4">
613
- <MetricList
614
- items={[
615
- {
616
- content: (
617
- <MetricValue
618
- tooltip={[
619
- { label: "input", value: "12.4k" },
620
- { label: "output", value: "3.1k" },
621
- ]}
622
- >
623
- 15.5k tokens
624
- </MetricValue>
625
- ),
626
- key: "tokens",
627
- },
628
- { content: <MetricValue>$0.42</MetricValue>, key: "cost" },
629
- { content: <MetricValue>38s</MetricValue>, key: "duration" },
630
- ]}
631
- />
632
- <EmptyTelemetry>
633
- No activity was recorded for this period.
634
- </EmptyTelemetry>
635
- </div>
636
- </Fixture>
637
- </GalleryShell>
638
- );
639
- }
640
-
641
- function ChartsGalleryPage() {
642
- return (
643
- <GalleryShell
644
- description="Production chart components rendered with deterministic fixtures."
645
- sectionId="charts"
646
- title="Charts"
647
- >
648
- <ChartFixtures />
649
- </GalleryShell>
650
- );
651
- }
652
-
653
- function TranscriptsGalleryPage() {
654
- return (
655
- <GalleryShell
656
- description="Markdown, event notifications, and transcript role treatments."
657
- sectionId="transcripts"
658
- title="Transcripts"
659
- >
660
- <Fixture title="Conversation spacing">
661
- <ConversationFixture />
662
- </Fixture>
663
- <Fixture title="Message attachments (mock reporting)">
664
- <MessageAttachmentsFixture />
665
- </Fixture>
666
- <Fixture title="Object visual language">
667
- <ObjectFixtures />
668
- </Fixture>
669
- <Fixture title="Object annotations">
670
- <ObjectCard
671
- card={{
672
- kind: "object",
673
- objectType: "code_change",
674
- plugin: "github",
675
- key: "getsentry/junior#1200",
676
- label: "getsentry/junior#1200",
677
- title: "Use object annotations for reply cards",
678
- status: "open",
679
- displayType: "Pull request",
680
- sourceUpdatedAt: "2026-09-25T13:45:00Z",
681
- facts: {
682
- type: "code_change",
683
- author: "alex",
684
- review: "changes_requested",
685
- checks: { passed: 12, failed: 1, pending: 0 },
686
- reviewers: ["sam"],
687
- mergeable: false,
688
- sourceBranch: "feature/object-cards",
689
- targetBranch: "main",
690
- changedFiles: 8,
691
- additions: 120,
692
- deletions: 30,
693
- },
694
- url: "https://github.com/getsentry/junior/pull/1200",
695
- }}
696
- />
697
- <ObjectCard
698
- card={{
699
- kind: "object",
700
- objectType: "task",
701
- plugin: "linear",
702
- key: "ENG-123",
703
- label: "ENG-123",
704
- title: "Keep background annotation updates out of the next reply",
705
- status: "In Progress",
706
- facts: {
707
- type: "task",
708
- assignees: ["Sam"],
709
- priority: "High",
710
- project: "Conversation quality",
711
- cycle: "September",
712
- dueDate: "2026-09-30",
713
- labels: ["UX", "Reliability"],
714
- },
715
- url: "https://linear.app/example/issue/ENG-123",
716
- }}
717
- />
718
- <ObjectCard
719
- card={{
720
- kind: "object",
721
- objectType: "deployment",
722
- displayType: "Deployment",
723
- plugin: "vercel",
724
- key: "dpl_example",
725
- label: "dpl_example",
726
- title: "junior-docs.vercel.app",
727
- status: "READY",
728
- url: "https://junior-docs.vercel.app",
729
- facts: {
730
- type: "deployment",
731
- environment: "production",
732
- project: "junior-docs",
733
- revision: "ca37e26a9",
734
- branch: "main",
735
- },
736
- }}
737
- />
738
- <ObjectCard
739
- card={{
740
- kind: "object",
741
- objectType: "item",
742
- plugin: "example",
743
- key: "note",
744
- label: "note",
745
- title: "A saved item without a source link",
746
- url: null,
747
- }}
748
- />
749
- </Fixture>
750
- <Fixture title="Automation in a reply">
751
- <div className="max-w-[52.5rem]">
752
- <TranscriptMessageShell actor="Junior" role="assistant">
753
- <span className="text-sm font-semibold text-dashboard-accent-text">
754
- Junior
755
- </span>
756
- <TranscriptText
757
- mentions={[]}
758
- role="assistant"
759
- text={
760
- "Your reminder is set.\n\nI'll remind you to drink water every 30 minutes until you ask me to stop."
761
- }
762
- />
763
- <AutomationCard
764
- card={{
765
- id: "sched_0123456789abcdef0123456789abcdef",
766
- title: "Drink water",
767
- instruction:
768
- "Remind the user to drink water with a short friendly message in this conversation. Then create another one-off reminder after 30 minutes.",
769
- trigger: "In 30 minutes",
770
- warning: null,
771
- }}
772
- />
773
- </TranscriptMessageShell>
774
- </div>
775
- </Fixture>
776
- <Fixture title="Automation card states">
777
- <AutomationCard
778
- card={{
779
- id: "sched_0123456789abcdef0123456789abcdef",
780
- title: "Drink water reminder",
781
- status: "active",
782
- instruction: "Remind the user to drink water in this conversation.",
783
- trigger: "Sep 23, 2026, 9:30 AM · America/Los_Angeles",
784
- warning: null,
785
- }}
786
- />
787
- <AutomationCard
788
- card={{
789
- id: "evt_0ffb0d2027d4b7600b64287bd6dc2b14",
790
- title:
791
- "Review automated fixes across the JavaScript SDK repositories",
792
- instruction:
793
- "Review Sentry PRs. Close invalid fixes and correct valid ones. Post in #proj-junior only when ready for human merge.",
794
- trigger:
795
- 'getsentry/junior · pull_request.opened · author = "sentry[bot]"',
796
- warning: null,
797
- }}
798
- />
799
- <AutomationCard
800
- card={{
801
- id: "scheduled-1",
802
- title: "Weekly release digest",
803
- status: "blocked",
804
- instruction:
805
- "Summarize the week's releases and send me the digest.",
806
- trigger: "Every Friday at 09:00 · America/Los_Angeles",
807
- warning: "Connect your GitHub account to resume this automation.",
808
- }}
809
- />
810
- </Fixture>
811
- <Fixture title="Event notification">
812
- <TranscriptMarkdown compact text={EVENT_NOTIFICATION} />
813
- </Fixture>
814
- <Fixture title="GFM sample">
815
- <TranscriptMarkdown text={GFM_SAMPLE} />
816
- </Fixture>
817
- <Fixture title="TranscriptText assistant">
818
- <TranscriptText mentions={[]} role="assistant" text={MIXED_ASSISTANT} />
819
- </Fixture>
820
- <Fixture title="TranscriptText user">
821
- <TranscriptText mentions={[]} role="user" text={EVENT_NOTIFICATION} />
822
- </Fixture>
823
- <Fixture title="Tool calls">
824
- <ToolCallGallery />
825
- </Fixture>
826
- <Fixture title="Subagent cards">
827
- <SubagentCardFixture />
828
- </Fixture>
829
- </GalleryShell>
830
- );
831
- }
832
-
833
- function GalleryShell(props: {
834
- children: ReactNode;
835
- description: string;
836
- sectionId?: GallerySectionId;
837
- title: string;
838
- }) {
839
- return (
840
- <div
841
- className={cn(
842
- dashboardContainerClass,
843
- "grid min-w-0 gap-8 px-4 py-4 sm:px-8 sm:py-8",
844
- )}
845
- >
846
- <div className="grid min-w-0 gap-3">
847
- {props.sectionId ? (
848
- <Link
849
- className="w-fit font-mono text-xs text-dashboard-text-muted no-underline hover:text-dashboard-text"
850
- to="/dev"
851
- >
852
- ← Component gallery
853
- </Link>
854
- ) : null}
855
- <PageHeader description={props.description} title={props.title} />
856
- </div>
857
- <div className="grid min-w-0 gap-6">{props.children}</div>
858
- </div>
859
- );
860
- }
861
-
862
- function Fixture(props: { children: ReactNode; title: string }) {
863
- return (
864
- <Card className="grid min-w-0 gap-3 p-4 sm:p-5" padding="none">
865
- <div className="border-b border-dashboard-border-subtle pb-3 font-sans text-xs font-medium text-dashboard-text-muted">
866
- {props.title}
867
- </div>
868
- <div className="min-w-0">{props.children}</div>
869
- </Card>
870
- );
871
- }
872
-
873
- function TokenSwatchRow(props: {
874
- label: string;
875
- swatches: readonly { className: string; label: string }[];
876
- }) {
877
- return (
878
- <div className="grid gap-2">
879
- <div className="font-sans font-medium text-xs text-dashboard-text-muted">
880
- {props.label}
881
- </div>
882
- <div className="flex flex-wrap gap-3">
883
- {props.swatches.map((swatch) => (
884
- <div className="grid w-20 gap-1.5" key={swatch.label}>
885
- <div
886
- className={cn(
887
- "h-10 rounded-md border border-dashboard-border-subtle",
888
- swatch.className,
889
- )}
890
- />
891
- <div className="truncate font-mono text-2xs text-dashboard-text-muted">
892
- {swatch.label}
893
- </div>
894
- </div>
895
- ))}
896
- </div>
897
- </div>
898
- );
899
- }