@sentry/junior-dashboard 0.248.0 → 0.249.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 (136) hide show
  1. package/dist/app.js +2 -2
  2. package/dist/client.js +36 -35
  3. package/dist/index.js +2 -2
  4. package/dist/tailwind.css +1 -1
  5. package/package.json +3 -3
  6. package/src/client/App.tsx +1 -5
  7. package/src/client/components/ActorAvatar.tsx +7 -4
  8. package/src/client/components/AutomationCard.tsx +2 -2
  9. package/src/client/components/Button.tsx +12 -11
  10. package/src/client/components/ConversationList.tsx +3 -3
  11. package/src/client/components/ConversationSummary.tsx +2 -1
  12. package/src/client/components/DetailList.tsx +3 -3
  13. package/src/client/components/Drawer.tsx +2 -2
  14. package/src/client/components/EmptyTelemetry.tsx +1 -1
  15. package/src/client/components/Field.tsx +1 -2
  16. package/src/client/components/FilterBar.tsx +6 -6
  17. package/src/client/components/Metric.tsx +4 -4
  18. package/src/client/components/Notice.tsx +7 -7
  19. package/src/client/components/PageContentSkeleton.tsx +2 -2
  20. package/src/client/components/Pagination.tsx +2 -2
  21. package/src/client/components/ParticipantAvatarStack.tsx +4 -4
  22. package/src/client/components/ProfileMenu.tsx +5 -7
  23. package/src/client/components/README.md +122 -58
  24. package/src/client/components/SearchInput.tsx +4 -3
  25. package/src/client/components/SegmentedNav.tsx +10 -17
  26. package/src/client/components/SegmentedTabs.tsx +3 -3
  27. package/src/client/components/Select.tsx +1 -1
  28. package/src/client/components/SelectableRow.tsx +2 -2
  29. package/src/client/components/Skeleton.tsx +1 -1
  30. package/src/client/components/StatusChip.tsx +1 -1
  31. package/src/client/components/StatusDot.tsx +1 -1
  32. package/src/client/components/TextInput.tsx +1 -1
  33. package/src/client/components/Tooltip.tsx +2 -2
  34. package/src/client/components/VersionDriftBanner.tsx +2 -2
  35. package/src/client/components/charts/ActivityChart.tsx +5 -6
  36. package/src/client/components/charts/CacheWrites.tsx +3 -3
  37. package/src/client/components/charts/ChartHeader.tsx +4 -4
  38. package/src/client/components/charts/ChartLegend.tsx +1 -1
  39. package/src/client/components/charts/InputCacheChart.tsx +5 -5
  40. package/src/client/components/charts/WorkspaceUsageChart.tsx +4 -11
  41. package/src/client/components/controls/DirectorySortSelect.tsx +2 -2
  42. package/src/client/components/directory/DirectoryMetric.tsx +2 -2
  43. package/src/client/components/directory/DirectoryRowsSkeleton.tsx +5 -5
  44. package/src/client/components/directory/DirectoryTable.tsx +3 -3
  45. package/src/client/components/layout/CardHeader.tsx +4 -4
  46. package/src/client/components/layout/DashboardChrome.tsx +9 -3
  47. package/src/client/components/layout/DashboardHeader.tsx +7 -7
  48. package/src/client/components/layout/PageHeader.tsx +2 -2
  49. package/src/client/components/layout/SecondaryNavigation.tsx +7 -14
  50. package/src/client/components/layout/SectionIntro.tsx +1 -1
  51. package/src/client/components/layout/SectionTitle.tsx +1 -1
  52. package/src/client/components/metrics/StatCard.tsx +2 -2
  53. package/src/client/conversations/ConversationArchiveNotices.tsx +1 -1
  54. package/src/client/conversations/ConversationBrief.tsx +4 -4
  55. package/src/client/conversations/ConversationChildAgents.tsx +7 -4
  56. package/src/client/conversations/ConversationComposer.tsx +8 -7
  57. package/src/client/conversations/ConversationHeader.tsx +5 -5
  58. package/src/client/conversations/ConversationHeaderActions.tsx +9 -9
  59. package/src/client/conversations/ConversationHomeList.tsx +3 -3
  60. package/src/client/conversations/ConversationListStatusIcon.tsx +1 -1
  61. package/src/client/conversations/ConversationMemories.tsx +4 -4
  62. package/src/client/conversations/ConversationMeta.tsx +10 -10
  63. package/src/client/conversations/ConversationPage.tsx +2 -1
  64. package/src/client/conversations/ConversationSidebar.tsx +6 -6
  65. package/src/client/conversations/ConversationUsageBreakdown.tsx +4 -4
  66. package/src/client/conversations/ConversationWorkspace.tsx +1 -1
  67. package/src/client/conversations/ConversationWorkspaceLoading.tsx +4 -4
  68. package/src/client/conversations/CopyMarkdownButton.tsx +1 -1
  69. package/src/client/conversations/EventUsage.tsx +2 -2
  70. package/src/client/conversations/PendingMailboxStack.tsx +5 -5
  71. package/src/client/conversations/README.md +9 -0
  72. package/src/client/conversations/SubagentTranscriptDrawer.tsx +39 -23
  73. package/src/client/conversations/ToolFrame.tsx +36 -14
  74. package/src/client/conversations/TranscriptActivityGroup.tsx +10 -3
  75. package/src/client/conversations/TranscriptAttachmentsDeliveredView.tsx +4 -6
  76. package/src/client/conversations/TranscriptContextEventView.tsx +2 -2
  77. package/src/client/conversations/TranscriptEventView.tsx +1 -1
  78. package/src/client/conversations/TranscriptMarkdown.tsx +3 -3
  79. package/src/client/conversations/TranscriptMessageContextView.tsx +7 -7
  80. package/src/client/conversations/TranscriptMessageView.tsx +2 -6
  81. package/src/client/conversations/TranscriptRailEvent.tsx +20 -8
  82. package/src/client/conversations/TranscriptReasoningView.tsx +12 -12
  83. package/src/client/conversations/TranscriptStructuredEventView.tsx +16 -11
  84. package/src/client/conversations/TranscriptSubagentView.tsx +64 -39
  85. package/src/client/conversations/TranscriptText.tsx +5 -4
  86. package/src/client/conversations/TranscriptToolView.tsx +9 -11
  87. package/src/client/conversations/TranscriptTurnContextView.tsx +3 -3
  88. package/src/client/conversations/TranscriptView.tsx +3 -3
  89. package/src/client/conversations/UsageCard.tsx +1 -1
  90. package/src/client/conversations/eventTranscript.ts +7 -0
  91. package/src/client/conversations/transcriptMarkdownLinks.ts +2 -4
  92. package/src/client/conversations/transcriptStyles.ts +1 -1
  93. package/src/client/pages/PersonalTokensPage.tsx +4 -4
  94. package/src/client/pages/admin/AdminPage.tsx +2 -2
  95. package/src/client/pages/automations/AutomationCostChart.tsx +2 -2
  96. package/src/client/pages/automations/AutomationDetailsDrawer.tsx +5 -10
  97. package/src/client/pages/automations/AutomationEditor.tsx +1 -1
  98. package/src/client/pages/automations/AutomationExecutionChart.tsx +2 -2
  99. package/src/client/pages/automations/AutomationExecutionStatusChart.tsx +2 -2
  100. package/src/client/pages/automations/AutomationExecutionsPage.tsx +4 -4
  101. package/src/client/pages/automations/AutomationRow.tsx +4 -4
  102. package/src/client/pages/automations/AutomationRunsPage.tsx +3 -3
  103. package/src/client/pages/automations/AutomationScheduleFields.tsx +1 -1
  104. package/src/client/pages/automations/AutomationVersionsPage.tsx +1 -1
  105. package/src/client/pages/code/CodeActivityChart.tsx +7 -6
  106. package/src/client/pages/code/CodeChangeRow.tsx +1 -1
  107. package/src/client/pages/code/CodePage.tsx +5 -5
  108. package/src/client/pages/code/RepositoryPage.tsx +2 -2
  109. package/src/client/pages/dev/ComponentsPage.tsx +40 -146
  110. package/src/client/pages/dev/TranscriptActivityFixtures.tsx +206 -0
  111. package/src/client/pages/locations/LocationDetailPage.tsx +4 -4
  112. package/src/client/pages/locations/LocationDirectory.tsx +1 -1
  113. package/src/client/pages/locations/PrivateActivityCard.tsx +3 -3
  114. package/src/client/pages/memory/MemoryCostChart.tsx +3 -5
  115. package/src/client/pages/memory/MemoryDetailsDrawer.tsx +5 -5
  116. package/src/client/pages/memory/MemoryPage.tsx +15 -15
  117. package/src/client/pages/memory/MemoryTimeline.tsx +3 -5
  118. package/src/client/pages/people/ContributionGrid.tsx +8 -5
  119. package/src/client/pages/people/PersonProfilePage.tsx +3 -6
  120. package/src/client/pages/people/ProfilePluginReports.tsx +2 -2
  121. package/src/client/pages/system/GuardianActivity.tsx +9 -9
  122. package/src/client/pages/system/PluginBarChart.tsx +4 -6
  123. package/src/client/pages/system/PluginDetails.tsx +11 -7
  124. package/src/client/pages/system/PluginPanels.tsx +8 -8
  125. package/src/client/pages/system/PluginReportRecordSet.tsx +14 -14
  126. package/src/client/pages/system/PluginReports.tsx +7 -11
  127. package/src/client/pages/system/SkillInventory.tsx +9 -9
  128. package/src/client/pages/system/SystemActivity.tsx +1 -1
  129. package/src/client/pages/system/SystemPage.tsx +3 -6
  130. package/src/client/pages/system/WorkspaceDetails.tsx +2 -5
  131. package/src/client/pages/system/WorkspaceEditor.tsx +2 -2
  132. package/src/client/pages/system/WorkspaceList.tsx +2 -2
  133. package/src/client/pages/user/PluginUserPage.tsx +3 -3
  134. package/src/client/styles.ts +5 -4
  135. package/src/client/types.ts +2 -0
  136. package/src/tailwind.css +36 -38
