@zmzai/theme 0.2.6 → 0.2.8
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zmzai/theme",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "zmzai 全品牌设计系统 — Radix UI + framer-motion + Tailwind v4 + MiSans",
|
|
@@ -95,5 +95,6 @@
|
|
|
95
95
|
"@radix-ui/react-tooltip": "^1.1.0",
|
|
96
96
|
"class-variance-authority": "^0.7.0",
|
|
97
97
|
"framer-motion": "^11.0.0"
|
|
98
|
-
}
|
|
98
|
+
},
|
|
99
|
+
"packageManager": "pnpm@10.34.5+sha512.a4ee05f2f73658255bd6a89859c065a45c28a57daefae2c893a168ee2b73168c37b91e83e57ea67654ad03f03031746430e8bce38e362e042605fb8abc80192e"
|
|
99
100
|
}
|
|
Binary file
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 规范图标集 — 16px 网格、1.5px 描边、currentColor、圆角端。
|
|
5
|
+
* 替代 Unicode 字符(+、✓、→)实现的按钮/状态图标。
|
|
6
|
+
* 命名 kebab-case;语义含义命名(grid 四宫格=目录、key=Token…)。
|
|
7
|
+
*/
|
|
8
|
+
const paths: Record<string, { d: string; fill?: boolean }> = {
|
|
9
|
+
// === 基础操作 ===
|
|
10
|
+
plus: { d: "M8 3.5v9M3.5 8h9" },
|
|
11
|
+
stop: { d: "M4.5 4.5h7v7h-7z", fill: true },
|
|
12
|
+
"new-session": { d: "M4 3.5h8a.5.5 0 0 1 .5.5v8a.5.5 0 0 1-.5.5H4a.5.5 0 0 1-.5-.5V4A.5.5 0 0 1 4 3.5zM8 6v4M6 8h4" },
|
|
13
|
+
check: { d: "M3.5 8.5l3 3 6-7" },
|
|
14
|
+
cross: { d: "M4.5 4.5l7 7M11.5 4.5l-7 7" },
|
|
15
|
+
download: { d: "M8 3v7M5 7.5L8 10.5 11 7.5M4 12.5h8" },
|
|
16
|
+
"arrow-down": { d: "M8 3.5v8M5 8.5L8 11.5 11 8.5" },
|
|
17
|
+
"arrow-right": { d: "M3 8h9.5M8.5 4.5L12 8l-3.5 3.5" },
|
|
18
|
+
"chevron-right": { d: "M6 4l4 4-4 4" },
|
|
19
|
+
"chevron-down": { d: "M4 6l4 4 4-4" },
|
|
20
|
+
refresh: { d: "M13 8a5 5 0 1 1-1.5-3.6M13 3.5v2.8h-2.8" },
|
|
21
|
+
retry: { d: "M13 8a5 5 0 1 1-1.5-3.6M13 3.5v2.8h-2.8" },
|
|
22
|
+
logout: { d: "M6 4.5h7a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-.5.5H6M8 8h4.5M10.5 6l2 2-2 2" },
|
|
23
|
+
edit: { d: "M8.8 4.2l3 3L6.5 12.5H3.5v-3zM8 5.5l2.5 2.5" },
|
|
24
|
+
trash: { d: "M4 4.5h8M6.5 4.5V3.5a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v1M5 4.5l.5 8a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5l.5-8M6.8 7v3.5M9.2 7v3.5" },
|
|
25
|
+
settings: { d: "M8 5.8a2.2 2.2 0 1 1 0 4.4 2.2 2.2 0 0 1 0-4.4zM8 2.5v1.6M8 11.9v1.6M2.5 8h1.6M11.9 8h1.6M4 4l1.1 1.1M10.9 10.9L12 12M12 4l-1.1 1.1M5.1 10.9L4 12" },
|
|
26
|
+
copy: { d: "M5.5 5.5h7.5v8H5.5zM3.5 3.5h7.5" },
|
|
27
|
+
external: { d: "M4 12V4h4M4 12L12 4M8 3.5h4.5V8" },
|
|
28
|
+
|
|
29
|
+
// === 导航/语义 ===
|
|
30
|
+
home: { d: "M2.5 7.5L8 3l5.5 4.5M4 6.5V13.5h8V6.5" },
|
|
31
|
+
grid: { d: "M3.5 3.5h3.5v3.5H3.5zM9 3.5h3.5v3.5H9zM3.5 9h3.5v3.5H3.5zM9 9h3.5v3.5H9z" },
|
|
32
|
+
key: { d: "M11 3.5a3.5 3.5 0 1 1-2 6.3L5.5 13.3 4 11.8l1.4-1.4L4 8.9 5 8l2.2 2.2A3.5 3.5 0 0 1 11 3.5zM11.8 6.2v.01" },
|
|
33
|
+
book: { d: "M4 3h8v10.5H5.8A1.8 1.8 0 0 0 4 15.3zM6.5 6.5h3" },
|
|
34
|
+
wallet: { d: "M2.5 5.5h11v7h-11zM2.5 5.5L10.5 3.2V5.5M10.5 9.5h.01" },
|
|
35
|
+
activity: { d: "M2 8h3l2-4 3 8 2-4h2" },
|
|
36
|
+
receipt: { d: "M4 3.5h8v9l-1.5-1-1 1-1.5-1-1 1-1.5-1-1 1zM6.5 6.5h3M6.5 8.5h3" },
|
|
37
|
+
link: { d: "M6.2 9.8l3.6-3.6M5 11.5l-1 1a2.4 2.4 0 0 1 3.4-3.4l1.4 1.4M11 4.5l1-1a2.4 2.4 0 0 1 3.4 3.4l-1.4 1.4" },
|
|
38
|
+
users: { d: "M5.5 6.5a1.8 1.8 0 1 0 0-3.6 1.8 1.8 0 0 0 0 3.6zM2.5 12.5c.5-2 1.8-3 3-3s2.5 1 3 3M10.5 4.2a1.8 1.8 0 1 1 0 3.6M10 9.8c1.7.2 3 1.3 3.5 2.7" },
|
|
39
|
+
sliders: { d: "M3 5h4.5M10.5 5H13M3 11h2M8 11h5M7.5 3v4M5 9v4" },
|
|
40
|
+
coins: { d: "M8 3.5c2.5 0 4.5.7 4.5 1.5s-2 1.5-4.5 1.5S3.5 5.8 3.5 5 5.5 3.5 8 3.5zM3.5 8c0 .8 2 1.5 4.5 1.5s4.5-.7 4.5-1.5M3.5 5v6c0 .8 2 1.5 4.5 1.5s4.5-.7 4.5-1.5V5" },
|
|
41
|
+
alert: { d: "M8 3l5.5 9.5h-11zM8 7v2.5M8 11.4v.01" },
|
|
42
|
+
"trend-up": { d: "M2.5 11.5l4-4 2.5 2.5L13 5.5M10 5.5h3v3" },
|
|
43
|
+
"check-circle": { d: "M8 2.8a5.2 5.2 0 1 1 0 10.4A5.2 5.2 0 0 1 8 2.8zM5.4 8.2l2 2 3.2-4" },
|
|
44
|
+
gauge: { d: "M13.5 8a5.5 5.5 0 1 1-11 0M8 8l2.4-3.2" },
|
|
45
|
+
bolt: { d: "M9 2.5L4 9h3.5L7 13.5 12 7H8.5z" },
|
|
46
|
+
shield: { d: "M8 2.5l5 2v4c0 3-2 5-5 6-3-1-5-3-5-6v-4zM6 8.5l1.5 1.5L10 7.5" },
|
|
47
|
+
sparkle: { d: "M8 2.5l1.3 4.2L13.5 8l-4.2 1.3L8 13.5l-1.3-4.2L2.5 8l4.2-1.3z" },
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export type IconName = keyof typeof paths;
|
|
51
|
+
|
|
52
|
+
export function Icon({ name, size = 14, className = "" }: { name: IconName; size?: number; className?: string }) {
|
|
53
|
+
const icon = paths[name];
|
|
54
|
+
if (!icon) return null;
|
|
55
|
+
return (
|
|
56
|
+
<svg
|
|
57
|
+
width={size}
|
|
58
|
+
height={size}
|
|
59
|
+
viewBox="0 0 16 16"
|
|
60
|
+
className={className}
|
|
61
|
+
aria-hidden="true"
|
|
62
|
+
fill={icon.fill ? "currentColor" : "none"}
|
|
63
|
+
stroke={icon.fill ? "none" : "currentColor"}
|
|
64
|
+
strokeWidth={1.5}
|
|
65
|
+
strokeLinecap="round"
|
|
66
|
+
strokeLinejoin="round"
|
|
67
|
+
>
|
|
68
|
+
<path d={icon.d} />
|
|
69
|
+
</svg>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Icon";
|
package/src/components/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./textarea";
|
|
|
7
7
|
export * from "./card";
|
|
8
8
|
export * from "./badge";
|
|
9
9
|
export * from "./avatar";
|
|
10
|
+
export * from "./icon";
|
|
10
11
|
|
|
11
12
|
// === Radix-based ===
|
|
12
13
|
export * from "./tooltip";
|
|
@@ -27,6 +28,7 @@ export * from "./stateful-button";
|
|
|
27
28
|
|
|
28
29
|
// === Layout & Structure ===
|
|
29
30
|
export * from "./floating-navbar";
|
|
31
|
+
export * from "./navbar";
|
|
30
32
|
export * from "./aceternity-sidebar";
|
|
31
33
|
export * from "./bento-grid";
|
|
32
34
|
export * from "./expandable-card";
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { type ReactNode } from "react";
|
|
4
|
+
import { cn } from "../../utils/cn";
|
|
5
|
+
import { Logo } from "../../brand/logo";
|
|
6
|
+
import { Wordmark } from "../../brand/wordmark";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* navItemClass — 导航项统一样式(全域导航一致)。
|
|
10
|
+
*
|
|
11
|
+
* active 时深墨 pill 高亮(bg-ink text-white),其余 hover 浮现。
|
|
12
|
+
* 链接本身由调用方渲染(Next.js 用 next/link,保持 SPA 导航),
|
|
13
|
+
* 只要都套这个 className,任何站点的导航观感就完全一致。
|
|
14
|
+
*/
|
|
15
|
+
export function navItemClass(active: boolean): string {
|
|
16
|
+
return cn(
|
|
17
|
+
"inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-sm font-medium transition-colors",
|
|
18
|
+
active
|
|
19
|
+
? "bg-ink text-white"
|
|
20
|
+
: "text-ink-2 hover:bg-surface-2 hover:text-ink"
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface NavbarProps {
|
|
25
|
+
/** Wordmark 后缀,如 "agent" / "relay"(品牌区自动 Logo + Wordmark) */
|
|
26
|
+
sublabel?: string;
|
|
27
|
+
/** 品牌区自定义(默认 Logo + Wordmark);传了则忽略 sublabel */
|
|
28
|
+
brand?: ReactNode;
|
|
29
|
+
/** 中间导航区(建议用 next/link 包 navItemClass(active)) */
|
|
30
|
+
children?: ReactNode;
|
|
31
|
+
/** 右侧操作区(用户信息 / 退出 / 入口按钮等) */
|
|
32
|
+
actions?: ReactNode;
|
|
33
|
+
/** 品牌区右侧的附属徽章(如域名 a.zmzai.cloud) */
|
|
34
|
+
badge?: ReactNode;
|
|
35
|
+
className?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Navbar — 全域统一顶栏。
|
|
40
|
+
*
|
|
41
|
+
* 左:品牌区(Logo + Wordmark);中:导航;右:操作区。
|
|
42
|
+
* 固定高度 3.5rem,paper 底色 + 模糊,底部细线。
|
|
43
|
+
* 各站(agent / relay / auth / hub)都消费这一个组件,保证导航一致。
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* <Navbar sublabel="agent" badge={<span>a.zmzai.cloud</span>} actions={<LogoutButton />}>
|
|
47
|
+
* <Link href="/fw" className={navItemClass(pathname === "/fw")}>新任务</Link>
|
|
48
|
+
* <Link href="/audit" className={navItemClass(pathname === "/audit")}>运行审计</Link>
|
|
49
|
+
* </Navbar>
|
|
50
|
+
*/
|
|
51
|
+
export function Navbar({ sublabel, brand, children, actions, badge, className }: NavbarProps) {
|
|
52
|
+
return (
|
|
53
|
+
<header
|
|
54
|
+
className={cn(
|
|
55
|
+
"sticky top-0 z-40 flex h-14 items-center justify-between gap-4 border-b border-line bg-paper/80 px-5 backdrop-blur-md",
|
|
56
|
+
className
|
|
57
|
+
)}
|
|
58
|
+
>
|
|
59
|
+
<div className="flex min-w-0 items-center gap-2.5">
|
|
60
|
+
{brand ?? (
|
|
61
|
+
<span className="inline-flex items-center gap-2">
|
|
62
|
+
<Logo size={22} />
|
|
63
|
+
<Wordmark size={16} sublabel={sublabel} />
|
|
64
|
+
</span>
|
|
65
|
+
)}
|
|
66
|
+
{badge}
|
|
67
|
+
</div>
|
|
68
|
+
{children ? (
|
|
69
|
+
<nav className="flex min-w-0 items-center gap-1 overflow-x-auto" aria-label="主导航">
|
|
70
|
+
{children}
|
|
71
|
+
</nav>
|
|
72
|
+
) : null}
|
|
73
|
+
{actions ? <div className="flex shrink-0 items-center gap-2.5">{actions}</div> : null}
|
|
74
|
+
</header>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Navbar";
|