@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
@@ -0,0 +1,77 @@
1
+ import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion";
2
+ import { cn } from "@dashboard/lib/utils";
3
+ import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
4
+
5
+ /** Group sections with Base UI disclosure and keyboard behavior. */
6
+ function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {
7
+ return (
8
+ <AccordionPrimitive.Root
9
+ data-slot="accordion"
10
+ className={cn("flex w-full flex-col", className)}
11
+ {...props}
12
+ />
13
+ );
14
+ }
15
+
16
+ /** Keep one section’s trigger and panel state together. */
17
+ function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {
18
+ return (
19
+ <AccordionPrimitive.Item
20
+ data-slot="accordion-item"
21
+ className={cn(
22
+ "not-last:border-b not-last:border-dashboard-border-subtle",
23
+ className,
24
+ )}
25
+ {...props}
26
+ />
27
+ );
28
+ }
29
+
30
+ /** Render the section heading and its expand or collapse control. */
31
+ function AccordionTrigger({
32
+ className,
33
+ children,
34
+ ...props
35
+ }: AccordionPrimitive.Trigger.Props) {
36
+ return (
37
+ <AccordionPrimitive.Header className="flex">
38
+ <AccordionPrimitive.Trigger
39
+ data-slot="accordion-trigger"
40
+ className={cn(
41
+ "group/accordion-trigger relative flex min-w-0 flex-1 cursor-pointer items-center justify-between gap-3 rounded-sm py-2.5 text-left font-sans text-sm font-medium text-dashboard-text transition-colors hover:text-dashboard-text-solid outline-none focus-visible:outline-2 focus-visible:outline-dashboard-focus aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-dashboard-text-muted",
42
+ className,
43
+ )}
44
+ {...props}
45
+ >
46
+ {children}
47
+ <ChevronDownIcon
48
+ data-slot="accordion-trigger-icon"
49
+ className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden"
50
+ />
51
+ <ChevronUpIcon
52
+ data-slot="accordion-trigger-icon"
53
+ className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline"
54
+ />
55
+ </AccordionPrimitive.Trigger>
56
+ </AccordionPrimitive.Header>
57
+ );
58
+ }
59
+
60
+ /** Reveal section content with measured height and reduced-motion support. */
61
+ function AccordionContent({
62
+ className,
63
+ children,
64
+ ...props
65
+ }: AccordionPrimitive.Panel.Props) {
66
+ return (
67
+ <AccordionPrimitive.Panel
68
+ data-slot="accordion-content"
69
+ className="h-(--accordion-panel-height) overflow-hidden text-sm transition-[height] duration-180 ease-out data-ending-style:h-0 data-starting-style:h-0 motion-reduce:transition-none"
70
+ {...props}
71
+ >
72
+ <div className={cn("pt-0 pb-2.5", className)}>{children}</div>
73
+ </AccordionPrimitive.Panel>
74
+ );
75
+ }
76
+
77
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
@@ -0,0 +1,89 @@
1
+ import type { ComponentProps } from "react";
2
+ import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog";
3
+ import { cn } from "@dashboard/lib/utils";
4
+ import { Button } from "./button";
5
+
6
+ /** Require an explicit response before a destructive action. */
7
+ export function AlertDialog(props: AlertDialogPrimitive.Root.Props) {
8
+ return <AlertDialogPrimitive.Root {...props} />;
9
+ }
10
+
11
+ /** Show a named confirmation above the page with modal focus handling. */
12
+ export function AlertDialogContent({
13
+ className,
14
+ ...props
15
+ }: AlertDialogPrimitive.Popup.Props) {
16
+ return (
17
+ <AlertDialogPrimitive.Portal>
18
+ <AlertDialogPrimitive.Backdrop className="fixed inset-0 z-50 bg-dashboard-overlay transition-opacity duration-180 motion-reduce:transition-none data-ending-style:opacity-0 data-starting-style:opacity-0" />
19
+ <AlertDialogPrimitive.Popup
20
+ data-dashboard-modal=""
21
+ data-slot="alert-dialog-content"
22
+ className={cn(
23
+ "fixed top-1/2 left-1/2 z-50 grid grid-cols-1 max-h-[calc(100dvh-2rem)] w-[calc(100%-2rem)] max-w-sm -translate-x-1/2 -translate-y-1/2 gap-4 overflow-y-auto rounded-xl border border-dashboard-border-emphasis bg-dashboard-surface-raised p-5 text-dashboard-text shadow-lg outline-none transition-[opacity,scale] duration-180 motion-reduce:transition-none data-ending-style:opacity-0 data-starting-style:opacity-0 data-ending-style:scale-95 data-starting-style:scale-95",
24
+ className,
25
+ )}
26
+ {...props}
27
+ />
28
+ </AlertDialogPrimitive.Portal>
29
+ );
30
+ }
31
+
32
+ /** Name the action that needs confirmation. */
33
+ export function AlertDialogTitle({
34
+ className,
35
+ ...props
36
+ }: AlertDialogPrimitive.Title.Props) {
37
+ return (
38
+ <AlertDialogPrimitive.Title
39
+ className={cn("m-0 font-display text-lg font-medium", className)}
40
+ {...props}
41
+ />
42
+ );
43
+ }
44
+
45
+ /** Describe what the action changes before the user confirms it. */
46
+ export function AlertDialogDescription({
47
+ className,
48
+ ...props
49
+ }: AlertDialogPrimitive.Description.Props) {
50
+ return (
51
+ <AlertDialogPrimitive.Description
52
+ className={cn(
53
+ "m-0 break-words text-sm leading-relaxed text-dashboard-text-muted",
54
+ className,
55
+ )}
56
+ {...props}
57
+ />
58
+ );
59
+ }
60
+
61
+ /** Keep confirmation controls together and reachable on small screens. */
62
+ export function AlertDialogFooter({
63
+ className,
64
+ ...props
65
+ }: ComponentProps<"div">) {
66
+ return (
67
+ <div
68
+ className={cn("flex flex-wrap justify-end gap-2", className)}
69
+ {...props}
70
+ />
71
+ );
72
+ }
73
+
74
+ /** Run the confirmed action; its owner decides when the dialog can close. */
75
+ export function AlertDialogAction(props: ComponentProps<typeof Button>) {
76
+ return (
77
+ <Button data-slot="alert-dialog-action" className="min-h-11" {...props} />
78
+ );
79
+ }
80
+
81
+ /** Cancel through Base UI so focus returns to the source control. */
82
+ export function AlertDialogCancel(props: AlertDialogPrimitive.Close.Props) {
83
+ return (
84
+ <AlertDialogPrimitive.Close
85
+ render={<Button className="min-h-11" />}
86
+ {...props}
87
+ />
88
+ );
89
+ }
@@ -0,0 +1,85 @@
1
+ import { Button as ButtonPrimitive } from "@base-ui/react/button";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import { cn } from "@dashboard/lib/utils";
4
+
5
+ const commandButtonClass =
6
+ "inline-flex h-9 max-w-full items-center justify-center gap-2 rounded-md border px-3 text-sm font-medium leading-none focus-visible:outline-2 focus-visible:outline-offset-2";
7
+
8
+ /** Style the dashboard command, primary, danger, and icon button surfaces. Links use it with `className`. */
9
+ const buttonVariants = cva(
10
+ "cursor-pointer font-sans no-underline transition-colors data-disabled:cursor-not-allowed data-disabled:opacity-50",
11
+ {
12
+ variants: {
13
+ variant: {
14
+ default: "",
15
+ primary: "",
16
+ danger: "",
17
+ },
18
+ size: {
19
+ default: "",
20
+ icon: "grid size-9 place-items-center rounded-md border-0 bg-transparent p-0 text-dashboard-text-muted focus-visible:outline-2 focus-visible:outline-offset-1 data-disabled:hover:!bg-transparent data-disabled:hover:!text-dashboard-text-muted",
21
+ },
22
+ },
23
+ compoundVariants: [
24
+ {
25
+ size: "default",
26
+ variant: "default",
27
+ className: cn(
28
+ commandButtonClass,
29
+ "border-dashboard-border-emphasis bg-dashboard-surface-raised text-dashboard-text hover:border-dashboard-border-heavy hover:bg-dashboard-surface-hover hover:text-dashboard-text focus-visible:outline-dashboard-focus data-disabled:hover:border-dashboard-border-emphasis data-disabled:hover:bg-dashboard-surface-raised data-disabled:hover:text-dashboard-text",
30
+ ),
31
+ },
32
+ {
33
+ size: "default",
34
+ variant: "primary",
35
+ className: cn(
36
+ commandButtonClass,
37
+ "border-dashboard-text-solid bg-dashboard-text-solid text-dashboard-text-inverse hover:border-dashboard-text-subtle hover:bg-dashboard-text-subtle focus-visible:outline-dashboard-focus data-disabled:hover:border-dashboard-text-solid data-disabled:hover:bg-dashboard-text-solid",
38
+ ),
39
+ },
40
+ {
41
+ size: "default",
42
+ variant: "danger",
43
+ className: cn(
44
+ commandButtonClass,
45
+ "border-dashboard-border-strong bg-transparent text-dashboard-text-muted hover:border-rose-300/40 hover:text-rose-300 focus-visible:outline-rose-300/55 data-disabled:hover:border-dashboard-border-strong data-disabled:hover:text-dashboard-text-muted",
46
+ ),
47
+ },
48
+ {
49
+ size: "icon",
50
+ variant: ["default", "primary"],
51
+ className:
52
+ "hover:!bg-dashboard-fill-strong hover:!text-dashboard-text focus-visible:outline-dashboard-focus",
53
+ },
54
+ {
55
+ size: "icon",
56
+ variant: "danger",
57
+ className:
58
+ "hover:!bg-rose-300/10 hover:!text-rose-300 focus-visible:outline-rose-300/55",
59
+ },
60
+ ],
61
+ defaultVariants: {
62
+ variant: "default",
63
+ size: "default",
64
+ },
65
+ },
66
+ );
67
+
68
+ /** Render a Base UI button with a dashboard button surface. */
69
+ function Button({
70
+ className,
71
+ variant = "default",
72
+ size = "default",
73
+ ...props
74
+ }: Omit<ButtonPrimitive.Props, "className"> &
75
+ VariantProps<typeof buttonVariants> & { className?: string }) {
76
+ return (
77
+ <ButtonPrimitive
78
+ data-slot="button"
79
+ className={cn(buttonVariants({ variant, size }), className)}
80
+ {...props}
81
+ />
82
+ );
83
+ }
84
+
85
+ export { Button, buttonVariants };
@@ -0,0 +1,74 @@
1
+ import * as React from "react";
2
+ import * as RechartsPrimitive from "recharts";
3
+ import { cn } from "@dashboard/lib/utils";
4
+
5
+ const INITIAL_DIMENSION = { width: 320, height: 200 } as const;
6
+
7
+ type ChartConfig = Record<
8
+ string,
9
+ {
10
+ label?: React.ReactNode;
11
+ color?: string;
12
+ }
13
+ >;
14
+
15
+ /**
16
+ * Size a Recharts chart to its box and expose each config color as
17
+ * `var(--color-<key>)` inside it.
18
+ */
19
+ function ChartContainer({
20
+ id,
21
+ className,
22
+ children,
23
+ config,
24
+ ...props
25
+ }: React.ComponentProps<"div"> & {
26
+ config: ChartConfig;
27
+ children: React.ComponentProps<
28
+ typeof RechartsPrimitive.ResponsiveContainer
29
+ >["children"];
30
+ }) {
31
+ const uniqueId = React.useId();
32
+ const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`;
33
+
34
+ return (
35
+ <div
36
+ data-slot="chart"
37
+ data-chart={chartId}
38
+ className={cn(
39
+ "flex aspect-video justify-center font-sans text-2xs tabular-nums [&_.recharts-cartesian-axis-tick-value]:fill-dashboard-text-muted [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-dashboard-border-subtle [&_.recharts-curve.recharts-tooltip-cursor]:stroke-dashboard-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-dashboard-fill-soft [&_.recharts-reference-line_[stroke='#ccc']]:stroke-dashboard-border [&_.recharts-surface]:outline-hidden [&_.recharts-surface]:focus-visible:outline-2 [&_.recharts-surface]:focus-visible:outline-dashboard-focus",
40
+ className,
41
+ )}
42
+ {...props}
43
+ >
44
+ <ChartStyle id={chartId} config={config} />
45
+ <RechartsPrimitive.ResponsiveContainer
46
+ initialDimension={INITIAL_DIMENSION}
47
+ >
48
+ {children}
49
+ </RechartsPrimitive.ResponsiveContainer>
50
+ </div>
51
+ );
52
+ }
53
+
54
+ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
55
+ const colors = Object.entries(config).flatMap(([key, { color }]) =>
56
+ color ? [` --color-${key}: ${color};`] : [],
57
+ );
58
+
59
+ if (!colors.length) {
60
+ return null;
61
+ }
62
+
63
+ return (
64
+ <style
65
+ dangerouslySetInnerHTML={{
66
+ __html: `[data-chart=${id}] {\n${colors.join("\n")}\n}`,
67
+ }}
68
+ />
69
+ );
70
+ };
71
+
72
+ const ChartTooltip = RechartsPrimitive.Tooltip;
73
+
74
+ export { ChartContainer, ChartTooltip };
@@ -0,0 +1,26 @@
1
+ import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox";
2
+ import { cn } from "@dashboard/lib/utils";
3
+ import { CheckIcon } from "lucide-react";
4
+
5
+ /** Render a Base UI checkbox with the dashboard control surface. */
6
+ function Checkbox({
7
+ className,
8
+ ...props
9
+ }: Omit<CheckboxPrimitive.Root.Props, "className"> & { className?: string }) {
10
+ return (
11
+ <CheckboxPrimitive.Root
12
+ data-slot="checkbox"
13
+ className={cn(
14
+ "grid size-4 shrink-0 cursor-pointer place-items-center rounded-sm border border-dashboard-border-interactive bg-dashboard-control text-dashboard-text-inverse transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-dashboard-focus data-checked:border-dashboard-focus data-checked:bg-dashboard-focus data-disabled:cursor-not-allowed data-disabled:opacity-50",
15
+ className,
16
+ )}
17
+ {...props}
18
+ >
19
+ <CheckboxPrimitive.Indicator data-slot="checkbox-indicator">
20
+ <CheckIcon aria-hidden="true" size={12} strokeWidth={3} />
21
+ </CheckboxPrimitive.Indicator>
22
+ </CheckboxPrimitive.Root>
23
+ );
24
+ }
25
+
26
+ export { Checkbox };
@@ -0,0 +1,22 @@
1
+ import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible";
2
+
3
+ /** Own open state for one trigger and its panel. */
4
+ function Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {
5
+ return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />;
6
+ }
7
+
8
+ /** Toggle the panel and expose its state with `aria-expanded`. */
9
+ function CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {
10
+ return (
11
+ <CollapsiblePrimitive.Trigger data-slot="collapsible-trigger" {...props} />
12
+ );
13
+ }
14
+
15
+ /** Render the panel only while open, unless `keepMounted` is set. */
16
+ function CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {
17
+ return (
18
+ <CollapsiblePrimitive.Panel data-slot="collapsible-content" {...props} />
19
+ );
20
+ }
21
+
22
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent };
@@ -0,0 +1,49 @@
1
+ import type { ComponentProps } from "react";
2
+ import { cn } from "@dashboard/lib/utils";
3
+
4
+ /** Stack a label, control, and messages for one form field. */
5
+ function Field({ className, ...props }: ComponentProps<"div">) {
6
+ return (
7
+ <div data-slot="field" className={cn("grid gap-2", className)} {...props} />
8
+ );
9
+ }
10
+
11
+ /** Label the field control. */
12
+ function FieldLabel({ className, ...props }: ComponentProps<"label">) {
13
+ return (
14
+ <label
15
+ data-slot="field-label"
16
+ className={cn("text-sm font-semibold text-dashboard-text", className)}
17
+ {...props}
18
+ />
19
+ );
20
+ }
21
+
22
+ /** Give help text below the field control. */
23
+ function FieldDescription({ className, ...props }: ComponentProps<"p">) {
24
+ return (
25
+ <p
26
+ data-slot="field-description"
27
+ className={cn(
28
+ "m-0 text-xs leading-relaxed text-dashboard-text-muted sm:text-sm",
29
+ className,
30
+ )}
31
+ {...props}
32
+ />
33
+ );
34
+ }
35
+
36
+ /** Announce a field validation error. Render nothing when there is no error. */
37
+ function FieldError({ className, ...props }: ComponentProps<"p">) {
38
+ if (!props.children) return null;
39
+ return (
40
+ <p
41
+ role="alert"
42
+ data-slot="field-error"
43
+ className={cn("m-0 text-xs leading-relaxed text-rose-300", className)}
44
+ {...props}
45
+ />
46
+ );
47
+ }
48
+
49
+ export { Field, FieldDescription, FieldError, FieldLabel };
@@ -0,0 +1,35 @@
1
+ import { Input as InputPrimitive } from "@base-ui/react/input";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import { cn } from "@dashboard/lib/utils";
4
+
5
+ /** Style the dashboard text control surface shared by inputs and text areas. */
6
+ export const textControlClass =
7
+ "block w-full rounded-md border border-dashboard-border-emphasis bg-dashboard-ink px-3 py-2 font-sans text-sm text-dashboard-text placeholder:text-dashboard-text-muted/70 focus:border-dashboard-focus focus:outline-none focus:ring-1 focus:ring-dashboard-focus/25 aria-invalid:border-rose-300 disabled:cursor-not-allowed disabled:opacity-50";
8
+
9
+ const inputVariants = cva(textControlClass, {
10
+ variants: {
11
+ size: {
12
+ default: "",
13
+ comfortable: "min-h-11 text-base sm:min-h-10 sm:text-sm",
14
+ },
15
+ },
16
+ defaultVariants: { size: "default" },
17
+ });
18
+
19
+ /** Render a Base UI text input. Use `size="comfortable"` for larger mobile controls. */
20
+ function Input({
21
+ className,
22
+ size,
23
+ ...props
24
+ }: Omit<InputPrimitive.Props, "className" | "size"> &
25
+ VariantProps<typeof inputVariants> & { className?: string }) {
26
+ return (
27
+ <InputPrimitive
28
+ data-slot="input"
29
+ className={cn(inputVariants({ size }), className)}
30
+ {...props}
31
+ />
32
+ );
33
+ }
34
+
35
+ export { Input };
@@ -0,0 +1,57 @@
1
+ import type { ComponentProps } from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import { ChevronDownIcon } from "lucide-react";
4
+ import { cn } from "@dashboard/lib/utils";
5
+
6
+ const nativeSelectVariants = cva(
7
+ "block w-full min-w-0 appearance-none pr-9 disabled:cursor-not-allowed disabled:opacity-60 forced-colors:appearance-auto [color-scheme:var(--dashboard-color-scheme,dark)]",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ /** Form field. Touch screens get the taller target. */
12
+ form: "min-h-11 rounded-md border border-dashboard-border-emphasis bg-dashboard-ink py-2 pl-3 text-base text-dashboard-text focus:border-dashboard-focus focus:outline-none aria-invalid:border-rose-300 sm:min-h-10 sm:text-sm",
13
+ /** Compact control in a filter bar. */
14
+ filter:
15
+ "h-9 rounded-lg border border-dashboard-border-emphasis bg-dashboard-control pl-2 text-sm text-dashboard-text transition-colors hover:border-dashboard-border-interactive focus:border-dashboard-focus focus:outline-none focus:ring-1 focus:ring-dashboard-focus/25",
16
+ /** Borderless sort control that fills its frame. */
17
+ sort: "h-full bg-dashboard-control pl-2 font-sans text-xs text-dashboard-text-muted outline-none",
18
+ },
19
+ },
20
+ defaultVariants: { variant: "form" },
21
+ },
22
+ );
23
+
24
+ /** Keep native choices and draw the dashboard arrow. */
25
+ function NativeSelect({
26
+ className,
27
+ variant,
28
+ ...props
29
+ }: Omit<ComponentProps<"select">, "size"> &
30
+ VariantProps<typeof nativeSelectVariants>) {
31
+ return (
32
+ <span
33
+ data-slot="native-select-wrapper"
34
+ className={cn(
35
+ "relative block w-full min-w-0",
36
+ variant === "sort" && "h-full",
37
+ className,
38
+ )}
39
+ >
40
+ <select
41
+ data-slot="native-select"
42
+ className={nativeSelectVariants({ variant })}
43
+ {...props}
44
+ />
45
+ <ChevronDownIcon
46
+ aria-hidden="true"
47
+ data-slot="native-select-icon"
48
+ className={cn(
49
+ "pointer-events-none absolute top-1/2 right-3 size-4 -translate-y-1/2 text-dashboard-text-muted forced-colors:hidden",
50
+ props.disabled && "opacity-60",
51
+ )}
52
+ />
53
+ </span>
54
+ );
55
+ }
56
+
57
+ export { NativeSelect };
@@ -0,0 +1,67 @@
1
+ import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
2
+ import { cn } from "@dashboard/lib/utils";
3
+
4
+ /** Own an anchored popover's state and dismissal. */
5
+ export function Popover(props: PopoverPrimitive.Root.Props) {
6
+ return <PopoverPrimitive.Root {...props} />;
7
+ }
8
+
9
+ /** Open a popover from the owning control. */
10
+ export function PopoverTrigger(props: PopoverPrimitive.Trigger.Props) {
11
+ return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />;
12
+ }
13
+
14
+ /** Position popover content within the viewport and share its themed surface. */
15
+ export function PopoverContent({
16
+ className,
17
+ align = "center",
18
+ side = "bottom",
19
+ ...props
20
+ }: PopoverPrimitive.Popup.Props &
21
+ Pick<PopoverPrimitive.Positioner.Props, "align" | "side">) {
22
+ return (
23
+ <PopoverPrimitive.Portal>
24
+ <PopoverPrimitive.Positioner
25
+ align={align}
26
+ side={side}
27
+ sideOffset={8}
28
+ className="isolate z-50"
29
+ >
30
+ <PopoverPrimitive.Popup
31
+ data-slot="popover-content"
32
+ className={cn(
33
+ "w-80 max-w-[calc(100vw-2rem)] max-h-(--available-height) origin-(--transform-origin) overflow-y-auto rounded-lg border border-dashboard-border-emphasis bg-dashboard-surface-raised p-4 text-sm text-dashboard-text shadow-lg outline-none focus-visible:outline-2 focus-visible:outline-dashboard-focus transition-[opacity,scale] duration-180 motion-reduce:transition-none data-ending-style:opacity-0 data-starting-style:opacity-0 data-ending-style:scale-95 data-starting-style:scale-95",
34
+ className,
35
+ )}
36
+ {...props}
37
+ />
38
+ </PopoverPrimitive.Positioner>
39
+ </PopoverPrimitive.Portal>
40
+ );
41
+ }
42
+
43
+ /** Name a popover through its visible heading. */
44
+ export function PopoverTitle({
45
+ className,
46
+ ...props
47
+ }: PopoverPrimitive.Title.Props) {
48
+ return (
49
+ <PopoverPrimitive.Title
50
+ className={cn("m-0 text-sm font-medium", className)}
51
+ {...props}
52
+ />
53
+ );
54
+ }
55
+
56
+ /** Explain a popover without duplicating its heading. */
57
+ export function PopoverDescription({
58
+ className,
59
+ ...props
60
+ }: PopoverPrimitive.Description.Props) {
61
+ return (
62
+ <PopoverPrimitive.Description
63
+ className={cn("m-0 leading-relaxed text-dashboard-text-muted", className)}
64
+ {...props}
65
+ />
66
+ );
67
+ }
@@ -0,0 +1,32 @@
1
+ import { Radio as RadioPrimitive } from "@base-ui/react/radio";
2
+ import { RadioGroup as RadioGroupPrimitive } from "@base-ui/react/radio-group";
3
+ import { cn } from "@dashboard/lib/utils";
4
+
5
+ /** Own the selected value and arrow-key focus for a set of radios. */
6
+ function RadioGroup<Value>(props: RadioGroupPrimitive.Props<Value>) {
7
+ return <RadioGroupPrimitive data-slot="radio-group" {...props} />;
8
+ }
9
+
10
+ /** Render one Base UI radio with the dashboard control surface. */
11
+ function RadioGroupItem({
12
+ className,
13
+ ...props
14
+ }: Omit<RadioPrimitive.Root.Props, "className"> & { className?: string }) {
15
+ return (
16
+ <RadioPrimitive.Root
17
+ data-slot="radio-group-item"
18
+ className={cn(
19
+ "grid size-4 shrink-0 cursor-pointer place-items-center rounded-full border border-dashboard-border-interactive bg-dashboard-control transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-dashboard-focus data-checked:border-dashboard-focus data-checked:bg-dashboard-focus data-disabled:cursor-not-allowed data-disabled:opacity-50",
20
+ className,
21
+ )}
22
+ {...props}
23
+ >
24
+ <RadioPrimitive.Indicator
25
+ data-slot="radio-group-indicator"
26
+ className="size-1.5 rounded-full bg-dashboard-text-inverse"
27
+ />
28
+ </RadioPrimitive.Root>
29
+ );
30
+ }
31
+
32
+ export { RadioGroup, RadioGroupItem };