@@ -18,10 +18,10 @@ export type ToggleButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
18
18
  };
19
19
 
20
20
  const buttonClassName =
21
- "inline-flex h-9 max-w-full items-center gap-2 rounded border border-dashboard-border-emphasis bg-dashboard-surface-raised px-3 font-mono text-sm font-semibold leading-none text-dashboard-text transition-colors hover:border-dashboard-border-heavy hover:bg-dashboard-surface-hover hover:text-dashboard-text";
21
+ "inline-flex h-9 max-w-full items-center justify-center gap-2 rounded-md border border-dashboard-border-emphasis bg-dashboard-surface-raised px-3 font-sans text-sm font-medium leading-none text-dashboard-text transition-colors hover:border-dashboard-border-heavy hover:bg-dashboard-surface-hover hover:text-dashboard-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-dashboard-focus";
22
22
 
23
23
  const dangerButtonClassName =
24
- "inline-flex h-9 max-w-full items-center justify-center gap-1.5 rounded border border-dashboard-border-strong bg-transparent px-3 font-mono text-xs font-semibold text-dashboard-text-muted transition-colors hover:border-rose-300/40 hover:text-rose-300";
24
+ "inline-flex h-9 max-w-full items-center justify-center gap-2 rounded-md border border-dashboard-border-strong bg-transparent px-3 font-sans text-sm font-medium leading-none text-dashboard-text-muted transition-colors hover:border-rose-300/40 hover:text-rose-300 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-rose-300/55";
25
25
 
26
26
  /** Render the dashboard's standard bordered command button surface. */
