Docs, ticks, working app

This commit is contained in:
Hugh Kaznowski
2026-09-05 15:05:39 +01:00
parent 41362aa3d8
commit 51e577f01e
41 changed files with 1039 additions and 683 deletions
+23 -23
View File
@@ -61,10 +61,10 @@ function PanelPreview({ panel, range }: { panel: Panel; range: TimeRange | null
}, [panel.promql, panel.chart_type, range?.startMs, range?.endMs])
if (error) {
return <div className="rounded border border-red-900 bg-red-950/50 px-2 py-1 text-xs text-red-400">{error}</div>
return <div className="rounded border border-danger-border bg-danger-bg/50 px-2 py-1 text-xs text-danger-text">{error}</div>
}
if (loading && series.length === 0) {
return <div className="flex h-48 items-center justify-center text-xs text-neutral-600">Loading…</div>
return <div className="flex h-48 items-center justify-center text-xs text-text-faint">Loading…</div>
}
return <PanelChart series={series} chartType={panel.chart_type} />
}
@@ -168,43 +168,43 @@ export function Dashboards({ range }: { range: TimeRange | null }) {
if (!activeProfile) {
return (
<div className="border-b border-neutral-800 p-3 text-xs text-neutral-600">
<div className="border-b border-border p-3 text-xs text-text-faint">
Dashboards — activate a profile (see the settings menu) to create and save dashboards.
</div>
)
}
return (
<div className="border-b border-neutral-800 p-3 text-sm">
<div className="mb-2 text-xs text-neutral-500">Dashboards — profile "{activeProfile}"</div>
<div className="border-b border-border p-3 text-sm">
<div className="mb-2 text-xs text-text-subtle">Dashboards — profile "{activeProfile}"</div>
{error && (
<div className="mb-2 rounded border border-red-900 bg-red-950/50 px-2 py-1 text-xs text-red-400">{error}</div>
<div className="mb-2 rounded border border-danger-border bg-danger-bg/50 px-2 py-1 text-xs text-danger-text">{error}</div>
)}
<div className="flex gap-4">
<div className="w-56 shrink-0 space-y-3">
<form onSubmit={handleCreateDashboard} className="flex gap-1">
<input
className="w-full min-w-0 flex-1 rounded border border-neutral-700 bg-neutral-900 px-2 py-1 text-xs text-neutral-100 placeholder:text-neutral-500 focus:border-neutral-500 focus:outline-none"
className="w-full min-w-0 flex-1 rounded border border-border-soft bg-surface-1 px-2 py-1 text-xs text-text placeholder:text-text-subtle focus:border-border-strong focus:outline-none"
value={newDashboardName}
onChange={(e) => setNewDashboardName(e.target.value)}
placeholder="New dashboard name"
/>
<button
type="submit"
className="rounded border border-neutral-700 px-2 py-1 text-xs text-neutral-300 hover:bg-neutral-800"
className="rounded border border-border-soft px-2 py-1 text-xs text-text-secondary hover:bg-surface-2"
>
+ Add
</button>
</form>
<div className="space-y-1">
{dashboards.length === 0 && <div className="text-xs text-neutral-600">No dashboards saved yet.</div>}
{dashboards.length === 0 && <div className="text-xs text-text-faint">No dashboards saved yet.</div>}
{dashboards.map((d) => (
<div
key={d.id}
className={`flex items-center justify-between rounded border px-2 py-1 text-xs ${
selectedId === d.id
? 'border-sky-500 bg-sky-500/10 text-sky-300'
: 'border-neutral-700 text-neutral-300 hover:bg-neutral-800'
? 'border-accent bg-accent/10 text-accent-text'
: 'border-border-soft text-text-secondary hover:bg-surface-2'
}`}
>
<button type="button" className="min-w-0 flex-1 truncate text-left" onClick={() => setSelectedId(d.id)}>
@@ -213,7 +213,7 @@ export function Dashboards({ range }: { range: TimeRange | null }) {
<button
type="button"
onClick={() => handleDeleteDashboard(d.id)}
className="ml-1 shrink-0 text-neutral-500 hover:text-red-400"
className="ml-1 shrink-0 text-text-subtle hover:text-danger-text"
title="Delete dashboard"
>
×
@@ -225,12 +225,12 @@ export function Dashboards({ range }: { range: TimeRange | null }) {
<div className="min-w-0 flex-1">
{!draft ? (
<div className="text-xs text-neutral-600">Select or create a dashboard to edit its panels.</div>
<div className="text-xs text-text-faint">Select or create a dashboard to edit its panels.</div>
) : (
<div className="space-y-3">
<div className="flex items-center justify-between">
<input
className="w-64 rounded border border-neutral-700 bg-neutral-900 px-2 py-1 text-sm text-neutral-100 focus:border-neutral-500 focus:outline-none"
className="w-64 rounded border border-border-soft bg-surface-1 px-2 py-1 text-sm text-text focus:border-border-strong focus:outline-none"
value={draft.name}
onChange={(e) => setDraft({ ...draft, name: e.target.value })}
/>
@@ -238,7 +238,7 @@ export function Dashboards({ range }: { range: TimeRange | null }) {
<button
type="button"
onClick={addPanel}
className="rounded border border-neutral-700 px-2 py-1 text-xs text-neutral-300 hover:bg-neutral-800"
className="rounded border border-border-soft px-2 py-1 text-xs text-text-secondary hover:bg-surface-2"
>
+ Add panel
</button>
@@ -246,7 +246,7 @@ export function Dashboards({ range }: { range: TimeRange | null }) {
type="button"
onClick={handleSaveDraft}
disabled={saving}
className="rounded border border-sky-700 bg-sky-500/10 px-2 py-1 text-xs text-sky-300 hover:bg-sky-500/20 disabled:opacity-50"
className="rounded border border-accent-soft bg-accent/10 px-2 py-1 text-xs text-accent-text hover:bg-accent/20 disabled:opacity-50"
>
{saving ? 'Saving…' : 'Save dashboard'}
</button>
@@ -254,27 +254,27 @@ export function Dashboards({ range }: { range: TimeRange | null }) {
</div>
{draft.panels.length === 0 && (
<div className="text-xs text-neutral-600">No panels yet — add one above.</div>
<div className="text-xs text-text-faint">No panels yet — add one above.</div>
)}
<div className="grid grid-cols-1 gap-3 lg:grid-cols-2">
{draft.panels.map((panel) => (
<div key={panel.id} className="rounded border border-neutral-800 p-2">
<div key={panel.id} className="rounded border border-border p-2">
<div className="mb-2 flex items-center gap-1">
<input
className="w-28 min-w-0 flex-1 rounded border border-neutral-700 bg-neutral-900 px-1.5 py-1 text-xs text-neutral-100 placeholder:text-neutral-500 focus:border-neutral-500 focus:outline-none"
className="w-28 min-w-0 flex-1 rounded border border-border-soft bg-surface-1 px-1.5 py-1 text-xs text-text placeholder:text-text-subtle focus:border-border-strong focus:outline-none"
value={panel.title}
onChange={(e) => updatePanel(panel.id, { title: e.target.value })}
placeholder="Panel title"
/>
<input
className="w-40 min-w-0 flex-[2] rounded border border-neutral-700 bg-neutral-900 px-1.5 py-1 font-mono text-xs text-neutral-100 placeholder:text-neutral-500 focus:border-neutral-500 focus:outline-none"
className="w-40 min-w-0 flex-[2] rounded border border-border-soft bg-surface-1 px-1.5 py-1 font-mono text-xs text-text placeholder:text-text-subtle focus:border-border-strong focus:outline-none"
value={panel.promql}
onChange={(e) => updatePanel(panel.id, { promql: e.target.value })}
placeholder={String.raw`requests{path="/a"}`}
/>
<select
className="rounded border border-neutral-700 bg-neutral-900 px-1 py-1 text-xs text-neutral-100 focus:border-neutral-500 focus:outline-none"
className="rounded border border-border-soft bg-surface-1 px-1 py-1 text-xs text-text focus:border-border-strong focus:outline-none"
value={panel.chart_type}
onChange={(e) => updatePanel(panel.id, { chart_type: e.target.value as ChartType })}
>
@@ -287,12 +287,12 @@ export function Dashboards({ range }: { range: TimeRange | null }) {
<button
type="button"
onClick={() => removePanel(panel.id)}
className="rounded border border-neutral-700 px-1.5 py-1 text-xs text-neutral-400 hover:bg-neutral-800"
className="rounded border border-border-soft px-1.5 py-1 text-xs text-text-muted hover:bg-surface-2"
>
×
</button>
</div>
{panel.title && <div className="mb-1 text-xs text-neutral-500">{panel.title}</div>}
{panel.title && <div className="mb-1 text-xs text-text-subtle">{panel.title}</div>}
<PanelPreview panel={panel} range={range} />
</div>
))}