diff --git a/ui/src/pages/_styleguide.tsx b/ui/src/pages/_styleguide.tsx index 53c36f35..730aba86 100644 --- a/ui/src/pages/_styleguide.tsx +++ b/ui/src/pages/_styleguide.tsx @@ -8,11 +8,26 @@ * safe to publish in PRs without enabling Privacy mode. */ import { useState } from 'react'; -import { Activity, Bot, Cloud, Cpu, Plus, RefreshCcw, ShieldCheck, Zap } from 'lucide-react'; +import { + Activity, + Bot, + Cloud, + Cpu, + Key, + Plus, + RefreshCcw, + RefreshCw, + ShieldCheck, + Sparkles, + Users, + Zap, +} from 'lucide-react'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; +import { ScrollArea } from '@/components/ui/scroll-area'; +import { cn } from '@/lib/utils'; import { PageShell, PageHeader, EmptyState, ErrorState } from '@/components/page-shell'; import { ConfigLayout, @@ -60,7 +75,25 @@ export function StyleguidePage() { return (
- + + + + + + + + + + @@ -153,7 +186,195 @@ function PrimitiveSection({ } // ----------------------------------------------------------------------------- -// PageHeader demo +// HeroBar demo (canonical: pages/home.tsx) +// +// One row packs logo + title + version + ≤4 inline stats. Optional dotted +// background pattern. Stats are clickable when they double as nav entry points. +// Use it for dashboard pages with a clear product identity and ≤4 hero numbers. +// ----------------------------------------------------------------------------- + +function DemoInlineStat({ + title, + value, + icon: Icon, + variant = 'default', +}: { + title: string; + value: string | number; + icon: typeof Activity; + variant?: 'default' | 'accent' | 'success' | 'warning'; +}) { + const styles = { + default: 'bg-muted text-muted-foreground', + accent: 'bg-accent/15 text-accent', + success: 'bg-emerald-600/15 text-emerald-700 dark:text-emerald-400', + warning: 'bg-amber-500/15 text-amber-700 dark:text-amber-400', + }[variant]; + const valueColor = { + default: 'text-foreground', + accent: 'text-accent', + success: 'text-emerald-700 dark:text-emerald-400', + warning: 'text-amber-700 dark:text-amber-400', + }[variant]; + + return ( + + ); +} + +function DemoHeroBar() { + return ( +
+
+
+
+
+
+
+
+ +
+
+
+

Demo Dashboard

+ + v1.0.0 + +
+

+ Single-row dense hero — logo + title + version + inline stats +

+
+
+
+ + + + +
+
+
+

+ Body content renders below — no separate KpiRow needed since stats are absorbed into the + hero strip. +

+
+ ); +} + +// ----------------------------------------------------------------------------- +// Rail-anchored identity demo (canonical: pages/cliproxy.tsx) +// +// Page identity (brand + page-level CTA + status) lives inside the left rail of +// a Config 3-pane layout. Zero top chrome. The body archetype gets the full +// vertical viewport. Use for multi-entity Config pages where the rail naturally +// carries the page name. +// ----------------------------------------------------------------------------- + +function DemoRailAnchored() { + const [selectedId, setSelectedId] = useState('provider-a'); + + const railHeader = ( +
+ {/* Brand strip — replaces the global PageHeader */} +
+
+
+ +

Demo Brand

+
+ +
+

Page subtitle / description

+ +
+ + {/* Provider list */} + +
+
+ Providers +
+
+ {DEMO_PROVIDERS.map((p) => ( + + ))} +
+
+
+ + {/* Footer status */} +
+
+ 4 providers + + 1 connected + +
+
+
+ ); + + return ( +
+ {/* NOTE: NO PageHeader at the top. Identity is inside the rail. */} + Provider A

} + footer={} + > + + + + + } + json={} + /> +
+ ); +} + +// ----------------------------------------------------------------------------- +// PageHeader demo (canonical: pages/health.tsx) +// +// Traditional title row with description and trailing actions. Use when the +// page does NOT fit either canonical hero AND the description carries +// non-redundant context (last refresh, page hierarchy, filter state, version). // ----------------------------------------------------------------------------- function DemoPageHeader() {