feat(ui): integrate official shadcn/ui + Radix primitives + cmdk + cva in src/components/ui

Browse Source
This commit is contained in:
Yin Kou committed 2026-11-07 00:40:25 +08:00
1 parent cbc47336d6
commit 07d2050c5f
21 files changed
+1606 -471

No files matched your search

+42 -67
View File
@@ -2,6 +2,8 @@ import React from 'react';
import { BookOpen, LayoutGrid, Moon, Search, Sun, Terminal } from 'lucide-react'; import { BookOpen, LayoutGrid, Moon, Search, Sun, Terminal } from 'lucide-react';
import { usePortalStore } from '../store/usePortalStore'; import { usePortalStore } from '../store/usePortalStore';
import type { RouteModeId } from '../types/telemetry'; import type { RouteModeId } from '../types/telemetry';
import { Button } from './ui/button';
import { Tabs, TabsList, TabsTrigger } from './ui/tabs';
const MODES: Array<{ id: RouteModeId; label: string }> = [ const MODES: Array<{ id: RouteModeId; label: string }> = [
{ id: 'auto', label: '智能路由' }, { id: 'auto', label: '智能路由' },
@@ -29,15 +31,15 @@ export const TopRibbon: React.FC = () => {
<> <>
{/* ===================================================================== {/* =====================================================================
Tier 1: Standard AppShell Global Top Navbar (h-14, NEVER wraps!) Tier 1: Standard AppShell Global Top Navbar (h-14, NEVER wraps!)
Left: Brand + View Tabs (中控台 / Storybook) Left: Brand + Radix Tabs (中控台 / Storybook)
Far Right (Red Box): Search (Cmd+K) + AGY Terminal + Theme Switcher Far Right: Search (Cmd+K) + AGY Terminal + Theme Switcher
===================================================================== */} ===================================================================== */}
<header <header
className="border-b hl-border sticky top-0 z-30 backdrop-blur-md" className="border-b hl-border sticky top-0 z-30 backdrop-blur-md"
style={{ backgroundColor: 'color-mix(in srgb, var(--bg-card) 88%, transparent)' }} style={{ backgroundColor: 'color-mix(in srgb, var(--bg-card) 88%, transparent)' }}
> >
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-14 flex items-center justify-between gap-4"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-14 flex items-center justify-between gap-4">
{/* Left Group: Brand Logo + Navigation Tabs */} {/* Left Group: Brand Logo + Official Radix Navigation Tabs */}
<div className="flex items-center gap-4 shrink-0"> <div className="flex items-center gap-4 shrink-0">
<div <div
onClick={() => setViewMode('dashboard')} onClick={() => setViewMode('dashboard')}
@@ -58,47 +60,30 @@ export const TopRibbon: React.FC = () => {
<div className="h-4 w-[1px] hl-muted" /> <div className="h-4 w-[1px] hl-muted" />
{/* View Switcher Tabs: Dashboard vs Storybook */} {/* View Switcher Tabs via @radix-ui/react-tabs */}
<nav className="flex items-center gap-1 text-xs"> <Tabs
<button value={viewMode}
onClick={() => setViewMode('dashboard')} onValueChange={(v) => setViewMode(v as 'dashboard' | 'storybook')}
className="px-2.5 py-1.5 rounded-md font-medium flex items-center gap-1.5 transition-all cursor-pointer" >
style={ <TabsList>
viewMode === 'dashboard' <TabsTrigger value="dashboard">
? { <LayoutGrid className="w-3.5 h-3.5" />
backgroundColor: 'var(--bg-muted)', <span>中控台</span>
color: 'var(--text-main)', </TabsTrigger>
} <TabsTrigger value="storybook">
: { color: 'var(--text-muted)' } <BookOpen className="w-3.5 h-3.5" />
} <span>Storybook 设计规范</span>
> </TabsTrigger>
<LayoutGrid className="w-3.5 h-3.5" /> </TabsList>
<span>中控台</span> </Tabs>
</button>
<button
onClick={() => setViewMode('storybook')}
className="px-2.5 py-1.5 rounded-md font-medium flex items-center gap-1.5 transition-all cursor-pointer"
style={
viewMode === 'storybook'
? {
backgroundColor: 'var(--bg-muted)',
color: 'var(--text-main)',
}
: { color: 'var(--text-muted)' }
}
>
<BookOpen className="w-3.5 h-3.5" />
<span>Storybook 设计规范</span>
</button>
</nav>
</div> </div>
{/* Far Right Group: Pinned to Right Edge (Search + AGY + Theme Switcher) */} {/* Far Right Group: Pinned to Right Edge (Search + AGY + Theme Switcher) */}
<div className="flex items-center gap-2.5 shrink-0 ml-auto"> <div className="flex items-center gap-2.5 shrink-0 ml-auto">
<button <Button
variant="outline"
onClick={() => setShowCmdPalette(true)} onClick={() => setShowCmdPalette(true)}
className="hl-btn-outline px-3 py-1.5 text-xs flex items-center gap-3 cursor-pointer" className="gap-3"
title="按 Cmd+K 唤起全局命令面板" title="按 Cmd+K 唤起全局命令面板"
> >
<span className="flex items-center gap-1.5" style={{ color: 'var(--text-muted)' }}> <span className="flex items-center gap-1.5" style={{ color: 'var(--text-muted)' }}>
@@ -111,15 +96,12 @@ export const TopRibbon: React.FC = () => {
> >
⌘K ⌘K
</kbd> </kbd>
</button> </Button>
<button <Button onClick={() => setShowAgyModal(true)}>
onClick={() => setShowAgyModal(true)}
className="hl-btn-primary px-3 py-1.5 text-xs flex items-center gap-1.5 cursor-pointer"
>
<Terminal className="w-3.5 h-3.5" /> <Terminal className="w-3.5 h-3.5" />
<span>AGY 终端</span> <span>AGY 终端</span>
</button> </Button>
{/* Top-Right Theme Toggle (Pinned at Far Right Corner!) */} {/* Top-Right Theme Toggle (Pinned at Far Right Corner!) */}
<div className="flex items-center p-0.5 rounded-lg hl-muted border hl-border text-xs"> <div className="flex items-center p-0.5 rounded-lg hl-muted border hl-border text-xs">
@@ -163,7 +145,7 @@ export const TopRibbon: React.FC = () => {
{/* ===================================================================== {/* =====================================================================
Tier 2: Subheader Telemetry & Route Mode Bar (Aligned with Grid) Tier 2: Subheader Telemetry & Route Mode Bar (Aligned with Grid)
Left: 4 Hardware & Network Gauges Left: 4 Hardware & Network Gauges
Right: Route Mode Segmented Switcher (智能路由 / 443 / 10443 / LAN) Right: Route Mode Segmented Switcher via @radix-ui/react-tabs
===================================================================== */} ===================================================================== */}
{viewMode === 'dashboard' && ( {viewMode === 'dashboard' && (
<div className="border-b hl-border" style={{ backgroundColor: 'var(--bg-card)' }}> <div className="border-b hl-border" style={{ backgroundColor: 'var(--bg-card)' }}>
@@ -217,27 +199,20 @@ export const TopRibbon: React.FC = () => {
</div> </div>
</div> </div>
{/* Right: Route Mode Switcher (Pinned to Right Edge of Subheader) */} {/* Right: Route Mode Switcher via @radix-ui/react-tabs */}
<div className="flex items-center p-0.5 rounded-lg hl-muted border hl-border text-xs ml-auto"> <Tabs
{MODES.map((m) => ( value={routeMode}
<button onValueChange={(v) => setRouteMode(v as RouteModeId)}
key={m.id} className="ml-auto"
onClick={() => setRouteMode(m.id)} >
className="px-2.5 py-1 rounded-md font-medium transition-all cursor-pointer" <TabsList>
style={ {MODES.map((m) => (
routeMode === m.id <TabsTrigger key={m.id} value={m.id}>
? { {m.label}
backgroundColor: 'var(--bg-card)', </TabsTrigger>
color: 'var(--text-main)', ))}
boxShadow: '0 1px 2px rgba(0,0,0,0.08)', </TabsList>
} </Tabs>
: { color: 'var(--text-muted)' }
}
>
{m.label}
</button>
))}
</div>
</div> </div>
</div> </div>
)} )}