27
27
  export function Button({
@@ -36,16 +36,16 @@ export function Button({
36
36
  <button
37
37
  {...props}
38
38
  className={cn(
39
- "font-mono transition-colors disabled:cursor-not-allowed disabled:opacity-50",
39
+ "font-sans transition-colors disabled:cursor-not-allowed disabled:opacity-50",
40
40
  size === "icon"
41
41
  ? cn(
42
- "grid size-9 place-items-center rounded-md border-0 bg-transparent p-0 focus-visible:outline focus-visible:outline-1 disabled:hover:!bg-transparent",
42
+ "grid size-9 place-items-center rounded-md border-0 bg-transparent p-0 focus-visible:outline-2 focus-visible:outline-offset-1 disabled:hover:!bg-transparent",
43
43
  isDanger
44
44
  ? "text-dashboard-text-muted hover:!bg-rose-300/10 hover:!text-rose-300 focus-visible:outline-rose-300/55 disabled:hover:!text-dashboard-text-muted"
45
- : "text-dashboard-text-muted hover:!bg-dashboard-fill-strong hover:!text-dashboard-text focus-visible:outline-cyan-300/55 disabled:hover:!text-dashboard-text-muted",
45
+ : "text-dashboard-text-muted hover:!bg-dashboard-fill-strong hover:!text-dashboard-text focus-visible:outline-dashboard-focus disabled:hover:!text-dashboard-text-muted",
46
46
  )
47
47
  : tone === "primary"
48
- ? "inline-flex h-9 items-center justify-center gap-2 rounded border border-dashboard-text-solid bg-dashboard-text-solid px-3 font-sans text-sm font-semibold text-dashboard-text-inverse hover:bg-dashboard-text-subtle focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-dashboard-focus"
48
+ ? "inline-flex h-9 items-center justify-center gap-2 rounded-md border border-dashboard-text-solid bg-dashboard-text-solid px-3 font-sans text-sm font-medium leading-none text-dashboard-text-inverse hover:border-dashboard-text-subtle hover:bg-dashboard-text-subtle disabled:hover:border-dashboard-text-solid disabled:hover:bg-dashboard-text-solid focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-dashboard-focus"
49
49
  : isDanger
50
50
  ? cn(
51
51
  dangerButtonClassName,
@@ -96,21 +96,22 @@ export function ToggleButton({
96
96
  }
97
97
 
98
98
  const toggleButtonBase: Record<ToggleButtonVariant, string> = {
99
- pill: "cursor-pointer rounded border px-2 py-1 font-mono text-xs font-semibold uppercase leading-tight transition-colors focus-visible:outline focus-visible:outline-1 focus-visible:outline-cyan-300/55",
99
+ pill: "cursor-pointer rounded-md border px-2 py-1 font-sans text-xs font-medium leading-tight transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-dashboard-focus",
100
100
  segment:
101
- "h-7 min-w-10 cursor-pointer rounded border px-2 font-mono text-xs transition-colors focus-visible:outline focus-visible:outline-1 focus-visible:outline-cyan-300/55",
102
- text: "cursor-pointer border-0 bg-transparent px-1.5 py-1 font-mono uppercase tracking-normal underline-offset-4 transition-colors focus-visible:outline focus-visible:outline-1 focus-visible:outline-cyan-300/55",
101
+ "inline-flex h-7 min-w-10 cursor-pointer items-center justify-center rounded-md border px-2 font-sans text-xs font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-dashboard-focus",
102
+ text: "cursor-pointer rounded-sm border-0 bg-transparent px-1.5 py-1 font-sans font-medium underline-offset-4 transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-dashboard-focus",
103
103
  };
104
104
 
105
105
  const toggleButtonPressed: Record<ToggleButtonVariant, string> = {
106
106
  pill: "border-dashboard-border-heavy bg-dashboard-text-solid text-dashboard-text-inverse",
107
- segment: "border-amber-500/30 bg-amber-500/20 text-amber-400",
107
+ segment:
108
+ "border-dashboard-border-interactive bg-dashboard-surface-active text-dashboard-text",
108
109
  text: "text-dashboard-text underline decoration-dashboard-text-solid",
109
110
  };
110
111
 
111
112
  const toggleButtonIdle: Record<ToggleButtonVariant, string> = {
112
113
  pill: "border-dashboard-border-strong bg-dashboard-surface-raised text-dashboard-text-muted hover:border-dashboard-border-interactive hover:bg-dashboard-surface-hover hover:text-dashboard-text",
113
114
  segment:
114
- "border-dashboard-border-strong bg-dashboard-fill-faint text-dashboard-text-muted hover:bg-dashboard-fill-strong hover:text-dashboard-text",
115
+ "border-transparent bg-transparent text-dashboard-text-muted hover:bg-dashboard-fill-hover hover:text-dashboard-text",
115
116
  text: "text-dashboard-text-muted hover:text-dashboard-text",
116
117
  };
@@ -28,7 +28,7 @@ export function ConversationList(props: {
28
28
  return (
29
29
  <div className="min-w-0" role="table">
30
30
  <div
31
- className="sticky top-0 z-[1] grid grid-cols-[minmax(13rem,1.7fr)_minmax(13rem,1fr)] items-center gap-3 border-b border-dashboard-border-subtle bg-dashboard-overlay-soft px-3 py-2.5 font-mono text-xs uppercase tracking-[0.1em] text-dashboard-text-muted max-md:hidden"
31
+ className="sticky top-0 z-[1] grid grid-cols-[minmax(13rem,1.7fr)_minmax(13rem,1fr)] items-center gap-3 border-b border-dashboard-border-subtle bg-dashboard-overlay-soft px-3 py-2.5 font-sans font-medium text-xs text-dashboard-text-muted max-md:hidden"
32
32
  role="row"
33
33
  >
34
34
  <div>Conversation</div>
@@ -85,8 +85,8 @@ function conversationRecordClass(
85
85
  selected: boolean | undefined,
86
86
  ): string {
87
87
  return cn(
88
- "group grid min-w-0 cursor-pointer grid-cols-[minmax(13rem,1.7fr)_minmax(13rem,1fr)] items-center gap-3 overflow-hidden border-b border-b-white/[0.055] px-3 py-3 text-left text-inherit no-underline transition-colors hover:bg-white/[0.035] max-md:grid-cols-1 max-md:px-4 max-md:py-4",
88
+ "group grid min-w-0 cursor-pointer grid-cols-[minmax(13rem,1.7fr)_minmax(13rem,1fr)] items-center gap-3 overflow-hidden border-b border-b-dashboard-border-subtle px-3 py-3 text-left text-inherit no-underline transition-colors hover:bg-dashboard-fill-soft max-md:grid-cols-1 max-md:px-4 max-md:py-4",
89
89
  status === "idle" && "saturate-50",
90
- selected && "bg-cyan-400/[0.045]",
90
+ selected && "bg-dashboard-accent/[0.045]",
91
91
  );
92
92
  }
@@ -11,6 +11,7 @@ import {
11
11
  conversationParticipants,
12
12
  ParticipantAvatarStack,
13
13
  } from "./ParticipantAvatarStack";
14
+ import { cn, dashboardInlineLinkClass } from "../styles";
14
15
 
15
16
  /** Render the shared conversation title and identity. */
16
17
  export function ConversationSummary(props: { conversation: Conversation }) {
@@ -38,7 +39,7 @@ function ConversationIdentity(props: { conversation: Conversation }) {
38
39
  {location && props.conversation.locationId ? (
39
40
  <>
40
41
  <Link
41
- className="font-semibold text-dashboard-text underline decoration-white/20 underline-offset-2 transition-colors hover:text-dashboard-text hover:decoration-white/60"
42
+ className={cn("font-semibold", dashboardInlineLinkClass)}
42
43
  onClick={(event: MouseEvent<HTMLAnchorElement>) =>
43
44
  event.stopPropagation()
44
45
  }
@@ -7,7 +7,7 @@ export function DetailList(props: { children: ReactNode; className?: string }) {
7
7
  return (
8
8
  <dl
9
9
  className={cn(
10
- "grid gap-px overflow-hidden rounded border border-white/[0.06] bg-white/[0.055]",
10
+ "grid gap-px overflow-hidden rounded-md border border-dashboard-border-subtle bg-dashboard-fill-hover",
11
11
  props.className,
12
12
  )}
13
13
  >
@@ -23,8 +23,8 @@ export function Detail(props: {
23
23
  valueClassName?: string;
24
24
  }) {
25
25
  return (
26
- <div className="min-w-0 bg-[#09090b] px-3 py-3">
27
- <dt className="font-mono text-xs uppercase tracking-[0.12em] text-dashboard-text-muted">
26
+ <div className="min-w-0 bg-dashboard-bg-elevated px-3 py-3">
27
+ <dt className="font-sans font-medium text-xs text-dashboard-text-muted">
28
28
  {props.label}
29
29
  </dt>
30
30
  <dd
@@ -112,7 +112,7 @@ export function Drawer(props: {
112
112
  />
113
113
  <aside
114
114
  className={cn(
115
- "absolute top-0 right-0 grid h-full w-full grid-rows-[auto_minmax(0,1fr)] bg-dashboard-bg-elevated shadow-[-20px_0_60px_rgba(0,0,0,0.45)] md:border-l md:border-dashboard-border-emphasis",
115
+ "absolute top-0 right-0 grid h-full w-full grid-rows-[auto_minmax(0,1fr)] bg-dashboard-bg-elevated shadow-[-20px_0_60px_rgba(0,0,0,0.45)] md:border-l md:border-dashboard-border-strong",
116
116
  props.width === "wide"
117
117
  ? "md:w-[min(760px,94vw)]"
118
118
  : props.width === "narrow"
@@ -120,7 +120,7 @@ export function Drawer(props: {
120
120
  : "md:w-[min(560px,94vw)]",
121
121
  )}
122
122
  >
123
- <header className="relative grid grid-cols-[minmax(0,1fr)_auto] gap-3 border-b border-dashboard-border-strong bg-dashboard-surface-raised px-4 py-3 pt-[max(0.75rem,env(safe-area-inset-top))] md:px-5">
123
+ <header className="relative grid grid-cols-[minmax(0,1fr)_auto] gap-3 border-b border-dashboard-border bg-dashboard-bg-elevated px-4 py-3 pt-[max(0.75rem,env(safe-area-inset-top))] md:px-5">
124
124
  <div className="min-w-0">{props.header}</div>
125
125
  <div className="flex items-start gap-1.5">
126
126
  {props.actions}
@@ -3,7 +3,7 @@ import type { ReactNode } from "react";
3
3
  /** Render the dashboard empty-state block with quiet warning context. */
4
4
  export function EmptyTelemetry(props: { children: ReactNode }) {
5
5
  return (
6
- <div className="min-w-0 rounded-lg border border-white/10 bg-[#050505] px-4 py-3 text-base leading-relaxed text-dashboard-text-muted">
6
+ <div className="min-w-0 rounded-lg border border-dashboard-border-strong bg-dashboard-bg px-4 py-3 text-base leading-relaxed text-dashboard-text-muted">
7
7
  {props.children}
8
8
  </div>
9
9
  );
@@ -5,8 +5,7 @@ import { cn } from "../styles";
5
5
  export type FieldSize = "compact" | "default";
6
6
 
7
7
  const labelClass: Record<FieldSize, string> = {
8
- compact:
9
- "font-mono text-xs uppercase tracking-[0.12em] text-dashboard-text-muted",
8
+ compact: "font-sans font-medium text-xs text-dashboard-text-muted",
10
9
  default: "text-sm font-semibold text-dashboard-text",
11
10
  };
12
11
 
@@ -41,7 +41,7 @@ export function FilterGroup(props: {
41
41
  }) {
42
42
  return (
43
43
  <div className={cn("min-w-0", props.className)}>
44
- <div className="mb-2 font-mono text-xs uppercase tracking-[0.12em] text-dashboard-text-muted">
44
+ <div className="mb-2 font-sans font-medium text-xs text-dashboard-text-muted">
45
45
  {props.label}
46
46
  </div>
47
47
  <div
@@ -71,7 +71,7 @@ export function FilterTabList(props: {
71
71
  return (
72
72
  <div
73
73
  aria-label={props.ariaLabel}
74
- className="grid min-w-0 grid-cols-3 gap-1 border-b border-white/[0.06] sm:flex sm:overflow-x-auto"
74
+ className="grid min-w-0 grid-cols-3 gap-1 border-b border-dashboard-border-subtle sm:flex sm:overflow-x-auto"
75
75
  role="tablist"
76
76
  >
77
77
  {props.items.map((item) => {
@@ -80,9 +80,9 @@ export function FilterTabList(props: {
80
80
  <button
81
81
  aria-selected={selected}
82
82
  className={cn(
83
- "relative flex min-w-0 cursor-pointer items-center justify-between gap-2 border-0 bg-transparent px-3 py-2.5 font-mono text-xs uppercase tracking-[0.1em] transition-colors after:absolute after:inset-x-2 after:bottom-0 after:h-px sm:shrink-0 sm:justify-start",
83
+ "relative flex min-w-0 cursor-pointer items-center justify-between gap-2 border-0 bg-transparent px-3 py-2.5 font-sans font-medium text-xs transition-colors after:absolute after:inset-x-2 after:bottom-0 after:h-px sm:shrink-0 sm:justify-start",
84
84
  selected
85
- ? "text-cyan-100 after:bg-cyan-300"
85
+ ? "text-dashboard-accent-text after:bg-dashboard-accent"
86
86
  : "text-dashboard-text-muted after:bg-transparent hover:text-dashboard-text",
87
87
  )}
88
88
  key={item.value || "all"}
@@ -96,8 +96,8 @@ export function FilterTabList(props: {
96
96
  className={cn(
97
97
  "rounded-sm border px-1.5 py-0.5 text-xs",
98
98
  selected
99
- ? "border-cyan-300/20 bg-cyan-300/10 text-cyan-100"
100
- : "border-white/[0.07] bg-white/[0.025] text-dashboard-text-muted",
99
+ ? "border-dashboard-accent/20 bg-dashboard-accent/10 text-dashboard-accent-text"
100
+ : "border-dashboard-border bg-dashboard-fill-soft text-dashboard-text-muted",
101
101
  )}
102
102
  >
103
103
  {item.count.toLocaleString("en-US")}
@@ -28,10 +28,10 @@ function TooltipLines(props: { lines: MetricTooltipLine[] }) {
28
28
  : cn(
29
29
  "col-span-2 block min-w-0 break-words text-dashboard-text",
30
30
  line.valueStyle === "heading" &&
31
- "font-mono font-semibold text-dashboard-text",
31
+ "font-sans tabular-nums font-semibold text-dashboard-text",
32
32
  line.valueStyle === "heading" &&
33
33
  index > 0 &&
34
- "mt-1 border-t border-white/10 pt-2",
34
+ "mt-1 border-t border-dashboard-border-strong pt-2",
35
35
  )
36
36
  }
37
37
  key={`${index}-${line.label ?? ""}-${line.value}-${line.live ? "live" : ""}`}
@@ -88,7 +88,7 @@ export function MetricValue(props: {
88
88
  <Tooltip
89
89
  align={props.align}
90
90
  className={cn(
91
- "w-[calc(100vw-2rem)] max-w-80 rounded-lg border border-white/15 bg-[#050505] text-left text-xs font-normal text-dashboard-text-muted shadow-xl shadow-black/35",
91
+ "w-[calc(100vw-2rem)] max-w-80 rounded-lg border border-dashboard-border-emphasis bg-dashboard-bg text-left text-xs font-normal text-dashboard-text-muted shadow-xl shadow-black/35",
92
92
  props.tooltipCard ? "p-3 leading-snug" : "px-3 py-2 leading-relaxed",
93
93
  )}
94
94
  content={
@@ -106,7 +106,7 @@ export function MetricValue(props: {
106
106
  >
107
107
  <span
108
108
  className={cn(
109
- "inline-flex border-b border-dotted border-white/20 outline-none transition-colors hover:border-white/45 focus-visible:border-white/45",
109
+ "inline-flex border-b border-dotted border-dashboard-border-interactive outline-none transition-colors hover:border-dashboard-border-heavy focus-visible:border-dashboard-border-heavy",
110
110
  props.className,
111
111
  )}
112
112
  tabIndex={0}
@@ -31,8 +31,8 @@ export function Notice({
31
31
  return (
32
32
  <div
33
33
  className={cn(
34
- "overflow-hidden rounded-xl shadow-[0_16px_40px_rgba(0,0,0,0.5)]",
35
- isError ? "bg-[#1f1216]" : "bg-[#111719]",
34
+ "overflow-hidden rounded-xl border bg-dashboard-surface-raised shadow-[0_16px_40px_rgba(0,0,0,0.5)]",
35
+ isError ? "border-rose-300/25" : "border-dashboard-border-strong",
36
36
  )}
37
37
  >
38
38
  <div className="flex min-w-0 items-center gap-3 px-3 py-3">
@@ -42,7 +42,7 @@ export function Notice({
42
42
  "grid size-8 shrink-0 place-items-center rounded-lg",
43
43
  isError
44
44
  ? "bg-rose-300/15 text-rose-100"
45
- : "bg-cyan-300/10 text-cyan-100/80",
45
+ : "bg-dashboard-accent/10 text-dashboard-accent-text/80",
46
46
  )}
47
47
  >
48
48
  <Icon aria-hidden="true" size={16} />
@@ -61,7 +61,7 @@ export function Notice({
61
61
  {detail ? (
62
62
  <div
63
63
  className={cn(
64
- "mt-0.5 truncate font-mono text-xs",
64
+ "mt-0.5 truncate font-sans text-xs",
65
65
  isError ? "text-rose-100/70" : "text-dashboard-text-muted",
66
66
  )}
67
67
  >
@@ -89,10 +89,10 @@ export function NoticeAction({
89
89
  {...props}
90
90
  className={cn(
91
91
  "shrink-0 cursor-pointer px-3 py-1.5 text-xs transition focus:outline-none focus:ring-2 disabled:cursor-not-allowed disabled:opacity-40",
92
- isError ? "focus:ring-rose-300/40" : "focus:ring-cyan-300/35",
92
+ isError ? "focus:ring-rose-300/40" : "focus:ring-dashboard-focus/35",
93
93
  isError
94
- ? "rounded-lg bg-rose-200/15 font-display font-medium text-rose-50 hover:bg-rose-200/25"
95
- : "rounded-lg bg-cyan-200/10 font-display font-medium text-cyan-100 hover:bg-cyan-200/20",
94
+ ? "rounded-lg bg-rose-200/15 font-sans font-medium text-rose-50 hover:bg-rose-200/25"
95
+ : "rounded-lg bg-dashboard-accent/10 font-sans font-medium text-dashboard-accent-text hover:bg-dashboard-accent/20",
96
96
  className,
97
97
  )}
98
98
  type={type}
@@ -96,7 +96,7 @@ function LibrarySkeleton() {
96
96
  return (
97
97
  <>
98
98
  <div className="flex flex-wrap items-end justify-between gap-4">
99
- <SkeletonBone className="h-7 w-56 rounded bg-dashboard-fill-soft" />
99
+ <SkeletonBone className="h-7 w-56 rounded-md bg-dashboard-fill-soft" />
100
100
  <SkeletonBone className="h-10 w-full max-w-md rounded-lg border border-dashboard-border-subtle bg-dashboard-fill-faint sm:w-72" />
101
101
  </div>
102
102
  <div
@@ -108,7 +108,7 @@ function LibrarySkeleton() {
108
108
  className="flex items-center justify-between gap-2 px-3 py-2.5 sm:justify-start"
109
109
  key={index}
110
110
  >
111
- <SkeletonBone className="h-3 w-12 rounded bg-dashboard-fill-soft" />
111
+ <SkeletonBone className="h-3 w-12 rounded-md bg-dashboard-fill-soft" />
112
112
  <SkeletonBone className="h-5 w-8 rounded-sm border border-dashboard-border-subtle bg-dashboard-fill-faint" />
113
113
  </div>
114
114
  ))}
@@ -61,7 +61,7 @@ export function PagePagination(props: {
61
61
  props.className,
62
62
  )}
63
63
  >
64
- <p className="m-0 font-mono text-xs text-dashboard-text-muted">
64
+ <p className="m-0 font-sans tabular-nums text-xs text-dashboard-text-muted">
65
65
  Showing {start.toLocaleString("en-US")}-{end.toLocaleString("en-US")} of{" "}
66
66
  {props.total.toLocaleString("en-US")}
67
67
  </p>
@@ -74,7 +74,7 @@ export function PagePagination(props: {
74
74
  >
75
75
  <ChevronLeft aria-hidden="true" size={16} />
76
76
  </Button>
77
- <span className="min-w-16 text-center font-mono text-xs text-dashboard-text-muted">
77
+ <span className="min-w-16 text-center font-sans tabular-nums text-xs text-dashboard-text-muted">
78
78
  {current} / {props.pageCount}
79
79
  </span>
80
80
  <Button
@@ -45,7 +45,7 @@ function ParticipantTooltipContent(props: { participant: ActorIdentity }) {
45
45
  <span className="grid gap-0.5 font-sans">
46
46
  <span className="font-semibold text-dashboard-text">{name}</span>
47
47
  {email && email !== name ? (
48
- <span className="font-mono text-dashboard-text-muted">{email}</span>
48
+ <span className="font-sans text-dashboard-text-muted">{email}</span>
49
49
  ) : null}
50
50
  </span>
51
51
  );
@@ -60,7 +60,7 @@ function Avatar(props: {
60
60
  <Tooltip
61
61
  content={<ParticipantTooltipContent participant={props.participant} />}
62
62
  focusable
63
- triggerClassName="-ml-1.5 first:ml-0 pointer-events-none [@media(hover:hover)_and_(pointer:fine)]:pointer-events-auto"
63
+ triggerClassName="-ml-1 first:ml-0 pointer-events-none [@media(hover:hover)_and_(pointer:fine)]:pointer-events-auto"
64
64
  >
65
65
  <span
66
66
  aria-label={label}
@@ -116,14 +116,14 @@ export function ParticipantAvatarStack(props: ParticipantAvatarStackProps) {
116
116
  </span>
117
117
  }
118
118
  focusable
119
- triggerClassName="-ml-1.5 pointer-events-none [@media(hover:hover)_and_(pointer:fine)]:pointer-events-auto"
119
+ triggerClassName="-ml-1 pointer-events-none [@media(hover:hover)_and_(pointer:fine)]:pointer-events-auto"
120
120
  >
121
121
  <span
122
122
  aria-label={`${hidden.length} more participants: ${hidden
123
123
  .map(participantDescription)
124
124
  .join("; ")}`}
125
125
  className={cn(
126
- "relative inline-grid shrink-0 place-items-center rounded-full border-2 border-dashboard-bg bg-dashboard-fill-strong font-mono font-semibold leading-none text-dashboard-text-muted focus-visible:z-10 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-dashboard-focus",
126
+ "relative inline-grid shrink-0 place-items-center rounded-full border-2 border-dashboard-bg bg-dashboard-surface-active font-sans font-semibold tabular-nums leading-none text-dashboard-text-muted focus-visible:z-10 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-dashboard-focus",
127
127
  props.size === "list" ? "size-6 text-2xs" : "size-7 text-xs",
128
128
  )}
129
129
  onKeyDown={(event) => event.stopPropagation()}
@@ -155,7 +155,7 @@ export function ProfileMenu({
155
155
  ) : null}
156
156
  </div>
157
157
  </div>
158
- <div className="mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 font-mono text-xs tabular-nums text-dashboard-text-muted">
158
+ <div className="mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 font-sans text-xs tabular-nums text-dashboard-text-muted">
159
159
  <span>
160
160
  7d{" "}
161
161
  <span className="font-semibold text-dashboard-text">
@@ -230,11 +230,9 @@ export function ProfileMenu({
230
230
  return (
231
231
  <div
232
232
  aria-label={`Personal model spend: 7 days ${sevenDaySpend}, 30 days ${thirtyDaySpend}`}
233
- className="grid gap-1.5 rounded-lg border border-dashboard-border bg-dashboard-fill-soft px-3 py-2.5 font-mono text-xs tabular-nums text-dashboard-text-muted"
233
+ className="grid gap-1.5 rounded-lg border border-dashboard-border bg-dashboard-fill-soft px-3 py-2.5 font-sans text-xs tabular-nums text-dashboard-text-muted"
234
234
  >
235
- <span className="text-xs font-medium uppercase tracking-[0.08em]">
236
- Spend
237
- </span>
235
+ <span className="text-xs font-medium">Spend</span>
238
236
  <span className="whitespace-nowrap">
239
237
  7d{" "}
240
238
  <span className="font-semibold text-dashboard-text">
@@ -254,7 +252,7 @@ export function ProfileMenu({
254
252
  if (variant === "sheet-links") {
255
253
  // Match primary sheet rows exactly.
256
254
  const sheetItemClass = cn(
257
- "rounded-lg border-0 bg-transparent px-3 py-3 text-left font-mono text-sm font-medium tracking-normal no-underline transition-colors hover:bg-dashboard-fill-soft focus-visible:bg-dashboard-fill-soft focus-visible:outline-none",
255
+ "rounded-lg border-0 bg-transparent px-3 py-3 text-left font-sans text-sm font-medium no-underline transition-colors hover:bg-dashboard-fill-soft focus-visible:bg-dashboard-fill-soft focus-visible:outline-none",
258
256
  dashboardInteractiveTextClass,
259
257
  );
260
258
  return (
@@ -313,7 +311,7 @@ export function ProfileMenu({
313
311
  {name}
314
312
  </p>
315
313
  {name !== email ? (
316
- <p className="mt-0.5 mb-0 truncate font-mono text-xs text-dashboard-text-muted">
314
+ <p className="mt-0.5 mb-0 truncate font-sans text-xs text-dashboard-text-muted">
317
315
  {email}
318
316
  </p>
319
317
  ) : null}
@@ -1,55 +1,128 @@
1
1
  # Dashboard UI kit
2
2
 
3
3
  Shared dashboard components live here. Feature pages compose these surfaces
4
- instead of copying Tailwind blocks.
5
-
6
- ## Layers
7
-
8
- 1. **Primitives** — `Button` / `ToggleButton`, `Field`, `TextInput`,
9
- `StatusChip`, `StatusDot`, `Notice`, `FormNotice`, `Select`, `Drawer`, `Tooltip`, `Skeleton`,
10
- `PageContentSkeleton`, `SegmentedTabs`, `SegmentedNav`, and other small reusable controls.
11
- Use the segmented pill track to pick one of a few siblings. Use
12
- `SegmentedTabs` to switch panels in place. Pass the selected value, items,
13
- change handler, and selected panel content. It owns tab/panel labels and
14
- keyboard focus. Use `SegmentedNav` for links between sibling pages. With
15
- `fill`, links share the row width equally while their labels fit. Otherwise
16
- each link keeps its label width. Rows that do not fit scroll sideways. Keep
17
- collection filters in `FilterTabList`. Prefer
18
- `ToggleButton` variants (`pill`, `segment`, `text`) over one-off pressed
19
- styles. Prefer `Field` sizes (`default`, `compact`) over handwritten labels.
20
- Prefer `StatusDot` for dense table or list status markers and `StatusChip`
21
- when the label itself must stay visible. `StatusChip` uses a small dot and
22
- sentence-case text, without a border, fill, or all-caps styling. It is not
23
- an interactive control. Prefer `PageContentSkeleton`
24
- variants over ad-hoc pulse blocks in route modules. Use `PageRouteLoading`
25
- when a standard page must keep its real header above a body skeleton. Use a
26
- feature-owned loading component for distinct geometry, such as conversations.
27
- `ObjectIcon` owns native Ticket, Code change, Automation, Deployment, and
28
- Item icons. It uses the shared type/status mapping and original Octicons
29
- paths. Do not replace it with a provider logo or a status-only icon.
30
- Structural colors live
31
- as slim `dashboard-*` tokens in `src/tailwind.css` (canvas, surface, text,
32
- border, fill, overlay, focus). Prefer those roles over `white/*`, `black/*`,
33
- or hex literals. Status accents stay as Tailwind palette utilities.
34
- 2. **Patterns** — layout, filters, directory tables, charts, metrics.
35
- Activity time-series charts own bucket labels in
36
- `charts/ActivityChart` (`formatActivityDate` for axes,
37
- `ActivityChartTooltip` / `formatActivityTooltipDate` for hover labels).
38
- New day/hour charts should compose those helpers instead of formatting
39
- UTC bucket keys inline.
40
- Conversation mobile geometry is a hard ownership edge (see
41
- `policies/frontend-components.md`):
42
- - `layout/VisualViewportShell` — fixed shell, visualViewport CSS vars, body lock
43
- - `conversations/ChatLayout` — scroll-above-dock frame for reply threads
44
- - `conversations/ComposerDock` — reply bottom pad / dock chrome only
45
- Pages pass children only. Home and create are one landing surface, not a dock,
46
- and must
47
- not reuse `ComposerDock`. Do not invent viewport height, offset, or bottom
48
- safe-area math in page modules.
49
- 3. **Features** — stay under `conversations/` or `pages/` until a surface is
50
- shared by two real callers. Transcript layout stays in `conversations/`;
51
- see [Transcript components](../conversations/README.md) for ownership.
52
- Context panels use the shared `Drawer`, not a separate modal implementation.
4
+ instead of copying Tailwind blocks. See `policies/frontend-components.md` for
5
+ the policy. `pnpm dashboard-style:check` enforces the token rules below.
6
+
7
+ ## Foundations
8
+
9
+ Tokens live in the `@theme` block of `src/tailwind.css`. Light mode does not
10
+ exist yet. Keep every color in a token so a second theme can redefine them.
11
+
12
+ - **Surfaces.** Use the surface ladder, darkest to lightest: `bg`,
13
+ `bg-elevated` (drawers), `surface-panel` (sidebar, cards, bubbles),
14
+ `surface-raised` (buttons, tooltips), `control`, `surface-hover`,
15
+ `surface-active` (selected rows). Use `fill-*` for translucent fills and
16
+ `overlay-*` for scrims. Do not use `white/*` or `black/*` fills, borders, or
17
+ rings, or hex surface colors. Shadows may use black.
18
+ - **Borders.** Use `border-subtle` for hairlines inside a surface,
19
+ `border` for card edges, `border-strong` for shell edges, and
20
+ `border-emphasis` or `border-interactive` for controls and hover.
21
+ - **Text.** Brightest to dimmest: `text-solid`, `text`, `text-subtle`,
22
+ `text-muted`, `text-faint`.
23
+ - **Accent.** Lavender is the one brand accent. Use `accent` for icons,
24
+ active markers, and tinted fills, such as `bg-dashboard-accent/10`. Use
25
+ `accent-text` for links and accent text. Keep Tailwind palette colors for
26
+ status (info, success, warning, error) and for categorical chart, event, and
27
+ subagent colors.
28
+ - **Focus.** Use `outline-dashboard-focus` for keyboard focus. Do not use other
29
+ colors for focus rings.
30
+ - **Type faces.** `font-sans` is the UI face for prose, controls, navigation,
31
+ labels, and names. `font-display` is for headings, record titles, and large
32
+ metric values. `font-mono` is for machine values: code, ids, paths, file
33
+ names, tool names, and raw payloads. Show counts, times, and prices in
34
+ `font-sans tabular-nums`.
35
+ - **Type scale.** Use the named steps `text-2xs` through `text-4xl`. Keep
36
+ `text-2xs` for compact badges and chart annotations.
37
+ - **Labels.** Section, card, field, and column labels use
38
+ `font-sans text-xs font-medium text-dashboard-text-muted` in sentence case.
39
+ Do not use uppercase or letter spacing for labels.
40
+ - **Radius.** Controls and chips use `rounded-md`. Cards, list rows, and panels
41
+ use `rounded-lg`. The composer, menus, and transcript object cards use
42
+ `rounded-xl`. Avatars and count badges use `rounded-full`.
43
+
44
+ ## Shared class helpers
45
+
46
+ `src/client/styles.ts` holds the few class strings that many components share.
47
+
48
+ - `cn` joins class names.
49
+ - `dashboardContainerClass` sets the page width.
50
+ - `dashboardInlineLinkClass` styles a neutral underlined link inside prose.
51
+ - `dashboardInteractiveTextClass` styles muted text that brightens on hover.
52
+ - `dashboardComposerSurfaceClass` styles the composer surface.
53
+
54
+ ## Components
55
+
56
+ ### Primitives
57
+
58
+ - **Actions.** `Button` (`default`, `primary`, `danger`, and `size="icon"`) and
59
+ `ButtonLink`. Form pages use `Button tone="primary"` for their one main save
60
+ action. Use `ToggleButton` variants (`pill`, `segment`, `text`) for pressed
61
+ states, not one-off styles.
62
+ - **Forms.** `Field` (`default`, `compact`), `TextInput`, `TextArea`, `Select`,
63
+ and `SearchInput`. Use `TextInput size="comfortable"` for larger mobile
64
+ controls. Use `TextArea prose` for instructions, not code. `Field error`
65
+ renders an error at `<htmlFor>-error`. The owning control must set
66
+ `aria-invalid` and `aria-describedby`. `Select` matches native text controls.
67
+ - **Status.** Use `StatusDot` for dense table or list markers. Use `StatusChip`
68
+ when the label must stay visible. `StatusChip` is a small dot and
69
+ sentence-case text, with no border or fill. It is not a control.
70
+ - **Messages.** Use `Notice` for compact transient messages and `FormNotice`
71
+ for wrapping form recovery text.
72
+ - **Overlays.** `Drawer` owns dismissal, focus trapping, focus return, scroll
73
+ locking, and panel layout. Context panels use it, not a separate modal.
74
+ `Tooltip` and `IconButtonTooltip` own hover text.
75
+ - **Identity.** `ActorAvatar`, `ParticipantAvatarStack`, and `ObjectIcon`.
76
+ `ObjectIcon` owns native Ticket, Code change, Automation, Deployment, and
77
+ Item icons. It uses the shared type and status mapping and the original
78
+ Octicons paths. Do not replace it with a provider logo or a status-only icon.
79
+ - **Loading.** Use `Skeleton` for placeholder leaves and `PageContentSkeleton`
80
+ variants for page bodies. Use `PageRouteLoading` when a page keeps its real
81
+ header above a body skeleton. Use a feature-owned loading component for
82
+ distinct geometry, such as conversations.
83
+
84
+ ### Navigation
85
+
86
+ The dashboard has three navigation levels. Each has its own look, so the
87
+ levels stay distinct.
88
+
89
+ - **App navigation** in `layout/DashboardHeader` uses pills.
90
+ - **Page links** use `SegmentedNav`, through `layout/SecondaryNavigation`. They
91
+ are underline tabs that sit on the header border. With `fill`, links share
92
+ the row width while their labels fit. Rows that do not fit scroll sideways.
93
+ - **Panel switches** use `SegmentedTabs`, which draws a pill track. Pass the
94
+ selected value, items, change handler, and panel content. It owns tab and
95
+ panel labels and keyboard focus.
96
+
97
+ Keep collection filters in `FilterTabList`.
98
+
99
+ ### Patterns
100
+
101
+ - **Layout.** `layout/` holds the shell chrome, page headers, cards, and
102
+ section titles. `DashboardChrome` owns the sticky header block and its one
103
+ bottom border.
104
+ - **Directory tables and metrics.** `directory/` and `metrics/`.
105
+ - **Charts.** Activity time-series charts own bucket labels in
106
+ `charts/ActivityChart` (`formatActivityDate` for axes,
107
+ `ActivityChartTooltip` and `formatActivityTooltipDate` for hover labels). New
108
+ day or hour charts compose those helpers. They do not format UTC bucket keys
109
+ inline.
110
+ - **Conversation mobile geometry** is a hard ownership edge:
111
+ - `layout/VisualViewportShell` owns the fixed shell, visualViewport CSS
112
+ variables, and body lock.
113
+ - `conversations/ChatLayout` owns the scroll-above-dock frame for reply
114
+ threads.
115
+ - `conversations/ComposerDock` owns the reply bottom pad and dock chrome.
116
+
117
+ Pages pass children only. Home and create are one landing surface, not a
118
+ dock, and must not use `ComposerDock`. Do not add viewport height, offset, or
119
+ bottom safe-area math in page modules.
120
+
121
+ ### Features
122
+
123
+ Feature surfaces stay under `conversations/` or `pages/` until two real callers
124
+ share them. Transcript layout stays in `conversations/`. See
125
+ [Transcript components](../conversations/README.md) for ownership.
53
126
 
54
127
  ## Rules
55
128
 
@@ -58,12 +131,3 @@ instead of copying Tailwind blocks.
58
131
  - Add gallery fixtures under `/dev/<section>` for new or changed shared
59
132
  components. Keep the `/dev` index as the catalog only.
60
133
  - One-off page glue may stay inline when extraction only adds indirection.
61
-
62
- See `policies/frontend-components.md`.
63
-
64
- Use `TextInput size="comfortable"` for larger mobile form controls.
65
- Form pages use `Button tone="primary"` for their one main save action. Use
66
- `TextArea prose` for instructions rather than code. `Field error` renders an
67
- error at `<htmlFor>-error`; the owning control must set `aria-invalid` and
68
- `aria-describedby`. `Select` matches native text controls. Use `FormNotice` for
69
- wrapping form recovery text; use `Notice` for compact transient messages.
@@ -30,7 +30,7 @@ export function SearchInput(props: {
30
30
  <input
31
31
  aria-label={props.label}
32
32
  className={cn(
33
- "w-full rounded-lg border border-dashboard-border font-mono text-xs text-dashboard-text outline-none transition-colors placeholder:text-dashboard-text-muted hover:border-dashboard-border-emphasis focus:border-dashboard-focus",
33
+ "w-full rounded-md border border-dashboard-border font-sans text-sm text-dashboard-text outline-none transition-colors placeholder:text-dashboard-text-muted/70 hover:border-dashboard-border-emphasis focus:border-dashboard-focus",
34
34
  searchInputClass[size],
35
35
  )}
36
36
  onChange={(event) => props.onChange(event.currentTarget.value)}
@@ -49,7 +49,8 @@ const searchIconClass: Record<SearchInputSize, string> = {
49
49
  };
50
50
 
51
51
  const searchInputClass: Record<SearchInputSize, string> = {
52
- compact: "h-9 bg-dashboard-overlay-soft pr-3 pl-8 focus:ring-1 focus:ring-dashboard-focus/25",
52
+ compact:
53
+ "h-9 bg-dashboard-overlay-soft pr-3 pl-8 focus:ring-1 focus:ring-dashboard-focus/25",
53
54
  default:
54
- "h-10 bg-dashboard-overlay-soft pr-3 pl-9 focus:ring-2 focus:ring-dashboard-focus/20",
55
+ "h-10 bg-dashboard-overlay-soft pr-3 pl-9 focus:ring-1 focus:ring-dashboard-focus/25",
55
56
  };