@zmzai/theme 0.9.2 → 0.9.4

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.9.2",
3
+ "version": "0.9.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "zmzai 全品牌设计系统 — Radix UI + framer-motion + Tailwind v4 + MiSans",
@@ -70,7 +70,18 @@ const paths: Record<string, { d: string; fill?: boolean }> = {
70
70
 
71
71
  export type IconName = keyof typeof paths;
72
72
 
73
- export function Icon({ name, size = 14, className = "" }: { name: IconName; size?: number; className?: string }) {
73
+ export function Icon({
74
+ name,
75
+ size = 14,
76
+ className = "",
77
+ strokeWidth = 1.5,
78
+ }: {
79
+ name: IconName;
80
+ size?: number;
81
+ className?: string;
82
+ /** 描边宽度。viewBox 恒为 16,放大到 20px+ 时用 1.25 避免视觉过重(默认 1.5 不变) */
83
+ strokeWidth?: number;
84
+ }) {
74
85
  const icon = paths[name];
75
86
  if (!icon) return null;
76
87
  return (
@@ -82,7 +93,7 @@ export function Icon({ name, size = 14, className = "" }: { name: IconName; size
82
93
  aria-hidden="true"
83
94
  fill={icon.fill ? "currentColor" : "none"}
84
95
  stroke={icon.fill ? "none" : "currentColor"}
85
- strokeWidth={1.5}
96
+ strokeWidth={strokeWidth}
86
97
  strokeLinecap="round"
87
98
  strokeLinejoin="round"
88
99
  >
@@ -1,7 +1,8 @@
1
- // @zmzai/theme — Components barrel (54 components)
1
+ // @zmzai/theme — Components barrel (55 components)
2
2
 
3
3
  // === Basic ===
4
4
  export * from "./app-shell";
5
+ export * from "./page-header";
5
6
  export * from "./button";
6
7
  export * from "./input";
7
8
  export * from "./textarea";
@@ -0,0 +1,95 @@
1
+ "use client";
2
+
3
+ /**
4
+ * PageHeader — 页面标题统一组件
5
+ *
6
+ * v0.9.4 引入。此前 agent / relay 两站共 38 个页面各自手写 h1:
7
+ * 标题旁 0 图标、字号分 4~5 档(text-sm / text-lg / text-2xl / text-3xl /
8
+ * text-4xl / CSS clamp)、间距与颜色 token 各有偏差(text-muted-foreground
9
+ * 等旧变量混用)、部分页面缺 text-ink。
10
+ *
11
+ * 纪律:
12
+ * · 只有两个 variant —— hero(落地页)与 page(其余全部)
13
+ * · page 一律 text-2xl + 内联图标,不再区分公开页与控制台
14
+ * · 图标取 currentColor,不引入新色;hero 徽章用 accent 载体(墨底白图)
15
+ * · 描述统一 text-sm text-ink-2 —— ink-3 只有 3.69:1,副文案不用它
16
+ */
17
+
18
+ import type { ReactNode } from "react";
19
+ import { Icon, type IconName } from "../icon/Icon";
20
+
21
+ export interface PageHeaderProps {
22
+ /** 眉标:页面所属分区,如「控制台」「长期上下文」。hero 变体下作为统计/kicker 行。 */
23
+ eyebrow?: ReactNode;
24
+ /** 页面标题,渲染为 h1 */
25
+ title: ReactNode;
26
+ /** 标题左侧内联图标(page 变体)或墨底徽章内容(hero 变体) */
27
+ icon?: IconName;
28
+ /** 标题下方描述 */
29
+ description?: ReactNode;
30
+ /** 右侧操作区(按钮、筛选器等) */
31
+ actions?: ReactNode;
32
+ /** hero = 落地页(44px 墨底徽章 + text-4xl);page = 其余全部(内联图标 + text-2xl) */
33
+ variant?: "page" | "hero";
34
+ /** 追加到根元素 */
35
+ className?: string;
36
+ /** 追加到 h1(详情页标题过长时用 truncate) */
37
+ titleClassName?: string;
38
+ }
39
+
40
+ export function PageHeader({
41
+ eyebrow,
42
+ title,
43
+ icon,
44
+ description,
45
+ actions,
46
+ variant = "page",
47
+ className = "",
48
+ titleClassName = "",
49
+ }: PageHeaderProps) {
50
+ if (variant === "hero") {
51
+ return (
52
+ <header className={`flex flex-col ${className}`}>
53
+ {icon ? (
54
+ <span className="mb-4 grid size-11 shrink-0 place-items-center rounded-lg bg-accent text-accent-ink">
55
+ <Icon name={icon} size={22} strokeWidth={1.25} />
56
+ </span>
57
+ ) : null}
58
+ {eyebrow ? (
59
+ <small className="mb-2 block font-mono text-xs tracking-wide text-ink-3">{eyebrow}</small>
60
+ ) : null}
61
+ <h1
62
+ className={`font-serif text-4xl font-bold leading-tight tracking-tight text-ink ${titleClassName}`}
63
+ >
64
+ {title}
65
+ </h1>
66
+ {description ? (
67
+ <p className="mt-4 max-w-2xl text-lg leading-8 text-ink-2">{description}</p>
68
+ ) : null}
69
+ {actions ? <div className="mt-7 flex flex-wrap items-center gap-4">{actions}</div> : null}
70
+ </header>
71
+ );
72
+ }
73
+
74
+ return (
75
+ <header className={`flex flex-wrap items-end justify-between gap-3 ${className}`}>
76
+ <div className="min-w-0">
77
+ {eyebrow ? (
78
+ <small className="mb-1 block text-xs font-semibold uppercase tracking-wide text-ink-3">
79
+ {eyebrow}
80
+ </small>
81
+ ) : null}
82
+ <div className="flex items-center gap-2">
83
+ {icon ? <Icon name={icon} size={20} className="shrink-0 text-ink" /> : null}
84
+ <h1
85
+ className={`font-serif text-2xl font-semibold tracking-tight text-ink ${titleClassName}`}
86
+ >
87
+ {title}
88
+ </h1>
89
+ </div>
90
+ {description ? <p className="mt-2 text-sm leading-6 text-ink-2">{description}</p> : null}
91
+ </div>
92
+ {actions ? <div className="flex flex-wrap items-center gap-2">{actions}</div> : null}
93
+ </header>
94
+ );
95
+ }
@@ -0,0 +1,2 @@
1
+ export { PageHeader } from "./PageHeader";
2
+ export type { PageHeaderProps } from "./PageHeader";
@@ -21,6 +21,8 @@
21
21
  * v0.9.0 暖纸底 + Serif display——去单调
22
22
  * v0.9.1 印色路标撤回,命名定全词(现行)
23
23
  * v0.9.2 品红点睛色阶(墨底荧光)——spot 四层 + ink,仅深色载体
24
+ * v0.9.3 底色纯白化——暖纸退役,卡片层次交给 surface 灰阶与边框
25
+ * v0.9.4 PageHeader 统一组件——内页 text-2xl 内联图标、落地页 44px 墨底徽章
24
26
  */
25
27
 
26
28
  @theme {
@@ -30,7 +32,7 @@
30
32
  v0.6 的 ink(30°) / ink-2(55°) / line(88°) / surface(90°) 四个色相
31
33
  混用,是"说不出哪里怪"的根源。
32
34
  ══════════════════════════════════════════════════════ */
33
- --color-bg: oklch(0.992 0.003 85); /* 页面底,暖纸(v0.9.0:色相 85 彩度 0.003,有温度无色相感) */
35
+ --color-bg: oklch(1 0 0); /* 页面底,纯白(v0.9.3 用户定案去暖纸黄;层次靠 surface 灰阶与边框) */
34
36
  --color-surface: oklch(0.985 0.001 265); /* 卡片 / 面板 */
35
37
  --color-surface-2: oklch(0.968 0.002 265); /* 嵌套 / 表头 */
36
38
  --color-surface-3: oklch(0.94 0.003 265); /* hover / 按下 */