This commit is contained in:
sunzhongyi
2026-05-20 01:30:41 +08:00
parent f3e6b95be9
commit 7dded89537
44 changed files with 1166 additions and 3699 deletions
+159 -81
View File
@@ -2,142 +2,220 @@
# AI Agent Prompt: 生产级报纸组件库开发
## 任务目标
开发一个浏览器端生产级报纸布局组件库,参考 InDesign,组件少而精、职责明确、无冗余、无歧义,支持全局 24 列栅格、跨栏、视觉权重和主题系统,提供文档网站(内嵌 demo,无需 storybook)。
开发一个浏览器端生产级报纸布局组件库,参考 InDesign 与经典严肃风(NYT / The Times)排版传统,组件少而精、职责明确、无冗余、无歧义,支持全局 24 列栅格、跨栏、视觉权重和主题系统,提供文档网站(内嵌 demo,无需 storybook)。
视觉基调:经典严肃风(衬线为主、暖灰系、warm off-white 背景、双线分隔、首字下沉、栏间细线、真实多栏文字流)。
---
## 1. 项目 setup 与架构
- **Monorepo 管理**pnpm workspace / Turborepo
- **Monorepo 管理**pnpm workspace + Turborepo
- Packages:
1. `components` → Layout / Section / Article / Layer / Text / Media
2. `theme`全局主题变量、字体、颜色、间距、视觉权重映射
3. `docs` → 文档网站(shadcn stack + demo
4. `utils` → 栅格计算、跨栏逻辑、响应式辅助函数
1. `components` → Layout / Section / Article / Layer / Masthead / Rule / Headline / Subhead / Kicker / BodyText / Quote / Byline / Dateline / Caption / Image / Figure / Video / PullQuote
2. `theme`字体导入、CSS variables、视觉权重映射、Tailwind tokens、排版工具类
3. `docs` → 文档网站(Next.js + Tailwind + MDX
4. `utils` → 栅格校验(`validateSpan` / `clampSpan`)、`cx` 类名合并
- **目录结构示例**:
- **目录结构**:
```
/packages
/components
/Layout
/Section
/Article
/Layer
/Text
/Media
/theme
/docs
/utils
/components
/src
/layout (Layout / Section / Article / Layer / Masthead / Rule)
/text (Headline / Subhead / Kicker / BodyText / Quote / Byline / Dateline / Caption)
/media (Image / Figure / Video / PullQuote)
/theme
/src
fonts.css (Google Fonts: Cormorant Garamond / Source Serif 4 / Inter / UnifrakturMaguntia)
variables.css (CSS variables: 字体 / 暖灰系颜色 / 间距 / 分隔线 / 强调色)
typography.css (drop-cap / small-caps / paragraph-flow / OSF / column-rule 等工具类)
visual-weights.ts
tailwind.config.js
/docs
/utils
```
- **技术栈**:
- React 18+, TypeScript
- TailwindCSS + shadcn 文档 stack
- React 18+, TypeScript 5+
- TailwindCSS 3+ + 文档站基础 stack
- Vitest + React Testing Library
- 构建工具Vite + Rollup
- 构建:Vite + Rollupcomponents/theme/utils);Next.js 14+docs
---
## 2. 全局栅格系统
- `<Layout>` 顶层容器:
- maxWidth, padding, gutter, theme
- 栅格总列数 24
- snap-to-grid 支持
- Section 内对象 span ≤ Section.columns
- 响应式调整:小屏 1216 列
- `columns`(默认 24)、`maxWidth``padding``theme`'light' | 'dark'
- 通过 React Context 把 columns 下传给 `<Section>`
- `<Section>` 内部使用 `display: grid; grid-template-columns: repeat(N, 1fr); gap: var(--nui-gutter)`
- Section 内对象通过 `grid-column: span N` 跨栏,统一布局机制
- 响应式:通过 CSS media query / container query 调整(不再使用 JS 路径)
---
## 3. 核心布局组件
1. `<Section>`
- columns, breakable, padding/margin, priority
- 内部对象 span ≤ Section.columns
- `columns`(必填)、`gap``breakable``divider`'none' | 'top' | 'bottom' | 'both'
- 内部对象 span ≤ Section.columns,超过自动 clamp 并 console.warn
2. `<Article>`
- span, priority/weight, breakable
- 内含 Headline / Subhead / BodyText / Image / PullQuote
- `span``breakable`
- 跨栏统一通过 `grid-column: span N`
3. `<Layer>`
- position, top/left/right/bottom, zIndex
- 用于浮动广告、拉引、浮动图片
- `position`'absolute' | 'fixed' | 'sticky')、`top/left/right/bottom``zIndex`
4. `<Masthead>` 报头组件:
- `title``kicker``edition``date``price`
- `variant`'classic'(双线居中 + Cormorant Garamond)、'blackletter'UnifrakturMaguntia 哥特体)、'modern'(左对齐 + accent 色)
5. `<Rule>` 分隔线组件:
- `variant`'hairline' | 'double' | 'thick'
- `orientation`'horizontal' | 'vertical'
- `span`(横向时占多少列,默认 `1 / -1`
---
## 4. 内容组件
- 文本类:Headline / Subhead / BodyText / Quote / Byline / Caption
- 媒体类:Image / Figure / Video / PullQuote
- 属性:span(跨栏)、weightHigh/Medium/Low)、margin/padding
- 所有 span 基于 Section.columns
- 文本类:`<Headline>` / `<Subhead>` / `<Kicker>` / `<BodyText>` / `<Quote>` / `<Byline>` / `<Dateline>` / `<Caption>`
- 媒体类:`<Image>` / `<Figure>` / `<Video>` / `<PullQuote>`
- 通用属性:`weight``span`(跨栏,由 Section 的 grid-column 提供)、`className``style`
- `<BodyText>` 核心扩展:
- `columns?: 1 | 2 | 3 | 4` 启用 CSS multi-column 真实多栏文字流
- `dropCap?: boolean` 首字下沉
- 默认开启段间无空行 + 第二段起首行缩进 1em + old-style figures + hanging punctuation
- `<Quote>``variant: 'block' | 'inline'`block 用左缩进 1.5em(不使用左 border
- `<PullQuote>`:上下双 hairline + Display 字体;`spanAllColumns` 在多栏 BodyText 内自动跨所有栏
- `<Byline>` / `<Dateline>` / `<Kicker>`:使用真小帽(OpenType `font-variant-caps: small-caps`,非 `text-transform: uppercase`
---
## 5. 视觉权重映射表(24 列
## 5. 视觉权重映射表(修订版
| 组件 | 权重 | font-size | font-weight | line-height | color | span | margin/padding |
|---|---|---|---|---|---|---|---|
| Headline | High | 3648px | 700 | 1.1 | #111 | 68 | 0 0 1rem 0 |
| Headline | Medium | 2834px | 600 | 1.2 | #111 | 46 | 0 0 0.75rem 0 |
| Headline | Low | 2226px | 500 | 1.3 | #222 | 24 | 0 0 0.5rem 0 |
| Subhead | High | 2024px | 600 | 1.25 | #222 | 23 | 0 0 0.5rem 0 |
| Subhead | Medium | 1618px | 500 | 1.3 | #333 | 12 | 0 0 0.25rem 0 |
| BodyText | High | 16px | 400 | 1.5 | #333 | 1 | 0 0 1rem 0 |
| BodyText | Medium | 1415px | 400 | 1.5 | #444 | 1 | 0 0 0.75rem 0 |
| BodyText | Low | 1214px | 400 | 1.4 | #555 | 1 | 0 0 0.5rem 0 |
| Quote | High | 2024px | 500 | 1.4 | #222 | 2 | 0 0 0.75rem 0 |
| Quote | Medium | 1618px | 400 | 1.4 | #333 | 1 | 0 0 0.5rem 0 |
| Image Caption | Standard | 1214px | 400 | 1.3 | #555 | 1 | 0.25rem 0 |
| PullQuote | High | 2428px | 600 | 1.2 | #111 | 23 | 0 0 0.5rem 0 |
| PullQuote | Medium | 1820px | 500 | 1.25 | #222 | 12 | 0 0 0.25rem 0 |
| Byline | Standard | 1214px | 400 | 1.3 | #555 | 1 | 0 0 0.25rem 0 |
经典严肃风修订要点:
- 字号上限放开(Headline High 4872px,原 3648px 太小压不住头版)
- font-weight 普遍下调(High 700 → 600Medium 600 → 500),避免数码黑
- line-height 衬线上调(BodyText 1.551.6
- 颜色使用暖灰系 token`--nui-text-primary` `#1A1A1A` 而非 `#111`
- 颜色 / 字体均通过 CSS variable token,不硬编码 hex
- 新增 4 档:Masthead / Kicker / Dateline / Caption credit
| 组件 | 权重 | font-family | font-size | font-weight | line-height | letter-spacing | font-variant | color | span | margin |
|---|---|---|---|---|---|---|---|---|---|---|
| Masthead | Standard | `--font-family-masthead` | 5696px | 700 | 1.0 | 0.02em | lining-nums | `--nui-text-primary` | 24 | 0 |
| Headline | High | `--font-family-display` | 4872px | 600 | 1.05 | -0.01em | lining-nums + balance | `--nui-text-primary` | 816 | `0 0 1rem 0` |
| Headline | Medium | `--font-family-headline` | 3240px | 600 | 1.1 | -0.005em | lining-nums | `--nui-text-primary` | 610 | `0 0 0.75rem 0` |
| Headline | Low | `--font-family-headline` | 2226px | 500 | 1.2 | 0 | lining-nums | `--nui-text-body` | 46 | `0 0 0.5rem 0` |
| Subhead | High | `--font-family-headline` italic | 1822px | 500 | 1.3 | 0 | oldstyle-nums | `--nui-text-secondary` | 48 | `0 0 0.75rem 0` |
| Subhead | Medium | `--font-family-headline` italic | 1618px | 400 | 1.35 | 0 | oldstyle-nums | `--nui-text-secondary` | 24 | `0 0 0.5rem 0` |
| Kicker | Standard | `--font-family-meta` small-caps | 1213px | 600 | 1.2 | 0.08em | small-caps + lining | `--nui-accent-primary` | 14 | `0 0 0.25rem 0` |
| BodyText | High | `--font-family-body` | 1617px | 400 | 1.6 | 0 | oldstyle-nums | `--nui-text-body` | 1 | `0 0 0.75rem 0` |
| BodyText | Medium | `--font-family-body` | 15px | 400 | 1.55 | 0 | oldstyle-nums | `--nui-text-body` | 1 | `0 0 0.5rem 0` |
| BodyText | Low | `--font-family-body` | 1314px | 400 | 1.5 | 0 | oldstyle-nums | `--nui-text-secondary` | 1 | `0 0 0.5rem 0` |
| Quote (block) | High | `--font-family-body` | 1719px | 400 | 1.55 | 0 | oldstyle-nums | `--nui-text-quote` | 2 | `1rem 0 1rem 1.5em` |
| Quote (inline) | — | `--font-family-body` italic | inherit | 400 | inherit | 0 | inherit | inherit | — | 0 |
| PullQuote | High | `--font-family-display` | 2632px | 600 | 1.2 | -0.005em | lining-nums + balance | `--nui-text-primary` | 23 | `1.5rem 0` |
| PullQuote | Medium | `--font-family-display` | 2024px | 500 | 1.25 | 0 | lining-nums | `--nui-text-body` | 12 | `1rem 0` |
| Caption | Standard | `--font-family-body` italic | 13px | 400 | 1.4 | 0 | oldstyle-nums | `--nui-text-secondary` | 1 | `0.5rem 0 0 0` |
| Caption credit | — | `--font-family-meta` small-caps | 1112px | 500 | 1.4 | 0.06em | small-caps | `--nui-text-muted` | 1 | inline |
| Byline | Standard | `--font-family-meta` small-caps | 1213px | 500 | 1.3 | 0.06em | small-caps + lining | `--nui-text-secondary` | 1 | `0 0 0.25rem 0` |
| Dateline | Standard | `--font-family-meta` small-caps | 1213px | 600 | 1.3 | 0.08em | small-caps + lining | `--nui-text-primary` | 1 | inline |
---
## 6. 主题系统
- 全局新闻字体预设
- 颜色变量(黑/灰/强调色
- 间距变量(gutter, margin, padding
- 权重映射 Token
- Tailwind + CSS Variables 支持主题切换
### 6.1 字体(Google Fonts,免费可商用)
- `--font-family-masthead`Cormorant Garamond(报头主字
- `--font-family-blackletter`UnifrakturMaguntia(哥特报头 preset
- `--font-family-display` / `--font-family-headline` / `--font-family-body`Source Serif 4Optical Size 可变字体,覆盖头条到正文)
- `--font-family-meta`InterByline / Dateline / Kicker / Caption credit 用真小帽)
### 6.2 颜色(暖灰系,避开纯黑/纯白)
Light(默认):
- 页面背景:`--nui-bg-page #F7F4ED``--nui-bg-surface #FBF9F4`
- 文字:`--nui-text-primary #1A1A1A``--nui-text-body #22201C``--nui-text-secondary #4A4742``--nui-text-muted #6E6A63``--nui-text-quote #2E2A24`
- 分隔线:`--nui-rule-hairline #C9C2B2``--nui-rule-decorative #1A1A1A`
- 强调色:`--nui-accent-primary #7A1F1F`NYT 朱红)、`--nui-accent-ink-blue #1B2A4A`The Times 蓝)、`--nui-highlight #F2E9C8`(旧报纸黄)
Dark(暖深棕黑,非冷黑):
- 反向映射保持暖意,accent 色提亮 + 降饱和
### 6.3 间距 / 排版工具类
- 间距 token`--nui-gutter``--nui-space-{1,2,3,4,6,8}`
- 排版工具类(typography.css):
- `.nui-drop-cap` 首字下沉(`::first-letter` + `float: left`
- `.nui-small-caps` 真小帽(OpenType `smcp/c2sc`
- `.nui-paragraph-flow` 段间无空行 + `p + p` 首行缩进 1em
- `.nui-osf` old-style figures、`.nui-tnum` tabular figures
- `.nui-hanging-punctuation` 悬挂引号
- `.nui-column-rule` 栏间 hairline
- `.nui-avoid-break` `break-inside: avoid`
- `.nui-span-all-columns` `column-span: all`(多栏内跨栏)
- `.nui-masthead-rule-top` / `.nui-masthead-rule-bottom` 报头双线
### 6.4 主题切换
通过 `[data-theme="dark"]` 覆盖 CSS variables,组件代码无需感知主题;提供手动切换按钮。
---
## 7. 布局规则
- Section 内对象 span ≤ Section.columns
- 高权重对象可跨多栏
- Layer 浮动/绝对定位
- breakable 控制分页断开
- 响应式:小屏 1216 列
- Section 内对象 span ≤ Section.columns,超过自动 clamp + console.warn(不抛异常崩溃)
- 高权重对象可跨多栏Headline High 跨 816 列)
- Layer 浮动/绝对定位,脱离栅格流
- `breakable` 控制打印分页断开`break-inside: auto | avoid`
- BodyText 多栏:`columns: 1 | 2 | 3 | 4` 启用 CSS multi-column;通过 `column-rule: 1px solid var(--nui-rule-hairline)` 渲染栏间细线;标题与 PullQuote 自动 `break-inside: avoid` 避免被切断
- 响应式:通过 CSS media query / container query 在小屏调整列数与栏宽(不使用 JS 路径)
---
## 8. 文档网站
- 技术栈:shadcn stack + Next.js + Tailwind + MDX
- Demo 内嵌组件,展示属性、span、视觉权重、跨栏效果
- 文档章节
1. 概览与目标
2. 栅格系统与 Layout/Section 说明
3. 核心组件(Article/Image/Layer)属性说明
4. 文本组件属性与权重映射
5. 主题与变量使用指南
6. 跨栏和浮动 Layer 示例
7. 响应式布局展示
- 技术栈:Next.js + Tailwind + MDX
- 页面:所有 demo 用真实组件渲染,非 mockup
- 路由结构
1. `/` 首页 = NYT 派完整报纸头版(Masthead + Briefs + Lead Story 含 hero image + 3 栏 BodyText + drop cap + PullQuote + Secondary + Third Story 4 栏)
2. `/grid-system` 栅格系统与 Layout/Section/Article/Layer 说明
3. `/components/masthead` Masthead 三种 variant 对照
4. `/components/article` Article + Layer 跨栏与浮动 demo
5. `/components/rule` Rule 三种 variant 对照
6. `/components/media` Image / Figure / Video / PullQuote
7. `/text` 文本组件全集 + 视觉权重映射表(实时渲染)+ 多栏文字流 demo + drop cap demo
8. `/theme` CSS variables 列表 + color swatch + 暗色主题切换按钮
9. `/examples/spanning` 跨栏布局示例
10. `/examples/responsive` 响应式布局展示
11. `/examples/blackletter-frontpage` The Times / FAZ 派哥特体头版 preset
---
## 9. 实施顺序
1. 初始化 monorepo + Layout / Section 基础组件
2. 配置主题系统、视觉权重映射 CSS / Tailwind Token
3. 开发 Article / Image / Layer / PullQuote / 文本组件
4. 实现 Section 网格跨栏逻辑
5. 测试生产级报纸布局:跨栏、浮动 Layer、breakable、响应式
6. 构建文档网站,内嵌 demo 展示组件属性与效果
7. 确认生产级排版效果符合视觉权重、跨栏、主题、响应式要求
1. 初始化 monorepopnpm workspace + Turborepo
2. 实现 theme(字体导入 + 暖灰系 CSS variables + 视觉权重表 + 排版工具类 + Tailwind tokens
3. 实现 utils`validateSpan` / `clampSpan` / `cx`
4. 实现 components 三层(layout / text / media);统一 grid-column span 跨栏机制;BodyText 接入 CSS multi-column
5. 测试生产级头版:跨栏、多栏文字流、首字下沉、栏间 hairline、真小帽、Pull Quote 跨栏、breakable、响应式
6. 构建文档网站,首页直接展示 NYT 派头版作为生产级标杆,章节页用真实组件 demo
7. 验收:视觉与传统报纸排版(NYT / The Times / FAZ)一致;自动化构建/测试通过;Design Agent 复评 ≥ 9/10
---
## 10. 验收标准
打开首页应满足:
- Masthead 是 Cormorant Garamond 衬线 + 双线分隔
- 头条字号 ≥ 48px、line-height ≤ 1.15、字重 600
- 头条下方 BodyText 真分 3 栏,栏间有 1px 暖灰 hairline
- 第一段开头有真实 drop cap(占 2–3 行)
- Byline / Dateline / Kicker 是 Inter 真小帽(不是 uppercase 伪小帽)
- PullQuote 上下双 hairline、字号 2632px
- 配色是 warm off-white + 暖深灰,不是 `#FFFFFF` + `#000000`
- 数字是 old-style figures3 / 5 / 7 有下伸笔)
- 段间无空行,第二段起首行缩进 1em
- 切换 `[data-theme="dark"]` 后是暖深棕黑(不是冷黑)