@sentry/junior-dashboard 0.248.0 → 0.250.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.
- package/README.md +3 -0
- package/dist/app.js +2 -2
- package/dist/client.js +40 -38
- package/dist/index.js +2 -2
- package/dist/tailwind.css +1 -1
- package/package.json +3 -3
- package/src/client/App.tsx +19 -5
- package/src/client/components/ActorAvatar.tsx +7 -4
- package/src/client/components/AutomationCard.tsx +2 -2
- package/src/client/components/Button.tsx +12 -11
- package/src/client/components/ConversationList.tsx +3 -3
- package/src/client/components/ConversationSummary.tsx +2 -1
- package/src/client/components/DetailList.tsx +3 -3
- package/src/client/components/Drawer.tsx +2 -2
- package/src/client/components/EmptyTelemetry.tsx +1 -1
- package/src/client/components/Field.tsx +1 -2
- package/src/client/components/FilterBar.tsx +6 -6
- package/src/client/components/Metric.tsx +4 -4
- package/src/client/components/Notice.tsx +7 -7
- package/src/client/components/PageContentSkeleton.tsx +2 -2
- package/src/client/components/Pagination.tsx +2 -2
- package/src/client/components/ParticipantAvatarStack.tsx +4 -4
- package/src/client/components/ProfileMenu.tsx +17 -7
- package/src/client/components/README.md +122 -58
- package/src/client/components/SearchInput.tsx +4 -3
- package/src/client/components/SegmentedNav.tsx +10 -17
- package/src/client/components/SegmentedTabs.tsx +3 -3
- package/src/client/components/Select.tsx +1 -1
- package/src/client/components/SelectableRow.tsx +2 -2
- package/src/client/components/Skeleton.tsx +1 -1
- package/src/client/components/StatusChip.tsx +1 -1
- package/src/client/components/StatusDot.tsx +1 -1
- package/src/client/components/TextInput.tsx +1 -1
- package/src/client/components/Tooltip.tsx +2 -2
- package/src/client/components/VersionDriftBanner.tsx +2 -2
- package/src/client/components/charts/ActivityChart.tsx +5 -6
- package/src/client/components/charts/CacheWrites.tsx +3 -3
- package/src/client/components/charts/ChartHeader.tsx +4 -4
- package/src/client/components/charts/ChartLegend.tsx +1 -1
- package/src/client/components/charts/InputCacheChart.tsx +5 -5
- package/src/client/components/charts/WorkspaceUsageChart.tsx +4 -11
- package/src/client/components/controls/DirectorySortSelect.tsx +2 -2
- package/src/client/components/directory/DirectoryMetric.tsx +2 -2
- package/src/client/components/directory/DirectoryRowsSkeleton.tsx +5 -5
- package/src/client/components/directory/DirectoryTable.tsx +3 -3
- package/src/client/components/layout/CardHeader.tsx +4 -4
- package/src/client/components/layout/DashboardChrome.tsx +9 -3
- package/src/client/components/layout/DashboardHeader.tsx +7 -7
- package/src/client/components/layout/PageHeader.tsx +2 -2
- package/src/client/components/layout/SecondaryNavigation.tsx +7 -14
- package/src/client/components/layout/SectionIntro.tsx +1 -1
- package/src/client/components/layout/SectionTitle.tsx +1 -1
- package/src/client/components/metrics/StatCard.tsx +2 -2
- package/src/client/conversations/ConversationArchiveNotices.tsx +1 -1
- package/src/client/conversations/ConversationBrief.tsx +4 -4
- package/src/client/conversations/ConversationChildAgents.tsx +7 -4
- package/src/client/conversations/ConversationComposer.tsx +8 -7
- package/src/client/conversations/ConversationHeader.tsx +5 -5
- package/src/client/conversations/ConversationHeaderActions.tsx +9 -9
- package/src/client/conversations/ConversationHomeList.tsx +3 -3
- package/src/client/conversations/ConversationListStatusIcon.tsx +1 -1
- package/src/client/conversations/ConversationMemories.tsx +4 -4
- package/src/client/conversations/ConversationMeta.tsx +10 -10
- package/src/client/conversations/ConversationPage.tsx +2 -1
- package/src/client/conversations/ConversationSidebar.tsx +6 -6
- package/src/client/conversations/ConversationUsageBreakdown.tsx +4 -4
- package/src/client/conversations/ConversationWorkspace.tsx +1 -1
- package/src/client/conversations/ConversationWorkspaceLoading.tsx +4 -4
- package/src/client/conversations/CopyMarkdownButton.tsx +1 -1
- package/src/client/conversations/EventUsage.tsx +2 -2
- package/src/client/conversations/PendingMailboxStack.tsx +5 -5
- package/src/client/conversations/README.md +9 -0
- package/src/client/conversations/SubagentTranscriptDrawer.tsx +39 -23
- package/src/client/conversations/ToolFrame.tsx +36 -14
- package/src/client/conversations/TranscriptActivityGroup.tsx +10 -3
- package/src/client/conversations/TranscriptAttachmentsDeliveredView.tsx +4 -6
- package/src/client/conversations/TranscriptContextEventView.tsx +2 -2
- package/src/client/conversations/TranscriptEventView.tsx +1 -1
- package/src/client/conversations/TranscriptMarkdown.tsx +3 -3
- package/src/client/conversations/TranscriptMessageContextView.tsx +7 -7
- package/src/client/conversations/TranscriptMessageView.tsx +2 -6
- package/src/client/conversations/TranscriptRailEvent.tsx +20 -8
- package/src/client/conversations/TranscriptReasoningView.tsx +12 -12
- package/src/client/conversations/TranscriptStructuredEventView.tsx +16 -11
- package/src/client/conversations/TranscriptSubagentView.tsx +64 -39
- package/src/client/conversations/TranscriptText.tsx +5 -4
- package/src/client/conversations/TranscriptToolView.tsx +9 -11
- package/src/client/conversations/TranscriptTurnContextView.tsx +3 -3
- package/src/client/conversations/TranscriptView.tsx +3 -3
- package/src/client/conversations/UsageCard.tsx +1 -1
- package/src/client/conversations/eventTranscript.ts +7 -0
- package/src/client/conversations/transcriptMarkdownLinks.ts +2 -4
- package/src/client/conversations/transcriptStyles.ts +1 -1
- package/src/client/pages/ConnectionsPage.tsx +207 -0
- package/src/client/pages/PersonalTokensPage.tsx +4 -4
- package/src/client/pages/admin/AdminPage.tsx +2 -2
- package/src/client/pages/automations/AutomationCostChart.tsx +2 -2
- package/src/client/pages/automations/AutomationDetailsDrawer.tsx +5 -10
- package/src/client/pages/automations/AutomationEditor.tsx +1 -1
- package/src/client/pages/automations/AutomationExecutionChart.tsx +2 -2
- package/src/client/pages/automations/AutomationExecutionStatusChart.tsx +2 -2
- package/src/client/pages/automations/AutomationExecutionsPage.tsx +4 -4
- package/src/client/pages/automations/AutomationRow.tsx +4 -4
- package/src/client/pages/automations/AutomationRunsPage.tsx +3 -3
- package/src/client/pages/automations/AutomationScheduleFields.tsx +1 -1
- package/src/client/pages/automations/AutomationVersionsPage.tsx +1 -1
- package/src/client/pages/code/CodeActivityChart.tsx +7 -6
- package/src/client/pages/code/CodeChangeRow.tsx +1 -1
- package/src/client/pages/code/CodePage.tsx +5 -5
- package/src/client/pages/code/RepositoryPage.tsx +2 -2
- package/src/client/pages/dev/ChartFixtures.tsx +265 -21
- package/src/client/pages/dev/ComponentsPage.tsx +40 -146
- package/src/client/pages/dev/TranscriptActivityFixtures.tsx +206 -0
- package/src/client/pages/locations/LocationDetailPage.tsx +4 -4
- package/src/client/pages/locations/LocationDirectory.tsx +1 -1
- package/src/client/pages/locations/PrivateActivityCard.tsx +3 -3
- package/src/client/pages/memory/MemoryCostChart.tsx +3 -5
- package/src/client/pages/memory/MemoryDetailsDrawer.tsx +5 -5
- package/src/client/pages/memory/MemoryPage.tsx +15 -15
- package/src/client/pages/memory/MemoryTimeline.tsx +3 -5
- package/src/client/pages/people/ContributionGrid.tsx +8 -5
- package/src/client/pages/people/PersonProfilePage.tsx +3 -6
- package/src/client/pages/people/ProfilePluginReports.tsx +2 -2
- package/src/client/pages/system/GuardianActivity.tsx +9 -9
- package/src/client/pages/system/PluginBarChart.tsx +4 -6
- package/src/client/pages/system/PluginDetails.tsx +11 -7
- package/src/client/pages/system/PluginPanels.tsx +8 -8
- package/src/client/pages/system/PluginReportRecordSet.tsx +14 -14
- package/src/client/pages/system/PluginReports.tsx +7 -11
- package/src/client/pages/system/SkillInventory.tsx +9 -9
- package/src/client/pages/system/SystemActivity.tsx +1 -1
- package/src/client/pages/system/SystemPage.tsx +3 -6
- package/src/client/pages/system/WorkspaceDetails.tsx +2 -5
- package/src/client/pages/system/WorkspaceEditor.tsx +2 -2
- package/src/client/pages/system/WorkspaceList.tsx +2 -2
- package/src/client/pages/user/PluginUserPage.tsx +3 -3
- package/src/client/styles.ts +5 -4
- package/src/client/types.ts +2 -0
- package/src/tailwind.css +36 -38
|
@@ -9,15 +9,18 @@ export function ActorAvatar(props: {
|
|
|
9
9
|
}) {
|
|
10
10
|
const [failedUrl, setFailedUrl] = useState<string>();
|
|
11
11
|
const words = props.name.trim().split(/\s+/).filter(Boolean);
|
|
12
|
+
// The compact size fits one initial at the 12px type floor.
|
|
12
13
|
const initials =
|
|
13
|
-
|
|
14
|
-
?
|
|
15
|
-
:
|
|
14
|
+
props.size === "list"
|
|
15
|
+
? props.name.trim().slice(0, 1)
|
|
16
|
+
: words.length > 1
|
|
17
|
+
? `${words[0]![0]}${words.at(-1)![0]}`
|
|
18
|
+
: props.name.slice(0, 2);
|
|
16
19
|
return (
|
|
17
20
|
<span
|
|
18
21
|
aria-hidden="true"
|
|
19
22
|
className={cn(
|
|
20
|
-
"relative inline-grid shrink-0 place-items-center overflow-hidden rounded-full border-2 border-dashboard-bg bg-dashboard-focus font-sans font-
|
|
23
|
+
"relative inline-grid shrink-0 place-items-center overflow-hidden rounded-full border-2 border-dashboard-bg bg-dashboard-focus font-sans font-semibold leading-none tracking-tight text-dashboard-text-inverse shadow-sm",
|
|
21
24
|
props.size === "list" ? "size-6 text-2xs" : "size-7 text-xs",
|
|
22
25
|
)}
|
|
23
26
|
>
|
|
@@ -21,7 +21,7 @@ export function AutomationCard({
|
|
|
21
21
|
className="my-1 w-full min-w-0 max-w-[37.5rem] overflow-hidden rounded-xl border border-dashboard-border-emphasis bg-dashboard-surface-panel text-sm"
|
|
22
22
|
>
|
|
23
23
|
<div className="flex items-center gap-3 px-4 pb-3 pt-4 md:px-5">
|
|
24
|
-
<span className="grid size-9 shrink-0 place-items-center rounded-lg border border-dashboard-border bg-dashboard-fill-soft text-
|
|
24
|
+
<span className="grid size-9 shrink-0 place-items-center rounded-lg border border-dashboard-border bg-dashboard-fill-soft text-dashboard-accent-text">
|
|
25
25
|
<ObjectIcon objectType="automation" status={card.status} size={18} />
|
|
26
26
|
</span>
|
|
27
27
|
<span className="min-w-0 flex-1 break-words text-base font-semibold text-dashboard-text">
|
|
@@ -65,7 +65,7 @@ export function AutomationCard({
|
|
|
65
65
|
<div className="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t border-dashboard-border bg-dashboard-fill-faint px-4 py-3 md:px-5">
|
|
66
66
|
<Link
|
|
67
67
|
to={automationPath(card.id)}
|
|
68
|
-
className="inline-flex shrink-0 items-center gap-2 rounded-sm text-xs font-medium text-
|
|
68
|
+
className="inline-flex shrink-0 items-center gap-2 rounded-sm text-xs font-medium text-dashboard-accent-text no-underline hover:underline focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-dashboard-focus"
|
|
69
69
|
>
|
|
70
70
|
Open automation
|
|
71
71
|
<ArrowUpRight aria-hidden="true" size={14} />
|
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
102
|
-
text: "cursor-pointer border-0 bg-transparent px-1.5 py-1 font-
|
|
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:
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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-
|
|
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-
|
|
27
|
-
<dt className="font-
|
|
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-
|
|
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
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
100
|
-
: "border-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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 ? "
|
|
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-
|
|
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-
|
|
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-
|
|
92
|
+
isError ? "focus:ring-rose-300/40" : "focus:ring-dashboard-focus/35",
|
|
93
93
|
isError
|
|
94
|
-
? "rounded-lg bg-rose-200/15 font-
|
|
95
|
-
: "rounded-lg bg-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
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-
|
|
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()}
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
ChevronDown,
|
|
4
4
|
KeyRound,
|
|
5
5
|
LogOut,
|
|
6
|
+
Plug,
|
|
6
7
|
Settings,
|
|
7
8
|
ShieldCheck,
|
|
8
9
|
UserRound,
|
|
@@ -155,7 +156,7 @@ export function ProfileMenu({
|
|
|
155
156
|
) : null}
|
|
156
157
|
</div>
|
|
157
158
|
</div>
|
|
158
|
-
<div className="mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 font-
|
|
159
|
+
<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
160
|
<span>
|
|
160
161
|
7d{" "}
|
|
161
162
|
<span className="font-semibold text-dashboard-text">
|
|
@@ -194,6 +195,14 @@ export function ProfileMenu({
|
|
|
194
195
|
<KeyRound aria-hidden="true" size={16} strokeWidth={2} />
|
|
195
196
|
API tokens
|
|
196
197
|
</Link>
|
|
198
|
+
<Link
|
|
199
|
+
className={profileLinkClass}
|
|
200
|
+
onClick={close}
|
|
201
|
+
to="/settings/connections"
|
|
202
|
+
>
|
|
203
|
+
<Plug aria-hidden="true" size={16} strokeWidth={2} />
|
|
204
|
+
Connected accounts
|
|
205
|
+
</Link>
|
|
197
206
|
{identity.user.isAdmin ? (
|
|
198
207
|
<Link className={profileLinkClass} onClick={close} to="/admin">
|
|
199
208
|
<ShieldCheck aria-hidden="true" size={16} strokeWidth={2} />
|
|
@@ -230,11 +239,9 @@ export function ProfileMenu({
|
|
|
230
239
|
return (
|
|
231
240
|
<div
|
|
232
241
|
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-
|
|
242
|
+
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
243
|
>
|
|
235
|
-
<span className="text-xs font-medium
|
|
236
|
-
Spend
|
|
237
|
-
</span>
|
|
244
|
+
<span className="text-xs font-medium">Spend</span>
|
|
238
245
|
<span className="whitespace-nowrap">
|
|
239
246
|
7d{" "}
|
|
240
247
|
<span className="font-semibold text-dashboard-text">
|
|
@@ -254,7 +261,7 @@ export function ProfileMenu({
|
|
|
254
261
|
if (variant === "sheet-links") {
|
|
255
262
|
// Match primary sheet rows exactly.
|
|
256
263
|
const sheetItemClass = cn(
|
|
257
|
-
"rounded-lg border-0 bg-transparent px-3 py-3 text-left font-
|
|
264
|
+
"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
265
|
dashboardInteractiveTextClass,
|
|
259
266
|
);
|
|
260
267
|
return (
|
|
@@ -268,6 +275,9 @@ export function ProfileMenu({
|
|
|
268
275
|
<Link className={sheetItemClass} to="/settings/api-tokens">
|
|
269
276
|
API tokens
|
|
270
277
|
</Link>
|
|
278
|
+
<Link className={sheetItemClass} to="/settings/connections">
|
|
279
|
+
Connected accounts
|
|
280
|
+
</Link>
|
|
271
281
|
{identity.user.isAdmin ? (
|
|
272
282
|
<Link className={sheetItemClass} to="/admin">
|
|
273
283
|
Admin
|
|
@@ -313,7 +323,7 @@ export function ProfileMenu({
|
|
|
313
323
|
{name}
|
|
314
324
|
</p>
|
|
315
325
|
{name !== email ? (
|
|
316
|
-
<p className="mt-0.5 mb-0 truncate font-
|
|
326
|
+
<p className="mt-0.5 mb-0 truncate font-sans text-xs text-dashboard-text-muted">
|
|
317
327
|
{email}
|
|
318
328
|
</p>
|
|
319
329
|
) : null}
|