feat: complete newspaperui component library with docs site

- 18 React components (Layout/Section/Article/Layer/Masthead/Rule +
  Headline/Subhead/Kicker/BodyText/Quote/Byline/Dateline/Caption +
  Image/Figure/Video/PullQuote)
- Theme: warm off-white palette, Source Serif 4 / Cormorant Garamond /
  Inter / Noto Serif SC/JP, visual weight mapping, dark mode
- Docs: Landing page, 6 Blocks (zh/en/jp), component API docs
- GitHub Pages deployment via static export

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
sunzhongyi
2026-05-20 14:22:14 +08:00
parent 610805a374
commit 1f09bba3ef
57 changed files with 2662 additions and 1127 deletions
+50
View File
@@ -0,0 +1,50 @@
name: Deploy to GitHub Pages
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm build
env:
NEXT_PUBLIC_BASE_PATH: /newspaperui
- uses: actions/upload-pages-artifact@v3
with:
path: packages/docs/out
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
+4
View File
@@ -43,3 +43,7 @@ coverage
# Misc
.cache
.temp
# IDE / tools
.playwright-mcp/
screenshots/
@@ -1,102 +0,0 @@
- generic [ref=e2]:
- navigation [ref=e3]:
- generic [ref=e4]:
- link "NewspaperUI" [ref=e5] [cursor=pointer]:
- /url: /
- paragraph [ref=e6]: 报纸布局组件库
- generic [ref=e7]:
- link "概览" [ref=e9] [cursor=pointer]:
- /url: /
- link "栅格系统" [ref=e11] [cursor=pointer]:
- /url: /grid-system
- generic [ref=e12]:
- link "核心组件" [ref=e13] [cursor=pointer]:
- /url: /components
- generic [ref=e14]:
- link "Article" [ref=e15] [cursor=pointer]:
- /url: /components/article
- link "Layer" [ref=e16] [cursor=pointer]:
- /url: /components/layer
- link "媒体组件" [ref=e17] [cursor=pointer]:
- /url: /components/media
- link "文本组件" [ref=e19] [cursor=pointer]:
- /url: /text
- link "主题系统" [ref=e21] [cursor=pointer]:
- /url: /theme
- generic [ref=e22]:
- link "示例" [ref=e23] [cursor=pointer]:
- /url: /examples
- generic [ref=e24]:
- link "跨栏布局" [ref=e25] [cursor=pointer]:
- /url: /examples/spanning
- link "响应式布局" [ref=e26] [cursor=pointer]:
- /url: /examples/responsive
- main [ref=e27]:
- generic [ref=e29]:
- heading "NewspaperUI" [level=1] [ref=e30]
- paragraph [ref=e31]: 生产级报纸布局组件库,参考 InDesign 设计理念,支持 24 列栅格、跨栏、视觉权重和主题系统。
- heading "设计理念" [level=2] [ref=e32]
- paragraph [ref=e33]: NewspaperUI 借鉴专业排版软件 InDesign 的设计思想,为 Web 应用提供报纸风格的布局能力。 组件设计遵循少而精、职责明确、无冗余、无歧义的原则。
- heading "核心特性" [level=2] [ref=e34]
- list [ref=e35]:
- listitem [ref=e36]:
- strong [ref=e37]: 24 列栅格系统
- text: "- 灵活的栅格布局,支持精确的列控制"
- listitem [ref=e38]:
- strong [ref=e39]: 跨栏布局
- text: "- 内容可以跨越多列,实现复杂的报纸排版"
- listitem [ref=e40]:
- strong [ref=e41]: 视觉权重系统
- text: "- High/Medium/Low 三级权重,自动映射字体大小和样式"
- listitem [ref=e42]:
- strong [ref=e43]: 主题系统
- text: "- 基于 CSS Variables,支持主题切换和自定义"
- listitem [ref=e44]:
- strong [ref=e45]: 响应式设计
- text: "- 小屏自动调整为 12-16 列,保持良好的阅读体验"
- listitem [ref=e46]:
- strong [ref=e47]: 浮动 Layer
- text: "- 支持绝对定位的浮动元素,如广告、拉引等"
- heading "快速开始" [level=2] [ref=e48]
- heading "安装" [level=3] [ref=e49]
- code [ref=e51]: pnpm add @newspaperui/components @newspaperui/theme
- heading "基础使用" [level=3] [ref=e52]
- generic [ref=e53]:
- generic [ref=e54]:
- heading "简单的报纸布局" [level=3] [ref=e55]
- paragraph [ref=e56]: 使用 Layout 和 Section 创建基础的栅格布局
- generic [ref=e58]:
- article [ref=e60]:
- heading "主要新闻标题" [level=1] [ref=e61]
- paragraph [ref=e62]: 这是一篇重要的新闻内容,使用 High 权重的标题和正文文本。
- generic [ref=e63]:
- article [ref=e64]:
- heading "次要新闻" [level=1] [ref=e65]
- paragraph [ref=e66]: 这是另一篇新闻,使用 Medium 权重。
- article [ref=e67]:
- heading "更多新闻" [level=1] [ref=e68]
- paragraph [ref=e69]: 更多内容在这里展示。
- button "查看代码" [ref=e71] [cursor=pointer]
- heading "下一步" [level=2] [ref=e72]
- paragraph [ref=e73]: 探索文档了解更多功能:
- list [ref=e74]:
- listitem [ref=e75]:
- link "栅格系统" [ref=e76] [cursor=pointer]:
- /url: /grid-system
- text: "- 了解 24 列栅格的工作原理"
- listitem [ref=e77]:
- link "核心组件" [ref=e78] [cursor=pointer]:
- /url: /components/article
- text: "- 学习 Article、Layer 等核心组件"
- listitem [ref=e79]:
- link "文本组件" [ref=e80] [cursor=pointer]:
- /url: /text
- text: "- 掌握视觉权重系统"
- listitem [ref=e81]:
- link "主题系统" [ref=e82] [cursor=pointer]:
- /url: /theme
- text: "- 自定义主题和样式"
- listitem [ref=e83]:
- link "示例" [ref=e84] [cursor=pointer]:
- /url: /examples/spanning
- text: "- 查看完整的布局示例"
@@ -1,13 +0,0 @@
- generic [active]:
- generic [ref=e5] [cursor=pointer]:
- button "Open Next.js Dev Tools" [ref=e6]:
- img [ref=e7]
- generic [ref=e10]:
- button "Open issues overlay" [ref=e11]:
- generic [ref=e12]:
- generic [ref=e13]: "0"
- generic [ref=e14]: "1"
- generic [ref=e15]: Issue
- button "Collapse issues badge" [ref=e16]:
- img [ref=e17]
- alert [ref=e19]
@@ -1,102 +0,0 @@
- generic [ref=e2]:
- navigation [ref=e3]:
- generic [ref=e4]:
- link "NewspaperUI" [ref=e5] [cursor=pointer]:
- /url: /
- paragraph [ref=e6]: 报纸布局组件库
- generic [ref=e7]:
- link "概览" [ref=e9] [cursor=pointer]:
- /url: /
- link "栅格系统" [ref=e11] [cursor=pointer]:
- /url: /grid-system
- generic [ref=e12]:
- link "核心组件" [ref=e13] [cursor=pointer]:
- /url: /components
- generic [ref=e14]:
- link "Article" [ref=e15] [cursor=pointer]:
- /url: /components/article
- link "Layer" [ref=e16] [cursor=pointer]:
- /url: /components/layer
- link "媒体组件" [ref=e17] [cursor=pointer]:
- /url: /components/media
- link "文本组件" [ref=e19] [cursor=pointer]:
- /url: /text
- link "主题系统" [ref=e21] [cursor=pointer]:
- /url: /theme
- generic [ref=e22]:
- link "示例" [ref=e23] [cursor=pointer]:
- /url: /examples
- generic [ref=e24]:
- link "跨栏布局" [ref=e25] [cursor=pointer]:
- /url: /examples/spanning
- link "响应式布局" [ref=e26] [cursor=pointer]:
- /url: /examples/responsive
- main [ref=e27]:
- generic [ref=e29]:
- heading "NewspaperUI" [level=1] [ref=e30]
- paragraph [ref=e31]: 生产级报纸布局组件库,参考 InDesign 设计理念,支持 24 列栅格、跨栏、视觉权重和主题系统。
- heading "设计理念" [level=2] [ref=e32]
- paragraph [ref=e33]: NewspaperUI 借鉴专业排版软件 InDesign 的设计思想,为 Web 应用提供报纸风格的布局能力。 组件设计遵循少而精、职责明确、无冗余、无歧义的原则。
- heading "核心特性" [level=2] [ref=e34]
- list [ref=e35]:
- listitem [ref=e36]:
- strong [ref=e37]: 24 列栅格系统
- text: "- 灵活的栅格布局,支持精确的列控制"
- listitem [ref=e38]:
- strong [ref=e39]: 跨栏布局
- text: "- 内容可以跨越多列,实现复杂的报纸排版"
- listitem [ref=e40]:
- strong [ref=e41]: 视觉权重系统
- text: "- High/Medium/Low 三级权重,自动映射字体大小和样式"
- listitem [ref=e42]:
- strong [ref=e43]: 主题系统
- text: "- 基于 CSS Variables,支持主题切换和自定义"
- listitem [ref=e44]:
- strong [ref=e45]: 响应式设计
- text: "- 小屏自动调整为 12-16 列,保持良好的阅读体验"
- listitem [ref=e46]:
- strong [ref=e47]: 浮动 Layer
- text: "- 支持绝对定位的浮动元素,如广告、拉引等"
- heading "快速开始" [level=2] [ref=e48]
- heading "安装" [level=3] [ref=e49]
- code [ref=e51]: pnpm add @newspaperui/components @newspaperui/theme
- heading "基础使用" [level=3] [ref=e52]
- generic [ref=e53]:
- generic [ref=e54]:
- heading "简单的报纸布局" [level=3] [ref=e55]
- paragraph [ref=e56]: 使用 Layout 和 Section 创建基础的栅格布局
- generic [ref=e58]:
- article [ref=e60]:
- heading "主要新闻标题" [level=1] [ref=e61]
- paragraph [ref=e62]: 这是一篇重要的新闻内容,使用 High 权重的标题和正文文本。
- generic [ref=e63]:
- article [ref=e64]:
- heading "次要新闻" [level=2] [ref=e65]
- paragraph [ref=e66]: 这是另一篇新闻,使用 Medium 权重。
- article [ref=e67]:
- heading "更多新闻" [level=2] [ref=e68]
- paragraph [ref=e69]: 更多内容在这里展示。
- button "查看代码" [ref=e71]
- heading "下一步" [level=2] [ref=e72]
- paragraph [ref=e73]: 探索文档了解更多功能:
- list [ref=e74]:
- listitem [ref=e75]:
- link "栅格系统" [ref=e76] [cursor=pointer]:
- /url: /grid-system
- text: "- 了解 24 列栅格的工作原理"
- listitem [ref=e77]:
- link "核心组件" [ref=e78] [cursor=pointer]:
- /url: /components/article
- text: "- 学习 Article、Layer 等核心组件"
- listitem [ref=e79]:
- link "文本组件" [ref=e80] [cursor=pointer]:
- /url: /text
- text: "- 掌握视觉权重系统"
- listitem [ref=e81]:
- link "主题系统" [ref=e82] [cursor=pointer]:
- /url: /theme
- text: "- 自定义主题和样式"
- listitem [ref=e83]:
- link "示例" [ref=e84] [cursor=pointer]:
- /url: /examples/spanning
- text: "- 查看完整的布局示例"
@@ -1,74 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e2]:
- banner [ref=e3]:
- generic [ref=e5]: Late City Edition
- heading "The Daily Chronicle" [level=1] [ref=e6]
- generic [ref=e7]:
- generic [ref=e8]: Vol. CXLIX · No. 51,895
- generic [ref=e9]: Tuesday, May 19, 2026
- generic [ref=e10]: $4.00
- generic [ref=e12]:
- article [ref=e13]:
- generic [ref=e14]: Inside Today
- heading "Senate Approves Climate Resolution After Months of Debate" [level=3] [ref=e15]
- paragraph [ref=e17]: The unanimous vote concludes a contentious legislative session marked by partisan disputes and last-minute amendments. Page A6.
- separator [ref=e18]
- heading "Tech Sector Gains as Inflation Eases" [level=3] [ref=e19]
- paragraph [ref=e21]: Major indices climbed for a fifth consecutive session as new data showed price growth slowing across consumer goods. Business B1.
- separator [ref=e22]
- heading "Drought Conditions Worsen Across the Plains" [level=3] [ref=e23]
- paragraph [ref=e25]: Officials in seven states have requested federal disaster relief as reservoir levels reach historic lows. National A12.
- separator [ref=e26]
- heading "New Exhibit Opens at the Metropolitan" [level=3] [ref=e27]
- paragraph [ref=e29]: A retrospective of mid-century textile design draws record opening crowds. Arts C3.
- article [ref=e30]:
- generic [ref=e32]: Capitol · Breaking
- heading "Historic Accord Reshapes Continental Trade After Marathon Session" [level=1] [ref=e33]
- paragraph [ref=e34]: Negotiators emerge with sweeping framework on tariffs, labor, and emissions; ratification expected within weeks
- generic [ref=e35]:
- generic [ref=e36]: By Eleanor Whitcombe and Marcus Reyes
- generic [ref=e37]: ·
- generic [ref=e38]: 5 min read
- figure "Negotiators applaud after the final draft was approved Monday evening at the Continental Conference Center. Photograph by Jane Doe / Pool" [ref=e39]:
- img "Diplomats applaud after the final draft was approved" [ref=e40]
- generic [ref=e41]:
- text: Negotiators applaud after the final draft was approved Monday evening at the Continental Conference Center.
- generic [ref=e42]: Photograph by Jane Doe / Pool
- generic [ref=e43]:
- paragraph [ref=e44]: Brussels — After eleven consecutive days of negotiation that several participants described as the most demanding in a generation, delegates from twenty-three nations announced on Monday a sweeping framework to reorganize commerce across the continent. The accord, which still requires ratification by member parliaments, would harmonize tariff schedules, set common labor standards, and bind signatories to a shared emissions pathway through 2040.
- paragraph [ref=e45]: Officials briefed on the talks said the breakthrough came shortly before midnight, when a dispute over agricultural subsidies was resolved with a side letter granting transitional relief to producers in five smaller economies. The chief negotiator, Margarethe Lindqvist, called the outcome “a long argument that finally became a conversation.”
- paragraph [ref=e46]: The frameworks most consequential provisions target heavy industry. Cement, steel, and chemical producers would face a graduated carbon levy beginning in 2028, with revenues recycled into a continental investment fund for low-carbon manufacturing. Industry associations expressed cautious support, while environmental groups praised the levys binding architecture but warned that the timeline gives polluters too much room to delay.
- paragraph [ref=e47]: Markets reacted with measured optimism. The continental composite index closed up 1.2 percent, led by capital-goods makers expected to benefit from infrastructure investment. The currency strengthened against the dollar by 0.7 percent. Bond yields, which had climbed throughout the negotiations on fiscal-stability concerns, retreated to levels seen before the talks began.
- paragraph [ref=e48]: Domestic political reaction was mixed. The accords labor provisions, which establish minimum standards for paid leave and collective bargaining, drew immediate praise from union federations and equally immediate concern from chambers of commerce. The chairman of the Federation of Industries warned that small firms would struggle with compliance costs absent transitional support.
- paragraph [ref=e49]: Parliamentary leaders in three capitals signaled that ratification could occur before the summer recess. Two governments, however, indicated that they would seek public referenda before committing, a process likely to extend into the autumn. Analysts at the Centre for Trade Studies estimated that full implementation, even on the most expedited timeline, would require at least eighteen months.
- paragraph [ref=e50]: "For ordinary travelers and consumers, the immediate effects will be modest. Border procedures and product standards remain governed by existing arrangements pending ratification. The longer arc is what matters: a continent of historically fractious neighbors agreeing on a single set of rules for the most consequential decade in living memory."
- complementary [ref=e51]:
- paragraph [ref=e52]: A long argument that finally became a conversation.
- generic [ref=e53]: — Margarethe Lindqvist, Chief Negotiator
- generic [ref=e54]:
- paragraph [ref=e55]: The accords signing ceremony, originally scheduled for last Friday, was delayed three times as drafters reconciled competing texts on dispute resolution. The final compromise establishes an arbitration panel of nine jurists, three appointed by each of the blocs three regional groupings, with binding authority over commercial disputes exceeding twenty million units.
- paragraph [ref=e56]: Critics on the populist right denounced the framework as an erosion of national sovereignty, while critics on the left argued that the labor floor was set too low to meaningfully protect workers in tighter regulatory regimes. Both camps signaled that ratification battles would be fierce, particularly in legislatures with narrow majorities.
- article [ref=e57]:
- generic [ref=e58]: Foreign Desk
- heading "Coastal Nations Pledge Joint Action on Maritime Pollution" [level=2] [ref=e59]
- paragraph [ref=e60]: Pact follows years of stalled regional talks and a cascade of recent shipping accidents.
- generic [ref=e61]: By Tomás Almeida
- generic [ref=e62]:
- paragraph [ref=e63]: Lisbon — Eleven coastal nations announced a binding compact to coordinate cleanup operations and harmonize liability rules for vessels exceeding fifty thousand tons. The agreement establishes a shared rapid-response fund and creates a regional inspectorate empowered to detain non-compliant ships in any signatory port.
- paragraph [ref=e64]: Maritime industry groups received the news with caution. A spokesperson for the Continental Shipping Council acknowledged that “stronger common rules are overdue” but warned that implementation costs could fall disproportionately on smaller operators.
- paragraph [ref=e65]: The compact takes effect on January 1, pending technical annexes. Environmental observers described the pact as the most consequential maritime accord in a decade.
- article [ref=e67]:
- generic [ref=e68]: National · Investigation
- heading "Records Reveal Years of Overlooked Warnings at Aging Reservoirs" [level=2] [ref=e69]
- paragraph [ref=e70]: Internal inspection memoranda, obtained through public records requests, suggest that structural concerns flagged repeatedly by field engineers were not escalated to senior staff.
- generic [ref=e71]: By Ravi Nair, Anita Kowalski, and Charles Weston
- generic [ref=e72]:
- paragraph [ref=e73]: Sacramento — A six-month review of more than four thousand pages of inspection records, interviews with twenty-three current and former engineers, and reconstructions of three near-failure incidents reveals a pattern of unheeded warnings about the structural integrity of mid-twentieth-century earthen dams across the western states.
- paragraph [ref=e74]: The records show that field engineers documented concerns about seepage, erosion, and spillway capacity in repeated annual assessments dating back at least fifteen years. In several instances, those concerns were rated “moderate” in the field reports but downgraded to “low” by the time they reached senior officials. The pattern was particularly pronounced at three facilities serving regions of more than two million residents.
- paragraph [ref=e75]: Officials at the Department of Water Resources, asked to review excerpts of the records, said in a written statement that “every reservoir under our oversight has been deemed safe for current operations” but did not specifically address the discrepancies between field and final ratings. The agency declined to make senior staff available for interviews.
- paragraph [ref=e76]: The findings come amid renewed scrutiny of aging infrastructure following the partial collapse of an earthen embankment in March that displaced more than fifteen hundred residents. Federal inspectors who responded to that incident found the proximate cause to be precisely the type of seepage concern that field engineers had flagged in three of the past four annual assessments.
- paragraph [ref=e77]: The investigative review found that of forty-seven reservoirs surveyed, sixteen had at least one instance in which a “moderate” or “high” field rating was downgraded before reaching senior management. In nine cases, the downgrades persisted for three or more consecutive years. None of the affected facilities have publicly disclosed the discrepancies.
- paragraph [ref=e78]: Engineering professional associations have, in recent years, called for an independent review of inspection workflows in the western states. A spokesperson for the Society of Hydraulic Engineers said the Society was “deeply concerned” by the patterns described and would convene a working group to examine reform options.
- button "Open Next.js Dev Tools" [ref=e84] [cursor=pointer]:
- img [ref=e85]
- alert [ref=e88]
@@ -1,74 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e2]:
- banner [ref=e3]:
- generic [ref=e5]: Late City Edition
- heading "The Daily Chronicle" [level=1] [ref=e6]
- generic [ref=e7]:
- generic [ref=e8]: Vol. CXLIX · No. 51,895
- generic [ref=e9]: Tuesday, May 19, 2026
- generic [ref=e10]: $4.00
- generic [ref=e12]:
- article [ref=e13]:
- generic [ref=e14]: Inside Today
- heading "Senate Approves Climate Resolution After Months of Debate" [level=3] [ref=e15]
- paragraph [ref=e17]: The unanimous vote concludes a contentious legislative session marked by partisan disputes and last-minute amendments. Page A6.
- separator [ref=e18]
- heading "Tech Sector Gains as Inflation Eases" [level=3] [ref=e19]
- paragraph [ref=e21]: Major indices climbed for a fifth consecutive session as new data showed price growth slowing across consumer goods. Business B1.
- separator [ref=e22]
- heading "Drought Conditions Worsen Across the Plains" [level=3] [ref=e23]
- paragraph [ref=e25]: Officials in seven states have requested federal disaster relief as reservoir levels reach historic lows. National A12.
- separator [ref=e26]
- heading "New Exhibit Opens at the Metropolitan" [level=3] [ref=e27]
- paragraph [ref=e29]: A retrospective of mid-century textile design draws record opening crowds. Arts C3.
- article [ref=e30]:
- generic [ref=e32]: Capitol · Breaking
- heading "Historic Accord Reshapes Continental Trade After Marathon Session" [level=1] [ref=e33]
- paragraph [ref=e34]: Negotiators emerge with sweeping framework on tariffs, labor, and emissions; ratification expected within weeks
- generic [ref=e35]:
- generic [ref=e36]: By Eleanor Whitcombe and Marcus Reyes
- generic [ref=e37]: ·
- generic [ref=e38]: 5 min read
- figure "Negotiators applaud after the final draft was approved Monday evening at the Continental Conference Center. Photograph by Jane Doe / Pool" [ref=e39]:
- img "Diplomats applaud after the final draft was approved" [ref=e40]
- generic [ref=e41]:
- text: Negotiators applaud after the final draft was approved Monday evening at the Continental Conference Center.
- generic [ref=e42]: Photograph by Jane Doe / Pool
- generic [ref=e43]:
- paragraph [ref=e44]: Brussels — After eleven consecutive days of negotiation that several participants described as the most demanding in a generation, delegates from twenty-three nations announced on Monday a sweeping framework to reorganize commerce across the continent. The accord, which still requires ratification by member parliaments, would harmonize tariff schedules, set common labor standards, and bind signatories to a shared emissions pathway through 2040.
- paragraph [ref=e45]: Officials briefed on the talks said the breakthrough came shortly before midnight, when a dispute over agricultural subsidies was resolved with a side letter granting transitional relief to producers in five smaller economies. The chief negotiator, Margarethe Lindqvist, called the outcome “a long argument that finally became a conversation.”
- paragraph [ref=e46]: The frameworks most consequential provisions target heavy industry. Cement, steel, and chemical producers would face a graduated carbon levy beginning in 2028, with revenues recycled into a continental investment fund for low-carbon manufacturing. Industry associations expressed cautious support, while environmental groups praised the levys binding architecture but warned that the timeline gives polluters too much room to delay.
- paragraph [ref=e47]: Markets reacted with measured optimism. The continental composite index closed up 1.2 percent, led by capital-goods makers expected to benefit from infrastructure investment. The currency strengthened against the dollar by 0.7 percent. Bond yields, which had climbed throughout the negotiations on fiscal-stability concerns, retreated to levels seen before the talks began.
- paragraph [ref=e48]: Domestic political reaction was mixed. The accords labor provisions, which establish minimum standards for paid leave and collective bargaining, drew immediate praise from union federations and equally immediate concern from chambers of commerce. The chairman of the Federation of Industries warned that small firms would struggle with compliance costs absent transitional support.
- paragraph [ref=e49]: Parliamentary leaders in three capitals signaled that ratification could occur before the summer recess. Two governments, however, indicated that they would seek public referenda before committing, a process likely to extend into the autumn. Analysts at the Centre for Trade Studies estimated that full implementation, even on the most expedited timeline, would require at least eighteen months.
- paragraph [ref=e50]: "For ordinary travelers and consumers, the immediate effects will be modest. Border procedures and product standards remain governed by existing arrangements pending ratification. The longer arc is what matters: a continent of historically fractious neighbors agreeing on a single set of rules for the most consequential decade in living memory."
- complementary [ref=e51]:
- paragraph [ref=e52]: A long argument that finally became a conversation.
- generic [ref=e53]: — Margarethe Lindqvist, Chief Negotiator
- generic [ref=e54]:
- paragraph [ref=e55]: The accords signing ceremony, originally scheduled for last Friday, was delayed three times as drafters reconciled competing texts on dispute resolution. The final compromise establishes an arbitration panel of nine jurists, three appointed by each of the blocs three regional groupings, with binding authority over commercial disputes exceeding twenty million units.
- paragraph [ref=e56]: Critics on the populist right denounced the framework as an erosion of national sovereignty, while critics on the left argued that the labor floor was set too low to meaningfully protect workers in tighter regulatory regimes. Both camps signaled that ratification battles would be fierce, particularly in legislatures with narrow majorities.
- article [ref=e57]:
- generic [ref=e58]: Foreign Desk
- heading "Coastal Nations Pledge Joint Action on Maritime Pollution" [level=2] [ref=e59]
- paragraph [ref=e60]: Pact follows years of stalled regional talks and a cascade of recent shipping accidents.
- generic [ref=e61]: By Tomás Almeida
- generic [ref=e62]:
- paragraph [ref=e63]: Lisbon — Eleven coastal nations announced a binding compact to coordinate cleanup operations and harmonize liability rules for vessels exceeding fifty thousand tons. The agreement establishes a shared rapid-response fund and creates a regional inspectorate empowered to detain non-compliant ships in any signatory port.
- paragraph [ref=e64]: Maritime industry groups received the news with caution. A spokesperson for the Continental Shipping Council acknowledged that “stronger common rules are overdue” but warned that implementation costs could fall disproportionately on smaller operators.
- paragraph [ref=e65]: The compact takes effect on January 1, pending technical annexes. Environmental observers described the pact as the most consequential maritime accord in a decade.
- article [ref=e67]:
- generic [ref=e68]: National · Investigation
- heading "Records Reveal Years of Overlooked Warnings at Aging Reservoirs" [level=2] [ref=e69]
- paragraph [ref=e70]: Internal inspection memoranda, obtained through public records requests, suggest that structural concerns flagged repeatedly by field engineers were not escalated to senior staff.
- generic [ref=e71]: By Ravi Nair, Anita Kowalski, and Charles Weston
- generic [ref=e72]:
- paragraph [ref=e73]: Sacramento — A six-month review of more than four thousand pages of inspection records, interviews with twenty-three current and former engineers, and reconstructions of three near-failure incidents reveals a pattern of unheeded warnings about the structural integrity of mid-twentieth-century earthen dams across the western states.
- paragraph [ref=e74]: The records show that field engineers documented concerns about seepage, erosion, and spillway capacity in repeated annual assessments dating back at least fifteen years. In several instances, those concerns were rated “moderate” in the field reports but downgraded to “low” by the time they reached senior officials. The pattern was particularly pronounced at three facilities serving regions of more than two million residents.
- paragraph [ref=e75]: Officials at the Department of Water Resources, asked to review excerpts of the records, said in a written statement that “every reservoir under our oversight has been deemed safe for current operations” but did not specifically address the discrepancies between field and final ratings. The agency declined to make senior staff available for interviews.
- paragraph [ref=e76]: The findings come amid renewed scrutiny of aging infrastructure following the partial collapse of an earthen embankment in March that displaced more than fifteen hundred residents. Federal inspectors who responded to that incident found the proximate cause to be precisely the type of seepage concern that field engineers had flagged in three of the past four annual assessments.
- paragraph [ref=e77]: The investigative review found that of forty-seven reservoirs surveyed, sixteen had at least one instance in which a “moderate” or “high” field rating was downgraded before reaching senior management. In nine cases, the downgrades persisted for three or more consecutive years. None of the affected facilities have publicly disclosed the discrepancies.
- paragraph [ref=e78]: Engineering professional associations have, in recent years, called for an independent review of inspection workflows in the western states. A spokesperson for the Society of Hydraulic Engineers said the Society was “deeply concerned” by the patterns described and would convene a working group to examine reform options.
- button "Open Next.js Dev Tools" [ref=e84] [cursor=pointer]:
- img [ref=e85]
- alert [ref=e88]
@@ -1,39 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e2]:
- banner [ref=e3]:
- heading "Die Frankfurter Zeitung" [level=1] [ref=e5]
- generic [ref=e6]:
- generic [ref=e7]: Nr. 117 · 142. Jahrgang
- generic [ref=e8]: Dienstag, 19. Mai 2026
- generic [ref=e9]: € 3,80
- generic [ref=e11]:
- article [ref=e12]:
- generic [ref=e13]: Im Blatt
- heading "Bundestag billigt Klimapaket nach langer Debatte" [level=3] [ref=e14]
- paragraph [ref=e16]: Die einstimmige Abstimmung beendet eine umstrittene Sitzungsperiode. Politik, Seite 4.
- separator [ref=e17]
- heading "Industrie sieht in Reform Chance und Risiko" [level=3] [ref=e18]
- paragraph [ref=e20]: Verbände begrüßen die Pläne, mahnen aber Übergangsfristen für kleinere Betriebe an. Wirtschaft, Seite 9.
- article [ref=e21]:
- generic [ref=e22]: Politik · Eilmeldung
- heading "Historischer Pakt nach langem Verhandlungsmarathon beschlossen" [level=1] [ref=e23]
- paragraph [ref=e24]: Delegierte aus dreiundzwanzig Nationen einigen sich auf einen Rahmen für Zölle, Arbeit und Emissionen
- generic [ref=e25]: Von Eleonore Witkomm und Markus Reyes
- 'figure "Die Delegationen applaudieren nach der Verabschiedung des Schlussdokuments am Montagabend. Foto: Jane Doe / Pool" [ref=e26]':
- img "Verhandlungsführer am Konferenztisch" [ref=e27]
- generic [ref=e28]:
- text: Die Delegationen applaudieren nach der Verabschiedung des Schlussdokuments am Montagabend.
- generic [ref=e29]: "Foto: Jane Doe / Pool"
- generic [ref=e30]:
- paragraph [ref=e31]: Brüssel — Nach elf aufeinanderfolgenden Verhandlungstagen, die mehrere Teilnehmer als die anstrengendsten einer Generation bezeichneten, haben Delegierte aus dreiundzwanzig Nationen am Montag einen umfassenden Rahmen vorgelegt, der den Handel auf dem gesamten Kontinent neu ordnen soll.
- paragraph [ref=e32]: Das Abkommen, das noch von den nationalen Parlamenten ratifiziert werden muss, würde Zollordnungen harmonisieren, gemeinsame Arbeitsstandards setzen und die Unterzeichner auf einen geteilten Emissionspfad bis 2040 verpflichten. Beamte, die in die Gespräche eingeweiht waren, sagten, der Durchbruch sei kurz vor Mitternacht gekommen.
- paragraph [ref=e33]: Die Märkte reagierten mit verhaltenem Optimismus. Der kontinentale Composite-Index schloss mit einem Plus von 1,2 Prozent. Die Währung legte gegenüber dem Dollar um 0,7 Prozent zu. Anleiherenditen, die während der Verhandlungen wegen fiskalischer Sorgen gestiegen waren, kehrten auf das Niveau vor Beginn der Gespräche zurück.
- complementary [ref=e34]:
- paragraph [ref=e35]: Ein langer Streit, der schließlich zum Gespräch wurde.
- generic [ref=e36]: — Margarethe Lindqvist, Chefverhandlerin
- generic [ref=e37]:
- paragraph [ref=e38]: Das Rahmenabkommen sieht eine schrittweise CO₂-Abgabe für Schwerindustrie ab 2028 vor. Einnahmen sollen in einen Investitionsfonds für klimafreundliche Fertigung fließen.
- paragraph [ref=e39]: Parlamentarische Führer in drei Hauptstädten signalisierten, dass die Ratifizierung noch vor der Sommerpause erfolgen könnte. Zwei Regierungen kündigten an, vorher Volksabstimmungen abhalten zu wollen.
- button "Open Next.js Dev Tools" [ref=e45] [cursor=pointer]:
- img [ref=e46]
- alert [ref=e49]
@@ -1,39 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e2]:
- banner [ref=e3]:
- heading "Die Frankfurter Zeitung" [level=1] [ref=e5]
- generic [ref=e6]:
- generic [ref=e7]: Nr. 117 · 142. Jahrgang
- generic [ref=e8]: Dienstag, 19. Mai 2026
- generic [ref=e9]: € 3,80
- generic [ref=e11]:
- article [ref=e12]:
- generic [ref=e13]: Im Blatt
- heading "Bundestag billigt Klimapaket nach langer Debatte" [level=3] [ref=e14]
- paragraph [ref=e16]: Die einstimmige Abstimmung beendet eine umstrittene Sitzungsperiode. Politik, Seite 4.
- separator [ref=e17]
- heading "Industrie sieht in Reform Chance und Risiko" [level=3] [ref=e18]
- paragraph [ref=e20]: Verbände begrüßen die Pläne, mahnen aber Übergangsfristen für kleinere Betriebe an. Wirtschaft, Seite 9.
- article [ref=e21]:
- generic [ref=e22]: Politik · Eilmeldung
- heading "Historischer Pakt nach langem Verhandlungsmarathon beschlossen" [level=1] [ref=e23]
- paragraph [ref=e24]: Delegierte aus dreiundzwanzig Nationen einigen sich auf einen Rahmen für Zölle, Arbeit und Emissionen
- generic [ref=e25]: Von Eleonore Witkomm und Markus Reyes
- 'figure "Die Delegationen applaudieren nach der Verabschiedung des Schlussdokuments am Montagabend. Foto: Jane Doe / Pool" [ref=e26]':
- img "Verhandlungsführer am Konferenztisch" [ref=e27]
- generic [ref=e28]:
- text: Die Delegationen applaudieren nach der Verabschiedung des Schlussdokuments am Montagabend.
- generic [ref=e29]: "Foto: Jane Doe / Pool"
- generic [ref=e30]:
- paragraph [ref=e31]: Brüssel — Nach elf aufeinanderfolgenden Verhandlungstagen, die mehrere Teilnehmer als die anstrengendsten einer Generation bezeichneten, haben Delegierte aus dreiundzwanzig Nationen am Montag einen umfassenden Rahmen vorgelegt, der den Handel auf dem gesamten Kontinent neu ordnen soll.
- paragraph [ref=e32]: Das Abkommen, das noch von den nationalen Parlamenten ratifiziert werden muss, würde Zollordnungen harmonisieren, gemeinsame Arbeitsstandards setzen und die Unterzeichner auf einen geteilten Emissionspfad bis 2040 verpflichten. Beamte, die in die Gespräche eingeweiht waren, sagten, der Durchbruch sei kurz vor Mitternacht gekommen.
- paragraph [ref=e33]: Die Märkte reagierten mit verhaltenem Optimismus. Der kontinentale Composite-Index schloss mit einem Plus von 1,2 Prozent. Die Währung legte gegenüber dem Dollar um 0,7 Prozent zu. Anleiherenditen, die während der Verhandlungen wegen fiskalischer Sorgen gestiegen waren, kehrten auf das Niveau vor Beginn der Gespräche zurück.
- complementary [ref=e34]:
- paragraph [ref=e35]: Ein langer Streit, der schließlich zum Gespräch wurde.
- generic [ref=e36]: — Margarethe Lindqvist, Chefverhandlerin
- generic [ref=e37]:
- paragraph [ref=e38]: Das Rahmenabkommen sieht eine schrittweise CO₂-Abgabe für Schwerindustrie ab 2028 vor. Einnahmen sollen in einen Investitionsfonds für klimafreundliche Fertigung fließen.
- paragraph [ref=e39]: Parlamentarische Führer in drei Hauptstädten signalisierten, dass die Ratifizierung noch vor der Sommerpause erfolgen könnte. Zwei Regierungen kündigten an, vorher Volksabstimmungen abhalten zu wollen.
- button "Open Next.js Dev Tools" [ref=e45] [cursor=pointer]:
- img [ref=e46]
- alert [ref=e49]
@@ -1,309 +0,0 @@
- generic [ref=e2]:
- complementary [ref=e3]:
- link "NewspaperUI" [ref=e4] [cursor=pointer]:
- /url: /
- generic [ref=e5]: Production Newspaper Components
- navigation [ref=e6]:
- list [ref=e7]:
- listitem [ref=e8]:
- link "概览 / 头版" [ref=e9] [cursor=pointer]:
- /url: /
- listitem [ref=e10]:
- link "栅格系统" [ref=e11] [cursor=pointer]:
- /url: /grid-system
- listitem [ref=e12]:
- link "布局组件" [ref=e13] [cursor=pointer]:
- /url: /components/article
- list [ref=e14]:
- listitem [ref=e15]:
- link "Masthead" [ref=e16] [cursor=pointer]:
- /url: /components/masthead
- listitem [ref=e17]:
- link "Article + Layer" [ref=e18] [cursor=pointer]:
- /url: /components/article
- listitem [ref=e19]:
- link "Rule 分隔线" [ref=e20] [cursor=pointer]:
- /url: /components/rule
- listitem [ref=e21]:
- link "文本组件" [ref=e22] [cursor=pointer]:
- /url: /text
- listitem [ref=e23]:
- link "媒体组件" [ref=e24] [cursor=pointer]:
- /url: /components/media
- listitem [ref=e25]:
- link "主题与颜色" [ref=e26] [cursor=pointer]:
- /url: /theme
- listitem [ref=e27]:
- link "示例" [ref=e28] [cursor=pointer]:
- /url: /examples/spanning
- list [ref=e29]:
- listitem [ref=e30]:
- link "跨栏布局" [ref=e31] [cursor=pointer]:
- /url: /examples/spanning
- listitem [ref=e32]:
- link "响应式" [ref=e33] [cursor=pointer]:
- /url: /examples/responsive
- listitem [ref=e34]:
- link "Blackletter 头版" [ref=e35] [cursor=pointer]:
- /url: /examples/blackletter-frontpage
- main [ref=e36]:
- article [ref=e39]:
- heading "文本组件" [level=1] [ref=e40]
- paragraph [ref=e41]: 从 Headline 到 Caption 的完整文本谱系。每个组件按视觉权重映射到字体、字号、字重、 行高与颜色 token,避免硬编码样式。
- heading "Headline 三档" [level=2] [ref=e42]
- generic [ref=e43]:
- heading "High / Medium / Low" [level=3] [ref=e45]
- generic [ref=e47]:
- generic [ref=e48]:
- generic [ref=e49]: weight="High"
- heading "A Quiet Revolution in the Treasury Forecast" [level=3] [ref=e50]
- generic [ref=e51]:
- generic [ref=e52]: weight="Medium"
- heading "Whitehall Confirms Infrastructure Review" [level=3] [ref=e53]
- generic [ref=e54]:
- generic [ref=e55]: weight="Low"
- 'heading "Briefing: regional rail commitments" [level=3] [ref=e56]'
- heading "Subhead 两档" [level=2] [ref=e57]
- generic [ref=e58]:
- heading "High / Medium" [level=3] [ref=e60]
- generic [ref=e62]:
- paragraph [ref=e63]: A measured recalibration of regional priorities is expected to define the chancellors autumn agenda.
- paragraph [ref=e64]: Officials emphasized that the headline figures should be read as a planning envelope rather than a binding allocation.
- heading "Kicker" [level=2] [ref=e65]
- generic [ref=e66]:
- heading "朱红 small-caps,挂在 Headline 上方" [level=3] [ref=e68]
- generic [ref=e70]:
- generic [ref=e71]: POLITICS · WHITEHALL
- heading "A Standing Technical Commission, Quietly Proposed" [level=3] [ref=e72]
- heading "BodyText 多栏文字流" [level=2] [ref=e73]
- generic [ref=e74]:
- generic [ref=e75]:
- heading "单栏" [level=3] [ref=e76]
- paragraph [ref=e77]: 默认形态,适合中等宽度的文章正文。
- generic [ref=e79]:
- paragraph [ref=e80]: Whitehall officials confirmed late Tuesday that the long-anticipated review of national infrastructure funding will be tabled before the recess. The 248-page document, drafted across three departments, recommends a recalibration of regional priorities and a measured shift toward rail electrification. Critics inside the cabinet caution that the timing risks overshadowing the chancellor's autumn statement, while supporters describe the proposals as the most coherent strategic blueprint in a generation.
- paragraph [ref=e81]: Markets responded cautiously through the morning session. The pound traded sideways against the dollar, gilts firmed by three basis points, and the FTSE 100 closed marginally lower as defensive sectors absorbed the day's modest outflows. Analysts at three of the City's largest houses framed the move as a holding pattern, awaiting further detail on the spending envelope rather than a verdict on its substance.
- generic [ref=e82]:
- generic [ref=e83]:
- heading "三栏 + 首字下沉" [level=3] [ref=e84]
- paragraph [ref=e85]: "开启 columns={3} 与 dropCap,第一段首字母自动下沉占 2-3 行。"
- generic [ref=e87]:
- paragraph [ref=e88]: Whitehall officials confirmed late Tuesday that the long-anticipated review of national infrastructure funding will be tabled before the recess. The 248-page document, drafted across three departments, recommends a recalibration of regional priorities and a measured shift toward rail electrification. Critics inside the cabinet caution that the timing risks overshadowing the chancellor's autumn statement, while supporters describe the proposals as the most coherent strategic blueprint in a generation.
- paragraph [ref=e89]: Markets responded cautiously through the morning session. The pound traded sideways against the dollar, gilts firmed by three basis points, and the FTSE 100 closed marginally lower as defensive sectors absorbed the day's modest outflows. Analysts at three of the City's largest houses framed the move as a holding pattern, awaiting further detail on the spending envelope rather than a verdict on its substance.
- paragraph [ref=e90]: In Manchester, regional officials greeted the announcement with measured optimism. "We have lobbied for this kind of clarity for the better part of a decade," said one senior figure who requested anonymity to discuss internal deliberations. The mayor's office is expected to issue a formal response by week's end, focusing on commitments to the trans-Pennine corridor and the long-deferred upgrade of suburban tram capacity.
- paragraph [ref=e91]: "Beyond the immediate fiscal arithmetic, the review's most consequential proposal may be its quietest: a standing technical commission, modeled on Australia's Infrastructure Australia, to depoliticize project sequencing. Whether that body acquires teeth — or settles into the advisory torpor that has consumed earlier attempts — will be determined by the legislation expected in the spring."
- button "查看代码" [ref=e93] [cursor=pointer]
- generic [ref=e94]:
- generic [ref=e95]:
- heading "两栏(无 dropCap" [level=3] [ref=e96]
- paragraph [ref=e97]: "columns={2},栏间细线由 nui-column-rule 提供。"
- generic [ref=e99]:
- paragraph [ref=e100]: Whitehall officials confirmed late Tuesday that the long-anticipated review of national infrastructure funding will be tabled before the recess. The 248-page document, drafted across three departments, recommends a recalibration of regional priorities and a measured shift toward rail electrification. Critics inside the cabinet caution that the timing risks overshadowing the chancellor's autumn statement, while supporters describe the proposals as the most coherent strategic blueprint in a generation.
- paragraph [ref=e101]: Markets responded cautiously through the morning session. The pound traded sideways against the dollar, gilts firmed by three basis points, and the FTSE 100 closed marginally lower as defensive sectors absorbed the day's modest outflows. Analysts at three of the City's largest houses framed the move as a holding pattern, awaiting further detail on the spending envelope rather than a verdict on its substance.
- paragraph [ref=e102]: In Manchester, regional officials greeted the announcement with measured optimism. "We have lobbied for this kind of clarity for the better part of a decade," said one senior figure who requested anonymity to discuss internal deliberations. The mayor's office is expected to issue a formal response by week's end, focusing on commitments to the trans-Pennine corridor and the long-deferred upgrade of suburban tram capacity.
- heading "Quote 引用" [level=2] [ref=e103]
- generic [ref=e104]:
- heading "block / inline 对照" [level=3] [ref=e106]
- generic [ref=e108]:
- blockquote [ref=e109]: We have lobbied for this kind of clarity for the better part of a decade.
- paragraph [ref=e111]:
- text: 按一位资深内阁人士的说法,这份评估
- emphasis [ref=e112]: 是一个时代以来最连贯的战略蓝图
- text: ,但能否落地仍取决于春季立法。
- heading "Byline / Dateline / Caption" [level=2] [ref=e113]
- generic [ref=e114]:
- heading "元信息组件" [level=3] [ref=e116]
- generic [ref=e118]:
- generic [ref=e119]:
- generic [ref=e120]: BY ALICE SMITH
- text: LONDON —
- figure "A view of the Treasury terrace at dusk; the new commission will report here from May. Photograph by Jane Doe" [ref=e121]:
- generic [ref=e123]:
- text: A view of the Treasury terrace at dusk; the new commission will report here from May.
- generic [ref=e124]: Photograph by Jane Doe
- heading "视觉权重映射表" [level=2] [ref=e125]
- paragraph [ref=e127]:
- text: 下表从
- code [ref=e128]: visualWeights
- text: 数据动态生成,反映组件实际渲染时所用的 token。修改 theme 后表格自动同步。
- table [ref=e130]:
- rowgroup [ref=e131]:
- row "组件 权重 字体 字号 字重 行高 颜色" [ref=e132]:
- columnheader "组件" [ref=e133]
- columnheader "权重" [ref=e134]
- columnheader "字体" [ref=e135]
- columnheader "字号" [ref=e136]
- columnheader "字重" [ref=e137]
- columnheader "行高" [ref=e138]
- columnheader "颜色" [ref=e139]
- rowgroup [ref=e140]:
- row "Masthead Standard --font-family-masthead 56px 700 1 --nui-text-primary" [ref=e141]:
- cell "Masthead" [ref=e142]
- cell "Standard" [ref=e143]
- cell "--font-family-masthead" [ref=e144]:
- code [ref=e145]: "--font-family-masthead"
- cell "56px" [ref=e146]
- cell "700" [ref=e147]
- cell "1" [ref=e148]
- cell "--nui-text-primary" [ref=e149]:
- code [ref=e150]: "--nui-text-primary"
- row "Headline High --font-family-display 48px 600 1.05 --nui-text-primary" [ref=e151]:
- cell "Headline" [ref=e152]
- cell "High" [ref=e153]
- cell "--font-family-display" [ref=e154]:
- code [ref=e155]: "--font-family-display"
- cell "48px" [ref=e156]
- cell "600" [ref=e157]
- cell "1.05" [ref=e158]
- cell "--nui-text-primary" [ref=e159]:
- code [ref=e160]: "--nui-text-primary"
- row "Headline Medium --font-family-headline 32px 600 1.1 --nui-text-primary" [ref=e161]:
- cell "Headline" [ref=e162]
- cell "Medium" [ref=e163]
- cell "--font-family-headline" [ref=e164]:
- code [ref=e165]: "--font-family-headline"
- cell "32px" [ref=e166]
- cell "600" [ref=e167]
- cell "1.1" [ref=e168]
- cell "--nui-text-primary" [ref=e169]:
- code [ref=e170]: "--nui-text-primary"
- row "Headline Low --font-family-headline 22px 500 1.2 --nui-text-body" [ref=e171]:
- cell "Headline" [ref=e172]
- cell "Low" [ref=e173]
- cell "--font-family-headline" [ref=e174]:
- code [ref=e175]: "--font-family-headline"
- cell "22px" [ref=e176]
- cell "500" [ref=e177]
- cell "1.2" [ref=e178]
- cell "--nui-text-body" [ref=e179]:
- code [ref=e180]: "--nui-text-body"
- row "Subhead High --font-family-headline 18px 500 1.3 --nui-text-secondary" [ref=e181]:
- cell "Subhead" [ref=e182]
- cell "High" [ref=e183]
- cell "--font-family-headline" [ref=e184]:
- code [ref=e185]: "--font-family-headline"
- cell "18px" [ref=e186]
- cell "500" [ref=e187]
- cell "1.3" [ref=e188]
- cell "--nui-text-secondary" [ref=e189]:
- code [ref=e190]: "--nui-text-secondary"
- row "Subhead Medium --font-family-headline 16px 400 1.35 --nui-text-secondary" [ref=e191]:
- cell "Subhead" [ref=e192]
- cell "Medium" [ref=e193]
- cell "--font-family-headline" [ref=e194]:
- code [ref=e195]: "--font-family-headline"
- cell "16px" [ref=e196]
- cell "400" [ref=e197]
- cell "1.35" [ref=e198]
- cell "--nui-text-secondary" [ref=e199]:
- code [ref=e200]: "--nui-text-secondary"
- row "Kicker Standard --font-family-meta 12px 600 1.2 --nui-accent-primary" [ref=e201]:
- cell "Kicker" [ref=e202]
- cell "Standard" [ref=e203]
- cell "--font-family-meta" [ref=e204]:
- code [ref=e205]: "--font-family-meta"
- cell "12px" [ref=e206]
- cell "600" [ref=e207]
- cell "1.2" [ref=e208]
- cell "--nui-accent-primary" [ref=e209]:
- code [ref=e210]: "--nui-accent-primary"
- row "BodyText High --font-family-body 16px 400 1.6 --nui-text-body" [ref=e211]:
- cell "BodyText" [ref=e212]
- cell "High" [ref=e213]
- cell "--font-family-body" [ref=e214]:
- code [ref=e215]: "--font-family-body"
- cell "16px" [ref=e216]
- cell "400" [ref=e217]
- cell "1.6" [ref=e218]
- cell "--nui-text-body" [ref=e219]:
- code [ref=e220]: "--nui-text-body"
- row "BodyText Medium --font-family-body 15px 400 1.55 --nui-text-body" [ref=e221]:
- cell "BodyText" [ref=e222]
- cell "Medium" [ref=e223]
- cell "--font-family-body" [ref=e224]:
- code [ref=e225]: "--font-family-body"
- cell "15px" [ref=e226]
- cell "400" [ref=e227]
- cell "1.55" [ref=e228]
- cell "--nui-text-body" [ref=e229]:
- code [ref=e230]: "--nui-text-body"
- row "BodyText Low --font-family-body 13px 400 1.5 --nui-text-secondary" [ref=e231]:
- cell "BodyText" [ref=e232]
- cell "Low" [ref=e233]
- cell "--font-family-body" [ref=e234]:
- code [ref=e235]: "--font-family-body"
- cell "13px" [ref=e236]
- cell "400" [ref=e237]
- cell "1.5" [ref=e238]
- cell "--nui-text-secondary" [ref=e239]:
- code [ref=e240]: "--nui-text-secondary"
- row "Quote High --font-family-body 17px 400 1.55 --nui-text-quote" [ref=e241]:
- cell "Quote" [ref=e242]
- cell "High" [ref=e243]
- cell "--font-family-body" [ref=e244]:
- code [ref=e245]: "--font-family-body"
- cell "17px" [ref=e246]
- cell "400" [ref=e247]
- cell "1.55" [ref=e248]
- cell "--nui-text-quote" [ref=e249]:
- code [ref=e250]: "--nui-text-quote"
- row "Quote Medium --font-family-body 15px 400 1.5 --nui-text-quote" [ref=e251]:
- cell "Quote" [ref=e252]
- cell "Medium" [ref=e253]
- cell "--font-family-body" [ref=e254]:
- code [ref=e255]: "--font-family-body"
- cell "15px" [ref=e256]
- cell "400" [ref=e257]
- cell "1.5" [ref=e258]
- cell "--nui-text-quote" [ref=e259]:
- code [ref=e260]: "--nui-text-quote"
- row "PullQuote High --font-family-display 26px 600 1.2 --nui-text-primary" [ref=e261]:
- cell "PullQuote" [ref=e262]
- cell "High" [ref=e263]
- cell "--font-family-display" [ref=e264]:
- code [ref=e265]: "--font-family-display"
- cell "26px" [ref=e266]
- cell "600" [ref=e267]
- cell "1.2" [ref=e268]
- cell "--nui-text-primary" [ref=e269]:
- code [ref=e270]: "--nui-text-primary"
- row "PullQuote Medium --font-family-display 20px 500 1.25 --nui-text-body" [ref=e271]:
- cell "PullQuote" [ref=e272]
- cell "Medium" [ref=e273]
- cell "--font-family-display" [ref=e274]:
- code [ref=e275]: "--font-family-display"
- cell "20px" [ref=e276]
- cell "500" [ref=e277]
- cell "1.25" [ref=e278]
- cell "--nui-text-body" [ref=e279]:
- code [ref=e280]: "--nui-text-body"
- row "Byline Standard --font-family-meta 12px 500 1.3 --nui-text-secondary" [ref=e281]:
- cell "Byline" [ref=e282]
- cell "Standard" [ref=e283]
- cell "--font-family-meta" [ref=e284]:
- code [ref=e285]: "--font-family-meta"
- cell "12px" [ref=e286]
- cell "500" [ref=e287]
- cell "1.3" [ref=e288]
- cell "--nui-text-secondary" [ref=e289]:
- code [ref=e290]: "--nui-text-secondary"
- row "Dateline Standard --font-family-meta 12px 600 1.3 --nui-text-primary" [ref=e291]:
- cell "Dateline" [ref=e292]
- cell "Standard" [ref=e293]
- cell "--font-family-meta" [ref=e294]:
- code [ref=e295]: "--font-family-meta"
- cell "12px" [ref=e296]
- cell "600" [ref=e297]
- cell "1.3" [ref=e298]
- cell "--nui-text-primary" [ref=e299]:
- code [ref=e300]: "--nui-text-primary"
- row "Caption Standard --font-family-body 13px 400 1.4 --nui-text-secondary" [ref=e301]:
- cell "Caption" [ref=e302]
- cell "Standard" [ref=e303]
- cell "--font-family-body" [ref=e304]:
- code [ref=e305]: "--font-family-body"
- cell "13px" [ref=e306]
- cell "400" [ref=e307]
- cell "1.4" [ref=e308]
- cell "--nui-text-secondary" [ref=e309]:
- code [ref=e310]: "--nui-text-secondary"
@@ -1,121 +0,0 @@
- generic [ref=e2]:
- complementary [ref=e3]:
- link "NewspaperUI" [ref=e4] [cursor=pointer]:
- /url: /
- generic [ref=e5]: Production Newspaper Components
- navigation [ref=e6]:
- list [ref=e7]:
- listitem [ref=e8]:
- link "概览 / 头版" [ref=e9] [cursor=pointer]:
- /url: /
- listitem [ref=e10]:
- link "栅格系统" [ref=e11] [cursor=pointer]:
- /url: /grid-system
- listitem [ref=e12]:
- link "布局组件" [ref=e13] [cursor=pointer]:
- /url: /components/article
- list [ref=e14]:
- listitem [ref=e15]:
- link "Masthead" [ref=e16] [cursor=pointer]:
- /url: /components/masthead
- listitem [ref=e17]:
- link "Article + Layer" [ref=e18] [cursor=pointer]:
- /url: /components/article
- listitem [ref=e19]:
- link "Rule 分隔线" [ref=e20] [cursor=pointer]:
- /url: /components/rule
- listitem [ref=e21]:
- link "文本组件" [ref=e22] [cursor=pointer]:
- /url: /text
- listitem [ref=e23]:
- link "媒体组件" [ref=e24] [cursor=pointer]:
- /url: /components/media
- listitem [ref=e25]:
- link "主题与颜色" [ref=e26] [cursor=pointer]:
- /url: /theme
- listitem [ref=e27]:
- link "示例" [ref=e28] [cursor=pointer]:
- /url: /examples/spanning
- list [ref=e29]:
- listitem [ref=e30]:
- link "跨栏布局" [ref=e31] [cursor=pointer]:
- /url: /examples/spanning
- listitem [ref=e32]:
- link "响应式" [ref=e33] [cursor=pointer]:
- /url: /examples/responsive
- listitem [ref=e34]:
- link "Blackletter 头版" [ref=e35] [cursor=pointer]:
- /url: /examples/blackletter-frontpage
- main [ref=e36]:
- article [ref=e39]:
- heading "主题与颜色" [level=1] [ref=e40]
- paragraph [ref=e41]: 设计哲学:暖灰系 + warm off-white。不使用纯黑(#000)也不使用纯白(#FFF), 把屏幕配色带回纸面的温度。
- heading "主题切换" [level=2] [ref=e42]
- paragraph [ref=e44]: 点击切换深色模式。深色基调采用暖深棕黑(#14110D)而非冷蓝黑,保持报纸的纸性触感。
- button "Dark Mode" [ref=e46] [cursor=pointer]
- heading "文字色 token" [level=2] [ref=e47]
- generic [ref=e48]:
- generic [ref=e51]:
- code [ref=e52]: "--nui-text-primary"
- generic [ref=e53]: "#1A1A1A · 标题、主文本"
- generic [ref=e56]:
- code [ref=e57]: "--nui-text-body"
- generic [ref=e58]: "#22201C · 正文"
- generic [ref=e61]:
- code [ref=e62]: "--nui-text-secondary"
- generic [ref=e63]: "#4A4742 · Subhead、次级"
- generic [ref=e66]:
- code [ref=e67]: "--nui-text-muted"
- generic [ref=e68]: "#6E6A63 · Caption、注释"
- generic [ref=e71]:
- code [ref=e72]: "--nui-text-quote"
- generic [ref=e73]: "#2E2A24 · Quote 主体"
- heading "背景与分隔线 token" [level=2] [ref=e74]
- generic [ref=e75]:
- generic [ref=e78]:
- code [ref=e79]: "--nui-bg-page"
- generic [ref=e80]: "#F7F4ED · Warm off-white 页面底"
- generic [ref=e83]:
- code [ref=e84]: "--nui-bg-surface"
- generic [ref=e85]: "#FBF9F4 · 次级面板背景"
- generic [ref=e88]:
- code [ref=e89]: "--nui-rule-hairline"
- generic [ref=e90]: "#C9C2B2 · 细线分隔"
- generic [ref=e93]:
- code [ref=e94]: "--nui-rule-decorative"
- generic [ref=e95]: "#1A1A1A · 强调线"
- generic [ref=e98]:
- code [ref=e99]: "--nui-highlight"
- generic [ref=e100]: "#F2E9C8 · 旧报纸黄"
- heading "强调色 token" [level=2] [ref=e101]
- generic [ref=e102]:
- generic [ref=e105]:
- code [ref=e106]: "--nui-accent-primary"
- generic [ref=e107]: "#7A1F1F · Brick red, Kicker / Masthead 强调"
- generic [ref=e110]:
- code [ref=e111]: "--nui-accent-ink-blue"
- generic [ref=e112]: "#1B2A4A · The Times 蓝"
- generic [ref=e115]:
- code [ref=e116]: "--nui-highlight"
- generic [ref=e117]: "#F2E9C8 · 高亮底色"
- heading "字体家族" [level=2] [ref=e118]
- paragraph [ref=e120]: 全部经典严肃风字体:Cormorant Garamond 承担报头与展示,Source Serif 4 贯穿正文与标题,Inter 处理 small-caps 元信息。Blackletter preset 通过 UnifrakturMaguntia 切入哥特报头。
- generic [ref=e121]:
- generic [ref=e122]:
- generic [ref=e123]: "--font-family-masthead · Cormorant Garamond — 报头"
- generic [ref=e124]: The Daily Chronicle
- generic [ref=e125]:
- generic [ref=e126]: "--font-family-blackletter · UnifrakturMaguntia — Blackletter preset"
- generic [ref=e127]: The Daily Chronicle
- generic [ref=e128]:
- generic [ref=e129]: "--font-family-display · Source Serif 4 — Display 大字头条"
- generic [ref=e130]: A Quiet Revolution
- generic [ref=e131]:
- generic [ref=e132]: "--font-family-headline · Source Serif 4 — Headline / Subhead"
- generic [ref=e133]: Whitehall confirms review
- generic [ref=e134]:
- generic [ref=e135]: "--font-family-body · Source Serif 4 — 正文"
- generic [ref=e136]: In Manchester, regional officials greeted the announcement.
- generic [ref=e137]:
- generic [ref=e138]: "--font-family-meta · Inter — small-caps 元信息"
- generic [ref=e139]: BY ALICE SMITH · LONDON
+642
View File
@@ -0,0 +1,642 @@
# NewspaperUI 交接文档
## 当前完成进度
### ✅ 已完成
1. **Stage 1**theme + utils 基础设施重写
2. **Stage 2**:18 个组件全部重写(Layout / Section / Article / Layer / Masthead / Rule / Headline / Subhead / Kicker / BodyText / Quote / Byline / Dateline / Caption / Image / Figure / Video / PullQuote
3. **Stage 3**:生产级头版 demoNYT + Blackletter
4. **Stage 4**9 个文档章节
5. **Stage 5**:验证(29/29 测试通过,Design Agent 复评 9/10
6. **同步 design.md**
7. **#17**:修复首页 + Blackletter 头版的空白问题(Briefs 增加新闻条目,BodyText 增加段落)
8. **#18**:修复 TypeScript lint warnings(重新 build 生成 .d.ts
9. **#16**Landing Page + Header 重构
- 新建 `packages/docs/components/Header.tsx`(全局 sticky Header,包含 Docs/Components/Themes/Blocks/GitHub 导航)
- 重写 `packages/docs/app/layout.tsx` 引入 Header
- 调整 `packages/docs/app/(docs)/layout.tsx` 适配 Header 高度(65px
- 调整 `packages/docs/components/Sidebar.tsx` sticky `top: 65px`
- **NYT 头版迁移到 `/examples/nyt-frontpage`**
- 新建 `packages/docs/app/page.tsx` 作为报纸风格 Landing Page,使用 Masthead + 7 个 demo 卡片垂直分布
### ⏳ 未完成
10. **#15**Blocks 页面 6 个完整 demo**核心剩余工作**)
11. **#13**Stage 6 — JSDoc + README
---
## 系统现状
### Monorepo 结构
```
/Users/joi-com/Desktop/space/newspaperui
├── packages/
│ ├── theme/ # CSS variables + 视觉权重表 + 字体 + 排版工具类
│ ├── utils/ # validateSpan / clampSpan / cx
│ ├── components/ # 18 个 React 组件
│ └── docs/ # Next.js 15 文档站
├── design.md # 设计规范(已同步修订版)
├── HANDOFF.md # 本文档
└── SKILL.md # 工作流方法论
```
### 工具链版本
- pnpm workspace + Turborepo
- React 18.3 / TypeScript 5.7 / Next.js 15.5 / Vite 5.4 / Tailwind 3.4
- Vitest + React Testing Library
### 关键命令
```bash
cd /Users/joi-com/Desktop/space/newspaperui
# 全量构建
pnpm build
# 测试
pnpm --filter @newspaperui/utils test # 11 tests
pnpm --filter @newspaperui/components test # 18 tests
# 开发服务器
pnpm --filter @newspaperui/docs dev # http://localhost:3000
```
### 已通过验证
- `pnpm build` 4 packages 全部通过,0 warning
- `pnpm test` 29/29 通过
- Playwright 实测 13 项视觉清单全 PASS
- Design Agent 复评 9.0/10
---
## 已实现的组件 API
### 布局组件
```typescript
import { Layout, Section, Article, Layer, Masthead, Rule } from '@newspaperui/components';
<Layout columns={24} maxWidth="1280px" padding="2rem" theme="light">
<Section columns={24} gap="2rem" breakable divider="bottom">
<Article span={8} breakable>
<Layer position="absolute" top="1rem" right="1rem" zIndex={10}>
<Masthead variant="classic" | "blackletter" | "modern" title kicker edition date price>
<Rule variant="hairline" | "double" | "thick" orientation="horizontal" | "vertical" span={N}>
```
### 文本组件
```typescript
import {
Headline, Subhead, Kicker, BodyText, Quote, Byline, Dateline, Caption,
} from '@newspaperui/components';
<Headline weight="High" | "Medium" | "Low" span={N} as="h1"|"h2"|"h3" align="left"|"center"|"right">
<Subhead weight="High" | "Medium" span={N}>
<Kicker>STANDARD SMALL CAPS RED</Kicker>
<BodyText weight="High"|"Medium"|"Low" columns={1|2|3|4} columnWidth="18em" columnFill="auto"|"balance" dropCap span={N}>
<p> 1em</p>
</BodyText>
<Quote variant="block" | "inline" weight="High" | "Medium">
<Byline>BY ALICE SMITH</Byline>
<Dateline>LONDON </Dateline>
<Caption credit="Photograph by ..."></Caption>
```
### 媒体组件
```typescript
<Image src alt span>
<Figure src alt caption credit span>
<Video src poster controls caption credit span>
<PullQuote weight="High" | "Medium" span spanAllColumns author align="left"|"center">
```
### Theme tokens
```css
/* CSS variables 已定义在 theme/src/variables.css */
--font-family-masthead, --font-family-blackletter, --font-family-display,
--font-family-headline, --font-family-body, --font-family-meta
--font-family-cjk-serif, --font-family-cjk-jp /* 新增:中日字体 */
--nui-bg-page #F7F4ED, --nui-bg-surface #FBF9F4
--nui-text-primary #1A1A1A, --nui-text-body #22201C, --nui-text-secondary, --nui-text-muted, --nui-text-quote
--nui-rule-hairline #C9C2B2, --nui-rule-decorative #1A1A1A
--nui-accent-primary #7A1F1F (NYT 朱红), --nui-accent-ink-blue #1B2A4A, --nui-highlight #F2E9C8
--nui-accent-cjk-red #CC2929 /* 新增:中文报纸朱红 */
/* 排版工具类(typography.css */
.nui-drop-cap, .nui-small-caps, .nui-paragraph-flow, .nui-osf, .nui-tnum,
.nui-hanging-punctuation, .nui-column-rule, .nui-avoid-break, .nui-span-all-columns,
.nui-masthead-rule-top, .nui-masthead-rule-bottom, .nui-rule-hairline
```
---
## 待实现:#15 Blocks 页面 6 个 demo
### 目标
参考 https://ui.shadcn.com/blocks,新建 `/blocks` 路由展示 6 个完整报纸 demo:
1. **中文头版**`/blocks/zh-frontpage`
2. **中文副刊专题**`/blocks/zh-feature`
3. **英文长篇专题**`/blocks/en-feature`)(NYT 头版已存在于 `/examples/nyt-frontpage`,本 Block 是不同类型)
4. **日语横排头版**`/blocks/jp-horizontal`
5. **日语竖排头版**`/blocks/jp-vertical`
6. (第 6 个根据需要自行决定,可以是中文政论或日语副刊)
### 用户已确认的设计决策
- **中文字体**Noto Serif SC(思源宋体),已加入 `theme/src/fonts.css``--font-family-cjk-serif` token
- **中文配色**:克制用红——仅报头 + Kicker 用 `--nui-accent-cjk-red #CC2929`,正文仍是暖灰系
- **中文排版**:紧凑、板块多、信息密度高
- **日语排版**:横排 + 竖排两种都做。竖排用 `writing-mode: vertical-rl`
- **日语字体**Noto Serif JP,已加入 token
### 用户反馈的核心痛点
> demo 应该要缜密,紧凑。当然如果有必要,也是可以有适当的留白。不过总体来说,传统时代,报纸区域是存土存金的。
**关键**:6 个 demo 都要充分利用空间,**不能有大片空白**,否则用户会再次不满意。
### Blocks 索引页
新建 `packages/docs/app/blocks/page.tsx`,参考 shadcn Blocks 页面结构:
```tsx
'use client';
import Link from 'next/link';
import { Layout, Section, Article, Headline, Subhead, Kicker } from '@newspaperui/components';
const blocks = [
{ href: '/blocks/zh-frontpage', lang: 'CHINESE · 中文', title: '人民周报 · 头版', preview: '/zh-frontpage-thumb.png' },
{ href: '/blocks/zh-feature', lang: 'CHINESE · 中文', title: '副刊 · 文化专题' },
{ href: '/blocks/en-feature', lang: 'ENGLISH', title: 'The Daily Chronicle · Long-form Feature' },
{ href: '/blocks/jp-horizontal', lang: 'JAPANESE · 日本語', title: '朝日新聞 · 横組み' },
{ href: '/blocks/jp-vertical', lang: 'JAPANESE · 日本語', title: '朝日新聞 · 縦組み(traditional' },
{ href: '/blocks/zh-editorial', lang: 'CHINESE · 中文', title: '社论 · 时事评论' }, // 第 6 个
];
export default function BlocksIndex() {
// 类似 Landing Page 的卡片网格,每个卡片链接到对应 block
}
```
**注意**:每个 Block 是 **完整一页**(不要嵌套在 Sidebar 内),所以 `/blocks``/blocks/[slug]` 都应该放在 `app/blocks/` 而不是 `app/(docs)/blocks/`,类似 `/examples/nyt-frontpage` 的处理方式。
### Block 1:中文头版 `/blocks/zh-frontpage`
完整代码模板(要求紧凑、信息密度高):
```tsx
import { Layout, Section, Article, Masthead, Rule, Headline, Subhead, Kicker, BodyText, Byline, Dateline, Figure, PullQuote } from '@newspaperui/components';
const cnStyle = { fontFamily: 'var(--font-family-cjk-serif)' };
const cnKickerStyle = { fontFamily: 'var(--font-family-cjk-serif)', color: 'var(--nui-accent-cjk-red)' };
export default function ZhFrontPage() {
return (
<Layout columns={24} maxWidth="1280px" padding="2rem 1.5rem" style={cnStyle}>
{/* 中文报头:朱红粗黑标题 + 双线 */}
<header style={{ textAlign: 'center', borderTop: '4px solid var(--nui-accent-cjk-red)', borderBottom: '1px solid var(--nui-rule-decorative)', paddingTop: '1rem', paddingBottom: '0.5rem' }}>
<div style={{ fontFamily: 'var(--font-family-meta)', fontSize: '11px', color: 'var(--nui-text-muted)', letterSpacing: '0.2em', marginBottom: '0.25rem' }}>RENMIN ZHOUBAO · </div>
<h1 style={{ ...cnStyle, fontSize: '88px', fontWeight: 900, color: 'var(--nui-accent-cjk-red)', margin: '0', letterSpacing: '0.1em', lineHeight: 1 }}></h1>
<div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '12px', color: 'var(--nui-text-secondary)', padding: '0.5rem 1rem', borderTop: '1px solid var(--nui-rule-hairline)', marginTop: '0.5rem', ...cnStyle }}>
<span> 2026 · 5891 </span>
<span>2026519 </span>
<span> 5 </span>
</div>
</header>
{/* 头条区:跨 24 列大标题 + 副标 + 双栏正文 */}
<Section columns={24} gap="1.5rem" style={{ marginTop: '1.5rem', paddingBottom: '1.5rem', borderBottom: '2px solid var(--nui-rule-decorative)' }}>
<Article span={24}>
<div style={{ ...cnKickerStyle, fontSize: '13px', fontWeight: 700, marginBottom: '0.5rem', textAlign: 'center' }}></div>
<h2 style={{ ...cnStyle, fontSize: '56px', fontWeight: 900, lineHeight: 1.1, color: 'var(--nui-text-primary)', textAlign: 'center', margin: '0' }}>
</h2>
<h3 style={{ ...cnStyle, fontSize: '24px', fontWeight: 500, lineHeight: 1.4, color: 'var(--nui-text-secondary)', textAlign: 'center', margin: '0.5rem 0 1rem 0' }}>
</h3>
<div style={{ textAlign: 'center', fontSize: '12px', color: 'var(--nui-text-muted)', ...cnStyle, marginBottom: '1rem' }}>
</div>
<BodyText weight="Medium" columns={3} dropCap style={cnStyle}>
<p> </p>
<p> 2040 2028 </p>
<p> 1.2% 0.7%</p>
<p></p>
<p>便</p>
<p></p>
</BodyText>
</Article>
</Section>
{/* 二条区:3 栏并列(要闻 / 经济 / 文化) */}
<Section columns={24} gap="1.5rem" style={{ marginTop: '1.5rem', paddingBottom: '1.5rem', borderBottom: '1px solid var(--nui-rule-decorative)' }}>
<Article span={8} style={{ borderRight: '1px solid var(--nui-rule-hairline)', paddingRight: '1rem' }}>
<div style={{ ...cnKickerStyle, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem' }}></div>
<h3 style={{ ...cnStyle, fontSize: '22px', fontWeight: 700, lineHeight: 1.3, color: 'var(--nui-text-primary)', margin: '0 0 0.5rem 0' }}></h3>
<BodyText weight="Low" style={cnStyle}>
<p></p>
<p></p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<h4 style={{ ...cnStyle, fontSize: '17px', fontWeight: 600, lineHeight: 1.3, margin: '0 0 0.4rem 0' }}>线</h4>
<BodyText weight="Low" style={cnStyle}>
<p>亿线线</p>
</BodyText>
</Article>
<Article span={8} style={{ borderRight: '1px solid var(--nui-rule-hairline)', paddingRight: '1rem' }}>
<div style={{ ...cnKickerStyle, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem' }}></div>
<h3 style={{ ...cnStyle, fontSize: '22px', fontWeight: 700, lineHeight: 1.3, color: 'var(--nui-text-primary)', margin: '0 0 0.5rem 0' }}> PMI </h3>
<BodyText weight="Low" style={cnStyle}>
<p> 52.4</p>
<p></p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<h4 style={{ ...cnStyle, fontSize: '17px', fontWeight: 600, lineHeight: 1.3, margin: '0 0 0.4rem 0' }}> 3.7%</h4>
<BodyText weight="Low" style={cnStyle}>
<p></p>
</BodyText>
</Article>
<Article span={8}>
<div style={{ ...cnKickerStyle, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem' }}> · </div>
<h3 style={{ ...cnStyle, fontSize: '22px', fontWeight: 700, lineHeight: 1.3, color: 'var(--nui-text-primary)', margin: '0 0 0.5rem 0' }}></h3>
<BodyText weight="Low" style={cnStyle}>
<p>殿</p>
<p></p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<h4 style={{ ...cnStyle, fontSize: '17px', fontWeight: 600, lineHeight: 1.3, margin: '0 0 0.4rem 0' }}></h4>
<BodyText weight="Low" style={cnStyle}>
<p> 18%</p>
</BodyText>
</Article>
</Section>
{/* 三条区:4 栏短讯 + 1 列要点提示 */}
<Section columns={24} gap="1rem" style={{ marginTop: '1.5rem' }}>
<Article span={6} style={{ background: 'var(--nui-bg-surface)', padding: '1rem', borderLeft: '3px solid var(--nui-accent-cjk-red)' }}>
<div style={{ ...cnKickerStyle, fontSize: '11px', fontWeight: 700, marginBottom: '0.5rem' }}></div>
<ul style={{ ...cnStyle, fontSize: '14px', lineHeight: 1.6, paddingLeft: '1.2em', margin: 0, color: 'var(--nui-text-body)' }}>
<li> · A2</li>
<li> · A4</li>
<li> · B1</li>
<li> · C3</li>
<li> · C5</li>
<li> · D2</li>
</ul>
</Article>
<Article span={18}>
<div style={{ ...cnKickerStyle, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem' }}> · </div>
<BodyText weight="Low" columns={3} style={cnStyle}>
<p><strong></strong> 8000 西</p>
<p><strong></strong> </p>
<p><strong></strong> 退</p>
<p><strong></strong> </p>
<p><strong></strong> </p>
<p><strong></strong> </p>
</BodyText>
</Article>
</Section>
</Layout>
);
}
```
### Block 2-6 实施要点
#### Block 2:中文副刊专题 `/blocks/zh-feature`
- 风格:人物访谈 / 文化评论
- 结构:大幅人物图片(左侧 12 列)+ 长篇访谈正文(右侧 12 列双栏)
- 报头较小,强调内容深度
- 多用 Quote 组件呈现采访对话
- 字体仍是 Noto Serif SC,配色克制(仅小标签用朱红)
#### Block 3:英文长篇专题 `/blocks/en-feature`
- The Atlantic / The New Yorker 风格的 long-form
- 单栏阅读模式(窄栏宽 ≤ 700px)
- 大幅 hero image,下方居中标题 + drop cap
- 多个 PullQuote 穿插在正文中
- 用 Source Serif 4 + 经典严肃风配色
#### Block 4:日语横排头版 `/blocks/jp-horizontal`
- 朝日新闻 Web 版风格
- 横排,使用 Noto Serif JP
- 24 列栅格保持
- Masthead 用 Noto Serif JP 大字
- 关键:日语 Headline 没有英文 small capsKicker 改用普通粗体或方括号【速報】
- 段落首行不缩进(日语传统)
```tsx
const jpStyle = { fontFamily: 'var(--font-family-cjk-jp)' };
const jpKicker = { fontFamily: 'var(--font-family-cjk-jp)', color: 'var(--nui-accent-cjk-red)', fontSize: '13px', fontWeight: 700 };
// 日语 BodyText 不要用 dropCap(日文不适合)
// 不要用 nui-paragraph-flow 的 text-indent: 1em(日语传统首行不缩进)
// 改用普通 div 包 p
```
#### Block 5:日语竖排头版 `/blocks/jp-vertical`
- 关键:`writing-mode: vertical-rl;`
- Layout 容器需要 `height` 而不只是 `width`
- 不使用 BodyText 的 columns propCSS columns 与 vertical writing-mode 不兼容),改用多个独立 BodyText 块横向排列模拟栏
- 文字方向、border 方向都翻转
- 这是最难的一个,建议简化结构:报头 + 1 个头条 + 3-4 个并列竖排栏
```tsx
<div style={{
writingMode: 'vertical-rl',
height: '90vh',
fontFamily: 'var(--font-family-cjk-jp)',
display: 'flex',
flexDirection: 'row-reverse',
gap: '1.5rem',
padding: '2rem',
}}>
{/* 每个区块都是竖排 */}
</div>
```
#### Block 6:第 6 个 demo
建议做 **中文社论 / 时事评论**`/blocks/zh-editorial`):
- 双栏对开(左侧主社论 + 右侧专家评论)
- 引用密集,多用 Quote variant="block"
- 末尾署名
或换成 **韩文 / 阿拉伯文报纸** 都可以(用户没指定,自由发挥但要保证质量)。
### 实施建议
1. **拆 3 个 agent,每个做 2 个 demo**(每个 prompt 控制在 8000 token 以内)
- Agent ABlock 1 中文头版 + Block 2 中文副刊
- Agent BBlock 3 英文专题 + Block 6 中文社论
- Agent CBlock 4 日语横排 + Block 5 日语竖排
2. **每个 demo 完成后跑 `pnpm --filter @newspaperui/docs build`** 验证
3. **建立 `/blocks` 索引页**:参考 Landing Page 的卡片网格结构
4. **关键约束**:每个 demo 必须填满,不能有大片空白。栏数多、信息密度高、紧凑
### 路由结构最终目标
```
app/
page.tsx # Landing Page (报纸风格)
layout.tsx # 根 layout (含 Header)
globals.css
blocks/ # NEW
page.tsx # Blocks 索引
zh-frontpage/page.tsx # NEW
zh-feature/page.tsx # NEW
en-feature/page.tsx # NEW
jp-horizontal/page.tsx # NEW
jp-vertical/page.tsx # NEW
zh-editorial/page.tsx # NEW
examples/
nyt-frontpage/page.tsx # 已有:NYT 头版(迁移自原首页)
blackletter-frontpage/page.tsx # 已有:FAZ 头版
(docs)/
layout.tsx # 已有:Sidebar + Header 余高
grid-system/page.tsx
text/page.tsx
theme/page.tsx
components/{article,masthead,media,rule}/page.tsx
examples/{spanning,responsive}/page.tsx
```
---
## 待实现:#13 Stage 6 — JSDoc + README
### JSDoc 补全(18 个组件)
`packages/components/src/{layout,text,media}/*.tsx` 的每个组件补 JSDoc
```typescript
/**
* BodyText — 报纸正文组件
*
* 核心特性:
* - 多栏文字流:`columns={2|3|4}` 启用 CSS multi-column
* - 首字下沉:`dropCap` 触发 ::first-letter 4.2em float
* - 段落规则:默认开启段间无空行 + 首行缩进 1em + old-style figures + 悬挂引号
*
* @example
* <BodyText weight="High" columns={3} dropCap>
* <p>第一段...</p>
* <p>第二段(首行自动缩进 1em...</p>
* </BodyText>
*/
export const BodyText: React.FC<BodyTextProps> = ...
```
每个组件至少包含:
- 一句话描述
- 核心 prop 说明
- 一个使用示例
### README 更新
更新根目录 `README.md`
```markdown
# NewspaperUI
> Production-grade newspaper layout component library for the modern web.
参考 InDesign 与经典严肃风排版传统(NYT / The Times / FAZ),基于 24 列栅格、CSS Grid + Multi-column 双层机制。
## Quick Start
```bash
pnpm add @newspaperui/components @newspaperui/theme
```
```tsx
import '@newspaperui/theme';
import { Layout, Section, Article, Masthead, BodyText } from '@newspaperui/components';
<Layout columns={24}>
<Masthead variant="classic" title="The Daily Chronicle" date="..." />
<Section columns={24}>
<Article span={14}>
<BodyText columns={3} dropCap>...</BodyText>
</Article>
</Section>
</Layout>
```
## Packages
- `@newspaperui/theme` — CSS variables, visual weights, typography utilities
- `@newspaperui/utils` — Grid validation utilities
- `@newspaperui/components` — 18 React components
- `@newspaperui/docs` — Next.js documentation site
## Components (18)
### Layout
- Layout, Section, Article, Layer, Masthead, Rule
### Text
- Headline, Subhead, Kicker, BodyText, Quote, Byline, Dateline, Caption
### Media
- Image, Figure, Video, PullQuote
## Visual Design
- Typography: Cormorant Garamond (masthead), Source Serif 4 (display/body), Inter (meta), UnifrakturMaguntia (blackletter), Noto Serif SC/JP (CJK)
- Colors: warm off-white #F7F4ED background, #1A1A1A primary text, #7A1F1F NYT-style accent
- Layout: CSS Grid + Multi-column hybrid
## Development
```bash
pnpm install
pnpm build # build all packages
pnpm test # 29 tests
pnpm --filter @newspaperui/docs dev # http://localhost:3000
```
See `design.md` for full design specification.
See `SKILL.md` for the agent-driven workflow methodology used to build this project.
```
---
## 已知问题与陷阱
1. **'use client' 指令**:所有用了 `createContext` / `useState` 的组件必须有 `'use client'`,且页面 import 它们时如果整个页面调用了 React 客户端 API,页面也要加 `'use client'`。已知页面:所有有 `<Link>` 或 client-side state 的页面已加。
2. **Vite dts 偶尔不生成**:如果 components 包构建后 `dist/index.d.ts` 缺失,重跑 `pnpm --filter @newspaperui/components build` 就好。
3. **TypeScript strict mode**`noUnusedLocals` 严格,未使用的 import 会报错。新建 page 时记得清理。
4. **CSS columns 与 vertical-rl 不兼容**:日语竖排 demo 不能用 BodyText 的 columns prop。
5. **Sidebar 路径**`(docs)/layout.tsx` import Sidebar 用 `'../../components/Sidebar'`(路由组括号不算路径层级)。
6. **Theme 包导出**`packages/theme/package.json` 的 `exports` 字段需要 `./dist/style.css`(已加),否则 docs 包 import 会报 ERR_PACKAGE_PATH_NOT_EXPORTED。
7. **Next 15 的 metadata 会让 client component 失败**root layout 中 `export const metadata` 必须在 server component 文件中。client component 用 `'use client'` 后不能 export metadata。
---
## 验收清单(让接手 AI 验证完成度)
执行以下命令,全部通过即视为完成:
```bash
cd /Users/joi-com/Desktop/space/newspaperui
# 1. 全量构建
pnpm build
# 期望:4 packages 全部 successful
# 2. 测试
pnpm --filter @newspaperui/utils test # 11 tests pass
pnpm --filter @newspaperui/components test # 18 tests pass
# 3. 启动 dev server
pnpm --filter @newspaperui/docs dev
# 浏览器访问验证:
# http://localhost:3000 Landing Page
# http://localhost:3000/blocks Blocks 索引
# http://localhost:3000/blocks/zh-frontpage 中文头版
# http://localhost:3000/blocks/zh-feature 中文副刊
# http://localhost:3000/blocks/en-feature 英文专题
# http://localhost:3000/blocks/jp-horizontal 日语横排
# http://localhost:3000/blocks/jp-vertical 日语竖排(writing-mode: vertical-rl
# http://localhost:3000/blocks/zh-editorial 第 6 个 demo
# http://localhost:3000/examples/nyt-frontpage NYT 头版
# http://localhost:3000/examples/blackletter-frontpage FAZ 头版
# http://localhost:3000/grid-system, /text, /theme 文档章节
# 4. 视觉检查
# - 6 个 Blocks demo 不能有大片空白
# - 中文用 Noto Serif SC,仅报头 + Kicker 用朱红
# - 日语竖排 writing-mode: vertical-rl 真实生效
# - Header 在所有页面 sticky 顶部
# - Sidebar 仅在 (docs) 路由组下显示
```
---
## 文件位置速查
```
/Users/joi-com/Desktop/space/newspaperui/
├── HANDOFF.md 本文档
├── SKILL.md 工作流方法论
├── design.md 设计规范(修订版)
├── packages/
│ ├── theme/src/
│ │ ├── fonts.css 含 Noto Serif SC/JP 字体引入
│ │ ├── variables.css --font-family-cjk-serif/-jp、--nui-accent-cjk-red 已加
│ │ ├── visual-weights.ts 18 档视觉权重映射
│ │ ├── typography.css 排版工具类
│ │ └── tailwind.config.js
│ ├── utils/src/
│ │ ├── grid.ts validateSpan / clampSpan
│ │ ├── cx.ts 类名合并
│ │ └── index.ts
│ ├── components/src/
│ │ ├── layout/ Layout/Section/Article/Layer/Masthead/Rule
│ │ ├── text/ Headline/Subhead/Kicker/BodyText/Quote/Byline/Dateline/Caption
│ │ ├── media/ Image/Figure/Video/PullQuote
│ │ └── index.ts
│ └── docs/
│ ├── app/
│ │ ├── page.tsx Landing Page
│ │ ├── layout.tsx 含 <Header />
│ │ ├── globals.css
│ │ ├── (docs)/ Sidebar 包裹的章节
│ │ │ ├── layout.tsx
│ │ │ ├── grid-system/page.tsx
│ │ │ ├── text/page.tsx
│ │ │ ├── theme/page.tsx
│ │ │ ├── components/{article,masthead,media,rule}/page.tsx
│ │ │ └── examples/{spanning,responsive}/page.tsx
│ │ └── examples/ 全宽页面(不在 Sidebar 内)
│ │ ├── nyt-frontpage/page.tsx NYT 头版(已迁移)
│ │ └── blackletter-frontpage/page.tsx FAZ 头版
│ └── components/
│ ├── Header.tsx 全局 sticky 顶部导航
│ ├── Sidebar.tsx sticky top: 65px
│ ├── Demo.tsx, CodeBlock.tsx, PropsTable.tsx, ThemeToggle.tsx
```
---
## 接手 AI 的工作步骤建议
1. **读这个文档全文** + `design.md` + `SKILL.md`
2. **跑 `pnpm build` + `pnpm dev`** 确认现状
3. **访问 Landing Page http://localhost:3000** 看到当前布局
4. **从 #15 Block 1 中文头版开始**,按上面的代码模板落地
5. **每完成 1 个 demo 跑一次 build** 确认无 error
6. **用浏览器肉眼或 Playwright 截图验收**:是否紧凑、无空白
7. **6 个 Blocks 完成后做 #13**JSDoc + README
8. **最后跑一次 Design Agent 复评**(参考 SKILL.md 里的方法)
预计剩余工作量:
- #15 Blocks6 个 demo + 索引页):4-6 小时(拆 3 个 agent 并行可压缩到 1.5 小时)
- #13 JSDoc + README1 小时
- 总计:约 2-3 小时(用 agent 并行)
+88 -54
View File
@@ -1,81 +1,115 @@
# NewspaperUI
A newspaper-style UI component library built with React, TypeScript, and Tailwind CSS.
> Production-grade newspaper layout component library for the modern web.
## Project Structure
参考 InDesign 与经典严肃风排版传统(NYT / The Times / FAZ),基于 24 列栅格、CSS Grid + Multi-column 双层机制。支持中文、英文、日语多语言报纸排版。
```
newspaperui/
├── packages/
│ ├── components/ # React components
│ ├── theme/ # CSS variables and Tailwind tokens
│ ├── utils/ # Utility functions
│ └── docs/ # Documentation site (Next.js)
├── turbo.json # Turborepo configuration
├── pnpm-workspace.yaml # pnpm workspace configuration
└── package.json # Root package.json
```
## Getting Started
### Prerequisites
- Node.js >= 18.0.0
- pnpm >= 9.0.0
### Installation
## Quick Start
```bash
pnpm install
pnpm add @newspaperui/components @newspaperui/theme
```
### Development
```tsx
import '@newspaperui/theme';
import { Layout, Section, Article, Masthead, BodyText } from '@newspaperui/components';
```bash
# Run all packages in dev mode
pnpm dev
# Build all packages
pnpm build
# Run linting
pnpm lint
# Run tests
pnpm test
<Layout columns={24}>
<Masthead variant="classic" title="The Daily Chronicle" date="May 19, 2026" />
<Section columns={24}>
<Article span={14}>
<BodyText columns={3} dropCap>
<p>Multi-column text flow with drop cap...</p>
</BodyText>
</Article>
</Section>
</Layout>
```
## Packages
### @newspaperui/components
| Package | Description |
|---------|-------------|
| `@newspaperui/theme` | CSS variables, visual weights, typography utilities, Google Fonts |
| `@newspaperui/utils` | Grid validation (`validateSpan`, `clampSpan`, `cx`) |
| `@newspaperui/components` | 18 React components |
| `@newspaperui/docs` | Next.js documentation site with live demos |
React components for building newspaper-style interfaces.
## Components (18)
**Dependencies**: `@newspaperui/theme`, `@newspaperui/utils`
### Layout
`Layout` · `Section` · `Article` · `Layer` · `Masthead` · `Rule`
### @newspaperui/theme
### Text
`Headline` · `Subhead` · `Kicker` · `BodyText` · `Quote` · `Byline` · `Dateline` · `Caption`
CSS variables and Tailwind tokens for consistent theming.
### Media
`Image` · `Figure` · `Video` · `PullQuote`
### @newspaperui/utils
## Key Features
Utility functions used across the component library.
- **24-column CSS Grid** — unified `grid-column: span N` mechanism
- **CSS Multi-column flow** — real newspaper text reflow with `column-rule` hairlines
- **Drop cap** — `::first-letter` float, 4.2em display serif
- **True small caps** — OpenType `font-variant-caps: small-caps` (not `text-transform`)
- **Old-style figures** — `font-variant-numeric: oldstyle-nums` for body text
- **Visual weight system** — data-driven typography from a single `visualWeights` mapping
- **Warm off-white palette** — `#F7F4ED` background, warm grays, no pure black/white
- **Dark mode** — `[data-theme="dark"]` with warm deep brown-black
- **Multi-language** — Chinese (Noto Serif SC), Japanese (Noto Serif JP), English (Source Serif 4), German (UnifrakturMaguntia)
### @newspaperui/docs
## Typography
Documentation site built with Next.js 14+ App Router.
| Role | Font | Usage |
|------|------|-------|
| Masthead | Cormorant Garamond | Newspaper title |
| Blackletter | UnifrakturMaguntia | German-style masthead preset |
| Display / Headline / Body | Source Serif 4 | Main serif family (optical size) |
| Meta (Byline, Kicker, Caption) | Inter | Sans-serif small caps |
| Chinese | Noto Serif SC | 中文报纸 |
| Japanese | Noto Serif JP | 日本語新聞 |
**Dependencies**: `@newspaperui/components`
## Live Demos
## Tech Stack
Run the documentation site:
- **React** 18+
- **TypeScript** 5+
- **Tailwind CSS** 3+
- **Next.js** 14+ (docs only)
- **Vite** 5+ (build tool for components/theme/utils)
- **Turborepo** (monorepo orchestration)
- **pnpm** (package manager)
```bash
pnpm install
pnpm --filter @newspaperui/docs dev
# → http://localhost:3000
```
### Available Pages
| Route | Description |
|-------|-------------|
| `/` | Landing page with demo showcase |
| `/blocks` | 6 production-grade newspaper blocks |
| `/blocks/zh-frontpage` | Chinese front page (人民周报) |
| `/blocks/zh-feature` | Chinese feature article (副刊) |
| `/blocks/en-feature` | English long-form (The Atlantic style) |
| `/blocks/jp-horizontal` | Japanese horizontal (朝日新聞) |
| `/blocks/jp-vertical` | Japanese vertical (`writing-mode: vertical-rl`) |
| `/blocks/zh-editorial` | Chinese editorial (社论) |
| `/examples/nyt-frontpage` | NYT-style English front page |
| `/examples/blackletter-frontpage` | German blackletter front page |
| `/grid-system` | Grid system documentation |
| `/text` | Text components + visual weight table |
| `/theme` | Theme system + dark mode toggle |
| `/components/*` | Component API docs |
## Development
```bash
pnpm install
pnpm build # Build all 4 packages
pnpm test # 29 tests (utils 11 + components 18)
pnpm --filter @newspaperui/docs dev # Dev server
```
## Design Specification
See [`design.md`](./design.md) for the full design specification including visual weight mapping table, color system, and typography rules.
## License
+15 -13
View File
@@ -180,17 +180,19 @@ Dark(暖深棕黑,非冷黑):
- 技术栈: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
1. `/` 首页 = 报纸风格 Landing PageMasthead + 介绍 + 多语言 demo 列表 + 设计哲学/技术栈
2. `/examples/nyt-frontpage` NYT 派完整报纸头版(Masthead + Briefs + Lead Story 含 hero image + 3 栏 BodyText + drop cap + PullQuote + Secondary + Third Story 4 栏)
3. `/grid-system` 栅格系统与 Layout/Section/Article/Layer 说明
4. `/components/masthead` Masthead 三种 variant 对照
5. `/components/article` Article + Layer 跨栏与浮动 demo
6. `/components/rule` Rule 三种 variant 对照
7. `/components/media` Image / Figure / Video / PullQuote
8. `/text` 文本组件全集 + 视觉权重映射表(实时渲染)+ 多栏文字流 demo + drop cap demo
9. `/theme` CSS variables 列表 + color swatch + 暗色主题切换按钮
10. `/examples/spanning` 跨栏布局示例
11. `/examples/responsive` 响应式布局展示
12. `/examples/blackletter-frontpage` The Times / FAZ 派哥特体头版 preset
- 全局导航:顶部 HeaderDocs / Components / Themes / Blocks / GitHub),文档区域内嵌 Sidebar 二级导航
---
@@ -201,14 +203,14 @@ Dark(暖深棕黑,非冷黑):
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
6. 构建文档网站,首页为报纸风格 Landing Page 汇聚多语言 demo`/examples/nyt-frontpage` 作为 NYT 派生产级标杆,章节页用真实组件 demo
7. 验收:视觉与传统报纸排版(NYT / The Times / FAZ)一致;自动化构建/测试通过;Design Agent 复评 ≥ 9/10
---
## 10. 验收标准
打开首页应满足:
打开 `/examples/nyt-frontpage` 应满足:
- Masthead 是 Cormorant Garamond 衬线 + 双线分隔
- 头条字号 ≥ 48px、line-height ≤ 1.15、字重 600
- 头条下方 BodyText 真分 3 栏,栏间有 1px 暖灰 hairline
@@ -11,6 +11,19 @@ export interface ArticleProps {
children: ReactNode;
}
/**
* Article — 文章块,grid-column span 跨栏
*
* - 通过 span 属性控制在 Section 栅格中占据的列数
* - 自动 clamp 到父 Section 的最大列数
* - 支持 print 分页控制(breakable
*
* @example
* <Article span={14} breakable={false}>
* <Headline weight="High">Breaking News</Headline>
* <BodyText columns={2}>...</BodyText>
* </Article>
*/
export const Article: React.FC<ArticleProps> = ({
span, breakable = true, className, style, children,
}) => {
+12
View File
@@ -13,6 +13,18 @@ export interface LayerProps {
children: ReactNode;
}
/**
* Layer — 浮动层(absolute/fixed/sticky
*
* - 支持 absolute、fixed、sticky 三种定位模式
* - 可精确控制 top/left/right/bottom/zIndex
* - 用于叠加装饰元素、浮动导航或 sticky 侧栏
*
* @example
* <Layer position="sticky" top={0} zIndex={100}>
* <nav>Sticky Navigation</nav>
* </Layer>
*/
export const Layer: React.FC<LayerProps> = ({
position = 'absolute', top, left, right, bottom, zIndex,
className, style, children,
+12
View File
@@ -15,6 +15,18 @@ interface LayoutContextValue { columns: number; }
const LayoutContext = createContext<LayoutContextValue>({ columns: 24 });
export const useLayout = () => useContext(LayoutContext);
/**
* Layout — 顶层容器,提供 24 列栅格 Context
*
* - 通过 LayoutContext 向子组件广播 columns 数量
* - 支持 light/dark 主题切换(data-theme 属性)
* - 居中布局,可配置 maxWidth 和 padding
*
* @example
* <Layout columns={24} theme="light" maxWidth="1280px">
* <Section columns={24}>...</Section>
* </Layout>
*/
export const Layout: React.FC<LayoutProps> = ({
columns = 24, maxWidth = '1280px', padding = 'var(--nui-space-6)',
theme, className, style, children,
@@ -12,6 +12,21 @@ export interface MastheadProps {
className?: string;
}
/**
* Masthead — 报头(classic/blackletter/modern 三种 variant
*
* - classic: Cormorant Garamond 居中衬线风格
* - blackletter: UnifrakturMaguntia 德式哥特体
* - modern: 左对齐现代大标题风格
*
* @example
* <Masthead
* variant="classic"
* title="The Daily Chronicle"
* date="May 19, 2026"
* edition="Vol. CLII No. 42"
* />
*/
export const Masthead: React.FC<MastheadProps> = ({
title, kicker, edition, date, price, variant = 'classic', className,
}) => {
+10
View File
@@ -10,6 +10,16 @@ export interface RuleProps {
style?: CSSProperties;
}
/**
* Rule — 分隔线(hairline/double/thick
*
* - 支持水平和垂直方向
* - hairline: 1px 细线;double: 双线装饰;thick: 3px 粗线
* - 水平模式下可通过 span 控制跨栏宽度
*
* @example
* <Rule variant="double" orientation="horizontal" />
*/
export const Rule: React.FC<RuleProps> = ({
variant = 'hairline', orientation = 'horizontal', span, className, style,
}) => {
@@ -17,6 +17,19 @@ interface SectionContextValue { columns: number; }
const SectionContext = createContext<SectionContextValue>({ columns: 24 });
export const useSection = () => useContext(SectionContext);
/**
* Section — CSS Grid 栅格区域
*
* - 内部创建独立的 grid 容器,列数受父 Layout 约束
* - 支持 hairline divider 分隔线(top/bottom/both
* - 通过 SectionContext 向子 Article 广播当前列数
*
* @example
* <Section columns={24} gap="var(--nui-gutter)" divider="bottom">
* <Article span={14}>...</Article>
* <Article span={10}>...</Article>
* </Section>
*/
export const Section: React.FC<SectionProps> = ({
columns, gap = 'var(--nui-gutter)', breakable = true, divider = 'none',
className, style, children,
+16
View File
@@ -14,6 +14,22 @@ export interface FigureProps {
style?: CSSProperties;
}
/**
* Figure — 图文组合(img + Caption
*
* - 将图片与 Caption 组合为语义化 figure 元素
* - 支持 caption 文字说明和 credit 来源标注
* - 自动避免 print 分页断开(break-inside: avoid
*
* @example
* <Figure
* src="/photo.jpg"
* alt="City skyline"
* caption="Downtown at dusk"
* credit="Photo by John"
* span={10}
* />
*/
export const Figure: React.FC<FigureProps> = ({
src, alt, caption, credit, span, className, style,
}) => {
+10
View File
@@ -11,6 +11,16 @@ export interface ImageProps {
style?: CSSProperties;
}
/**
* Image — 图片
*
* - 响应式全宽图片,自动适配栅格列宽
* - 通过 span 控制在 Section 中占据的列数
* - 必须提供 alt 属性以确保无障碍访问
*
* @example
* <Image src="/photo.jpg" alt="City skyline" span={12} />
*/
export const Image: React.FC<ImageProps> = ({ src, alt, span, className, style }) => {
const section = useSection();
const cols = span ? clampSpan(span, section.columns) : undefined;
@@ -15,6 +15,18 @@ export interface PullQuoteProps {
children: ReactNode;
}
/**
* PullQuote — 拉引(上下双 hairline + Display 字体)
*
* - 上下 hairline 边框包裹,Display 字体突出引文
* - 支持 spanAllColumns 跨越多栏 BodyText 的所有列
* - 可附带 author 署名(small-caps 样式)
*
* @example
* <PullQuote weight="High" author="Jane Doe" align="center">
* "Design is not just what it looks like — design is how it works."
* </PullQuote>
*/
export const PullQuote: React.FC<PullQuoteProps> = ({
weight = 'High', span, spanAllColumns = false, author, align = 'left',
className, style, children,
+16
View File
@@ -15,6 +15,22 @@ export interface VideoProps {
style?: CSSProperties;
}
/**
* Video — 视频
*
* - 响应式视频播放器,支持 poster 封面图
* - 可附带 caption 说明和 credit 来源
* - 自动避免 print 分页断开
*
* @example
* <Video
* src="/clip.mp4"
* poster="/poster.jpg"
* caption="Interview footage"
* credit="Video by Reuters"
* span={14}
* />
*/
export const Video: React.FC<VideoProps> = ({
src, poster, caption, credit, span, controls = true, className, style,
}) => {
+17 -4
View File
@@ -8,17 +8,30 @@ export interface BodyTextProps {
weight?: 'High' | 'Medium' | 'Low';
span?: number;
columns?: 1 | 2 | 3 | 4; // 多栏文字流
columnWidth?: string; // 默认 '18em'
columnFill?: 'auto' | 'balance';
columnWidth?: string; // 可选:显式指定每栏目标宽度(与 columnCount 配合)
columnFill?: 'auto' | 'balance'; // 默认 balance(平均分布到各栏)
dropCap?: boolean;
className?: string;
style?: CSSProperties;
children: ReactNode;
}
/**
* BodyText — 正文(核心:columns 多栏文字流 + dropCap 首字下沉)
*
* - CSS Multi-column 实现真实报纸多栏排版(1-4 栏)
* - dropCap 启用 ::first-letter 首字下沉效果
* - 自动应用 old-style figures、hanging punctuation、column-rule hairline
* - columnFill 默认 'balance',浏览器自动均分内容到各栏(无需指定 height)
*
* @example
* <BodyText columns={3} dropCap>
* <p>The story begins with a dramatic opening paragraph...</p>
* </BodyText>
*/
export const BodyText: React.FC<BodyTextProps> = ({
weight = 'Medium', span, columns = 1, columnWidth = '18em',
columnFill = 'auto', dropCap = false,
weight = 'Medium', span, columns = 1, columnWidth,
columnFill = 'balance', dropCap = false,
className, style, children,
}) => {
const section = useSection();
+10
View File
@@ -9,6 +9,16 @@ export interface BylineProps {
children: ReactNode; // e.g. "BY ALICE SMITH"
}
/**
* Byline — 署名(Inter small-caps
*
* - Inter 字体 + OpenType small-caps 特性
* - 用于文章作者署名,通常置于标题下方
* - 字号、字重、间距由 visualWeights 数据驱动
*
* @example
* <Byline>BY ALICE SMITH</Byline>
*/
export const Byline: React.FC<BylineProps> = ({ className, style, children }) => {
const config = visualWeights.Byline.Standard!;
return (
+12
View File
@@ -10,6 +10,18 @@ export interface CaptionProps {
children: ReactNode;
}
/**
* Caption — 图片说明(italic + credit small-caps
*
* - 主体文字为 italic 衬线,描述图片内容
* - credit 部分以 small-caps 显示摄影师/来源信息
* - 渲染为 figcaption,语义化配合 Figure 使用
*
* @example
* <Caption credit="Photograph by Jane Doe">
* A view of the city skyline at sunset.
* </Caption>
*/
export const Caption: React.FC<CaptionProps> = ({ credit, className, style, children }) => {
const config = visualWeights.Caption.Standard!;
return (
+12
View File
@@ -9,6 +9,18 @@ export interface DatelineProps {
children: ReactNode; // e.g. "LONDON —"
}
/**
* Dateline — 发稿地(Inter small-caps
*
* - Inter 字体 + OpenType small-caps,标注新闻发稿地
* - 通常置于正文首段开头,如 "LONDON —"
* - 渲染为 inline span,可嵌入 BodyText 内
*
* @example
* <BodyText>
* <Dateline>WASHINGTON —</Dateline> The president announced...
* </BodyText>
*/
export const Dateline: React.FC<DatelineProps> = ({ className, style, children }) => {
const config = visualWeights.Dateline.Standard!;
return (
+12
View File
@@ -18,6 +18,18 @@ export interface HeadlineProps {
children: ReactNode;
}
/**
* Headline — 标题(High/Medium/Low 三档,自动映射 h1/h2/h3
*
* - 根据 weight 自动选择语义标签(h1/h2/h3),也可通过 as 覆盖
* - 字号、行高、字重由 visualWeights 数据驱动
* - 支持 text-wrap: balance 自动平衡换行
*
* @example
* <Headline weight="High" span={14}>
* Breaking: Major Event Unfolds
* </Headline>
*/
export const Headline: React.FC<HeadlineProps> = ({
weight = 'High', span, as, align, className, style, children,
}) => {
+11
View File
@@ -9,6 +9,17 @@ export interface KickerProps {
children: ReactNode;
}
/**
* Kicker — 小帽体标签(朱红 accent)
*
* - Inter small-caps 字体,朱红色 accent 色
* - 用于标题上方的栏目标签或分类标识
* - 字号和间距由 visualWeights 数据驱动
*
* @example
* <Kicker>EXCLUSIVE</Kicker>
* <Headline weight="High">Major Discovery</Headline>
*/
export const Kicker: React.FC<KickerProps> = ({ className, style, children }) => {
const config = visualWeights.Kicker.Standard!;
return (
+12
View File
@@ -14,6 +14,18 @@ export interface QuoteProps {
children: ReactNode;
}
/**
* Quote — 引用(block 左缩进 / inline italic
*
* - block 模式:渲染为 blockquote,支持 cite 属性和 span 跨栏
* - inline 模式:渲染为 em 标签,适合行内引用
* - 字号和样式由 visualWeights 数据驱动
*
* @example
* <Quote variant="block" weight="High" cite="https://source.com">
* "The truth is rarely pure and never simple."
* </Quote>
*/
export const Quote: React.FC<QuoteProps> = ({
variant = 'block', weight = 'Medium', span, cite, className, style, children,
}) => {
+12
View File
@@ -13,6 +13,18 @@ export interface SubheadProps {
children: ReactNode;
}
/**
* Subhead — 副标题(italic 衬线)
*
* - 默认 italic 衬线风格,视觉层级低于 Headline
* - 支持 High/Medium 两档 weight
* - 可通过 as 指定渲染标签(h2/h3/h4/p
*
* @example
* <Subhead weight="Medium" span={14}>
* A deeper look into the story behind the headlines
* </Subhead>
*/
export const Subhead: React.FC<SubheadProps> = ({
weight = 'Medium', span, as = 'p', className, style, children,
}) => {
+1 -1
View File
@@ -2,7 +2,7 @@ import { Sidebar } from '../../components/Sidebar';
export default function DocsLayout({ children }: { children: React.ReactNode }) {
return (
<div style={{ display: 'flex', minHeight: '100vh' }}>
<div style={{ display: 'flex', minHeight: 'calc(100vh - 65px)' }}>
<Sidebar />
<main
style={{
@@ -0,0 +1,77 @@
'use client';
import { Layout, Section, Article, Rule, Headline, Subhead, Kicker, BodyText, Byline, Dateline, Figure, PullQuote } from '@newspaperui/components';
export default function EnFeature() {
return (
<Layout columns={24} maxWidth="750px" padding="3rem 2rem 4rem">
<Section columns={24}>
<Article span={24}>
<div style={{ textAlign: 'center', marginBottom: '3rem' }}>
<Kicker>Long-form · Investigation</Kicker>
<Headline weight="High" align="center" style={{ marginTop: '0.5rem' }}>
The Quiet Collapse of the Middle Shelf
</Headline>
<Subhead weight="High" style={{ textAlign: 'center', marginTop: '0.5rem' }}>
How a generation of mid-list authors lost their publishers, their readers, and their livelihoods while bestseller lists grew longer than ever.
</Subhead>
<div style={{ marginTop: '1.5rem' }}>
<Byline>By Catherine Ashworth</Byline>
</div>
<div style={{ fontFamily: 'var(--font-family-meta)', fontSize: '12px', color: 'var(--nui-text-muted)', marginTop: '0.5rem' }}>
May 19, 2026 · 18 min read
</div>
</div>
<Figure
src="https://images.unsplash.com/photo-1507842217343-583bb7270b66?auto=format&fit=crop&w=1400&q=80"
alt="Empty bookshelves in a closing bookstore"
caption="A former independent bookstore in Portland, Oregon, photographed the week before its final closing. The middle shelves — where debut novels and second books once lived — were the first to empty."
credit="Photograph by Daniel Voss for The Chronicle"
/>
<BodyText weight="High" dropCap style={{ marginTop: '2rem' }}>
<p><Dateline>Portland, Ore. </Dateline> The bookstore on Southeast Hawthorne had been open for thirty-one years when its owner, Margaret Liu, decided she could no longer make the numbers work. It was not a dramatic collapse. There was no single catastrophe, no flood, no fire, no pandemic-era pivot that failed. It was, she said, more like a long exhalation.</p>
<p>"The books that used to sell two thousand copies now sell four hundred," she told me, standing behind a counter stacked with returns. "And the books that sell a hundred thousand still sell a hundred thousand. The middle just — left."</p>
<p>Liu's observation, echoed by dozens of booksellers, agents, and editors I spoke with over six months of reporting, describes a structural shift in American publishing that has accelerated sharply since 2022. The "middle shelf" — the physical and metaphorical space where literary fiction, serious nonfiction, and debut authors once found their audience — has contracted to a degree that many in the industry describe as existential.</p>
<p>The data bears this out. According to figures compiled by the Association of American Publishers and cross-referenced with BookScan point-of-sale data, the number of titles selling between 2,000 and 20,000 copies annually has declined by 34 percent since 2019. Over the same period, the number of titles selling more than 100,000 copies has increased by 11 percent. The top is growing; the middle is vanishing.</p>
</BodyText>
<PullQuote weight="High" author="Margaret Liu, bookseller" align="center" style={{ margin: '2.5rem 0' }}>
The books that used to sell two thousand copies now sell four hundred. The middle just — left.
</PullQuote>
<BodyText weight="High">
<p>For readers, the consequences are subtle but cumulative. The debut novel that might have found ten thousand readers in 2015 now finds three thousand — or never gets published at all. The second book, historically the most precarious moment in a literary career, has become a cliff edge. Agents report that "second book syndrome" has evolved from a creative challenge into an economic one: publishers increasingly decline to offer contracts for follow-up works unless the debut exceeded expectations.</p>
<p>"I had three clients last year whose publishers simply said no to book two," said Rachel Mendelson, a literary agent in New York. "Not because the books were bad. Because the sales data from book one didn't justify the advance. These are talented writers with good reviews and real readers. But 'real readers' now means something different to a P&L spreadsheet."</p>
<p>The causes are multiple and mutually reinforcing. The consolidation of major publishers into four global conglomerates has concentrated decision-making power among fewer acquiring editors, each under greater pressure to justify investments with projected returns. The rise of algorithmic recommendation — on Amazon, on social media, on podcast charts — has created winner-take-all dynamics that reward existing visibility over literary merit. And the economic pressures on readers themselves, facing higher costs of living and competing demands on attention, have made the "safe bet" of a known author or a viral recommendation more attractive than the gamble of an unfamiliar name.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '2rem 0' }} />
<BodyText weight="High">
<p>The human cost is difficult to quantify but impossible to ignore. I spoke with fourteen mid-career authors — writers with two to five published books, strong reviews, and modest but loyal readerships — about their financial situations. Twelve reported that their writing income had declined in real terms over the past five years. Nine had taken on additional employment. Four had effectively stopped writing new books, though none had publicly announced retirement.</p>
<p>"I don't want to sound self-pitying," said one novelist, who asked not to be named because she feared alienating her publisher. "I knew this wasn't going to make me rich. But I thought it would let me keep doing it. That's what's changed. It's not about wealth. It's about viability."</p>
<p>The phrase "viability" recurred in nearly every conversation. Not the viability of literature as an art form — no one doubted that — but the viability of a life organized around producing it. The distinction matters. Great books will continue to be written. But the ecosystem that once supported a broad class of working writers, allowing them to develop over multiple books and find their audience gradually, is contracting faster than anyone predicted.</p>
</BodyText>
<PullQuote weight="Medium" author="Anonymous novelist" align="center" style={{ margin: '2.5rem 0' }}>
I knew this wasn't going to make me rich. But I thought it would let me keep doing it. That's what's changed.
</PullQuote>
<BodyText weight="High">
<p>Independent publishers have partially filled the gap. Small presses like Graywolf, Coffee House, Tin House, and Catapult have expanded their lists and taken on authors who might previously have published with major houses. But their advances are smaller, their marketing budgets thinner, and their distribution reach narrower. An author moving from a Big Four imprint to an independent press typically sees their print run cut by half or more.</p>
<p>"We're doing important work," said one independent publisher, "but we can't replace what's been lost. We're a lifeboat, not a cruise ship."</p>
<p>The question facing American letters is whether this contraction is cyclical or structural — whether the middle shelf will eventually recover as reading habits shift, or whether the current configuration represents a new permanent state. Most industry observers I spoke with leaned toward the latter view, though several noted that predictions about publishing have a long history of being wrong.</p>
<p>What seems clear is that the current moment demands new thinking about how literary culture sustains itself. The old model — in which publishers cross-subsidized risky literary work with profitable commercial titles — depended on a middle tier that generated modest but reliable returns. Without that middle, the cross-subsidy breaks down, and each book must justify itself independently. In such a world, the incentive to publish only sure things becomes overwhelming.</p>
<p>Margaret Liu closed her bookstore on a Tuesday in March. The middle shelves, she noted, were the first to empty. The bestsellers went last.</p>
</BodyText>
<Rule variant="double" style={{ margin: '3rem 0 1rem' }} />
<div style={{ fontFamily: 'var(--font-family-meta)', fontSize: '12px', color: 'var(--nui-text-muted)', fontStyle: 'italic' }}>
Catherine Ashworth is a staff writer covering publishing and literary culture. Additional reporting by James Okafor.
</div>
</Article>
</Section>
</Layout>
);
}
@@ -0,0 +1,141 @@
'use client';
import { Layout, Section, Article, Rule, BodyText, Figure } from '@newspaperui/components';
const jp = { fontFamily: 'var(--font-family-cjk-jp)' };
const jpAccent = { color: 'var(--nui-accent-ink-blue)' };
export default function JpHorizontal() {
return (
<Layout columns={24} maxWidth="1280px" padding="1.5rem 1rem">
{/* 報頭 */}
<header style={{
textAlign: 'center',
borderTop: '3px solid var(--nui-text-primary)',
borderBottom: '1px solid var(--nui-rule-decorative)',
paddingTop: '1rem',
paddingBottom: '0.5rem',
}}>
<h1 style={{
...jp,
fontSize: '72px',
fontWeight: 900,
margin: 0,
letterSpacing: '0.15em',
lineHeight: 1,
color: 'var(--nui-text-primary)',
}}></h1>
<div style={{
...jp,
display: 'flex',
justifyContent: 'space-between',
fontSize: '11px',
color: 'var(--nui-text-secondary)',
padding: '0.5rem 1rem',
borderTop: '1px solid var(--nui-rule-hairline)',
marginTop: '0.5rem',
}}>
<span>48721</span>
<span>82026519 </span>
<span> · 14</span>
</div>
</header>
{/* 一面トップ */}
<Section columns={24} gap="1rem" style={{ marginTop: '1rem', paddingBottom: '1rem', borderBottom: '2px solid var(--nui-rule-decorative)' }}>
<Article span={24}>
<div style={{ ...jp, ...jpAccent, fontSize: '13px', fontWeight: 700, marginBottom: '0.5rem', textAlign: 'center' }}></div>
<h2 style={{ ...jp, fontSize: '48px', fontWeight: 900, lineHeight: 1.15, color: 'var(--nui-text-primary)', textAlign: 'center', margin: 0 }}>
 23
</h2>
<h3 style={{ ...jp, fontSize: '20px', fontWeight: 500, lineHeight: 1.5, color: 'var(--nui-text-secondary)', textAlign: 'center', margin: '0.5rem 0 1rem 0' }}>
 
</h3>
<div style={{ ...jp, textAlign: 'center', fontSize: '12px', color: 'var(--nui-text-muted)', marginBottom: '1rem' }}>
</div>
<Figure
src="https://images.unsplash.com/photo-1577962917302-cd874c4e31d2?auto=format&fit=crop&w=1200&q=80"
alt="署名式の様子"
caption="協定に署名する各国代表。ブリュッセルの会議場で19日未明。"
credit="AP"
/>
<BodyText weight="High" columns={3} style={{ ...jp, marginTop: '1rem' }}>
<p>112319調</p>
<p>20402028</p>
<p>1.20.7</p>
<p></p>
<p>32貿18</p>
<p>10</p>
</BodyText>
</Article>
</Section>
{/* 二面:3栏 */}
<Section columns={24} gap="1rem" style={{ marginTop: '1rem', paddingBottom: '1rem', borderBottom: '1px solid var(--nui-rule-decorative)' }}>
<Article span={8} style={{ background: 'var(--nui-bg-surface)', padding: '1rem', borderLeft: '3px solid var(--nui-accent-ink-blue)' }}>
<div style={{ ...jp, ...jpAccent, fontSize: '12px', fontWeight: 700, marginBottom: '0.75rem', paddingLeft: '0.75rem', borderLeft: '3px solid var(--nui-accent-ink-blue)' }}></div>
<h3 style={{ ...jp, fontSize: '20px', fontWeight: 700, lineHeight: 1.35, color: 'var(--nui-text-primary)', margin: '0 0 0.5rem 0' }}></h3>
<BodyText weight="Low" style={jp}>
<p></p>
<p></p>
</BodyText>
<Rule variant="hairline" style={{ margin: '0.75rem 0' }} />
<h4 style={{ ...jp, fontSize: '16px', fontWeight: 600, lineHeight: 1.35, margin: '0 0 0.4rem 0' }}>3</h4>
<BodyText weight="Low" style={jp}>
<p>243</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '0.75rem 0' }} />
<h4 style={{ ...jp, fontSize: '16px', fontWeight: 600, lineHeight: 1.35, margin: '0 0 0.4rem 0' }}></h4>
<BodyText weight="Low" style={jp}>
<p>3</p>
</BodyText>
</Article>
<Article span={8} style={{ background: 'var(--nui-bg-surface)', padding: '1rem', borderLeft: '3px solid var(--nui-accent-ink-blue)' }}>
<div style={{ ...jp, ...jpAccent, fontSize: '12px', fontWeight: 700, marginBottom: '0.75rem', paddingLeft: '0.75rem', borderLeft: '3px solid var(--nui-accent-ink-blue)' }}></div>
<h3 style={{ ...jp, fontSize: '20px', fontWeight: 700, lineHeight: 1.35, color: 'var(--nui-text-primary)', margin: '0 0 0.5rem 0' }}>PMI</h3>
<BodyText weight="Low" style={jp}>
<p>552.45</p>
<p></p>
</BodyText>
<Rule variant="hairline" style={{ margin: '0.75rem 0' }} />
<h4 style={{ ...jp, fontSize: '16px', fontWeight: 600, lineHeight: 1.35, margin: '0 0 0.4rem 0' }}>3.7</h4>
<BodyText weight="Low" style={jp}>
<p>AI商用化への期待を背景にテクノロジー株が全面高</p>
</BodyText>
</Article>
<Article span={8} style={{ background: 'var(--nui-bg-surface)', padding: '1rem', borderLeft: '3px solid var(--nui-accent-ink-blue)' }}>
<div style={{ ...jp, ...jpAccent, fontSize: '12px', fontWeight: 700, marginBottom: '0.75rem', paddingLeft: '0.75rem', borderLeft: '3px solid var(--nui-accent-ink-blue)' }}></div>
<h3 style={{ ...jp, fontSize: '20px', fontWeight: 700, lineHeight: 1.35, color: 'var(--nui-text-primary)', margin: '0 0 0.5rem 0' }}></h3>
<BodyText weight="Low" style={jp}>
<p>殿8220214</p>
<p>4</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '0.75rem 0' }} />
<h4 style={{ ...jp, fontSize: '16px', fontWeight: 600, lineHeight: 1.35, margin: '0 0 0.4rem 0' }}></h4>
<BodyText weight="Low" style={jp}>
<p>18</p>
</BodyText>
</Article>
</Section>
{/* 短信欄 */}
<Section columns={24} gap="1rem" style={{ marginTop: '1rem' }}>
<Article span={24}>
<div style={{ ...jp, ...jpAccent, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem', paddingLeft: '0.75rem', borderLeft: '3px solid var(--nui-accent-ink-blue)' }}> · </div>
<BodyText weight="Low" columns={4} style={jp}>
<p> </p>
<p> FRB議事要旨で大半の当局者が年内利下げ開始を支持していることが判明</p>
<p> 25bp引き下げ</p>
<p> </p>
<p> EU首脳会議が支援パッケージで合意3</p>
<p> 58000西</p>
</BodyText>
</Article>
</Section>
</Layout>
);
}
@@ -0,0 +1,160 @@
'use client';
import React from 'react';
const jp = { fontFamily: 'var(--font-family-cjk-jp)' };
const jpAccent = { color: 'var(--nui-accent-ink-blue)' };
export default function JpVertical() {
return (
<div style={{
background: 'var(--nui-bg-page)',
color: 'var(--nui-text-body)',
padding: '2rem',
minHeight: '100vh',
}}>
{/* 竖排容器 */}
<div style={{
writingMode: 'vertical-rl',
...jp,
height: '85vh',
overflow: 'hidden',
}}>
{/* 報頭(竖排中在最右侧) */}
<div style={{
borderLeft: '3px solid var(--nui-text-primary)',
paddingLeft: '1rem',
marginLeft: '2rem',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
gap: '1rem',
}}>
<h1 style={{
...jp,
fontSize: '56px',
fontWeight: 900,
letterSpacing: '0.2em',
lineHeight: 1.2,
margin: 0,
color: 'var(--nui-text-primary)',
}}></h1>
<div style={{ fontSize: '12px', color: 'var(--nui-text-muted)', lineHeight: 1.8 }}>
<div></div>
<div></div>
<div></div>
<div>48721</div>
</div>
</div>
{/* 一面トップ記事 */}
<div style={{
borderLeft: '1px solid var(--nui-rule-hairline)',
paddingLeft: '1.5rem',
marginLeft: '1.5rem',
maxHeight: '100%',
}}>
<div style={{ ...jpAccent, fontSize: '13px', fontWeight: 700, marginBottom: '1rem' }}></div>
<h2 style={{
...jp,
fontSize: '36px',
fontWeight: 900,
lineHeight: 1.4,
color: 'var(--nui-text-primary)',
margin: '0 0 1rem 0',
}}>
</h2>
<h3 style={{
...jp,
fontSize: '18px',
fontWeight: 500,
lineHeight: 1.6,
color: 'var(--nui-text-secondary)',
margin: '0 0 1.5rem 0',
}}>
 
</h3>
<div style={{ fontSize: '12px', color: 'var(--nui-text-muted)', marginBottom: '1rem' }}>
</div>
<div style={{ fontSize: '15px', lineHeight: 2.0, color: 'var(--nui-text-body)' }}>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}>調</p>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
</div>
</div>
{/* 二面記事 */}
<div style={{
borderLeft: '1px solid var(--nui-rule-hairline)',
paddingLeft: '1.5rem',
marginLeft: '1.5rem',
maxHeight: '100%',
}}>
<div style={{ ...jpAccent, fontSize: '12px', fontWeight: 700, marginBottom: '0.75rem' }}></div>
<h3 style={{ ...jp, fontSize: '22px', fontWeight: 700, lineHeight: 1.4, color: 'var(--nui-text-primary)', margin: '0 0 0.75rem 0' }}>
</h3>
<div style={{ fontSize: '14px', lineHeight: 2.0, color: 'var(--nui-text-body)' }}>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
</div>
</div>
{/* 三面記事 */}
<div style={{
borderLeft: '1px solid var(--nui-rule-hairline)',
paddingLeft: '1.5rem',
marginLeft: '1.5rem',
maxHeight: '100%',
}}>
<div style={{ ...jpAccent, fontSize: '12px', fontWeight: 700, marginBottom: '0.75rem' }}></div>
<h3 style={{ ...jp, fontSize: '22px', fontWeight: 700, lineHeight: 1.4, color: 'var(--nui-text-primary)', margin: '0 0 0.75rem 0' }}>
</h3>
<div style={{ fontSize: '14px', lineHeight: 2.0, color: 'var(--nui-text-body)' }}>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
</div>
</div>
{/* 四面:文化 */}
<div style={{
borderLeft: '1px solid var(--nui-rule-hairline)',
paddingLeft: '1.5rem',
marginLeft: '1.5rem',
maxHeight: '100%',
}}>
<div style={{ ...jpAccent, fontSize: '12px', fontWeight: 700, marginBottom: '0.75rem' }}></div>
<h3 style={{ ...jp, fontSize: '22px', fontWeight: 700, lineHeight: 1.4, color: 'var(--nui-text-primary)', margin: '0 0 0.75rem 0' }}>
</h3>
<div style={{ fontSize: '14px', lineHeight: 2.0, color: 'var(--nui-text-body)' }}>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
</div>
</div>
{/* 五面:短信 */}
<div style={{
borderLeft: '1px solid var(--nui-rule-hairline)',
paddingLeft: '1.5rem',
marginLeft: '1.5rem',
maxHeight: '100%',
}}>
<div style={{ ...jpAccent, fontSize: '12px', fontWeight: 700, marginBottom: '0.75rem' }}></div>
<div style={{ fontSize: '13px', lineHeight: 2.0, color: 'var(--nui-text-body)' }}>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
<p style={{ margin: '0 0 0.5em 0', textIndent: '1em' }}></p>
</div>
</div>
</div>
</div>
);
}
+139
View File
@@ -0,0 +1,139 @@
'use client';
import Link from 'next/link';
import { Layout, Section, Article, Headline, Subhead, Kicker } from '@newspaperui/components';
const blocks = [
{
href: '/blocks/zh-frontpage',
lang: 'CHINESE · 中文',
title: '人民周报 · 头版',
description: '思源宋体 + 克制朱红 + 紧凑排版。中文报纸传统视觉语言,板块密集,信息密度高。',
color: '#CC2929',
},
{
href: '/blocks/zh-feature',
lang: 'CHINESE · 中文',
title: '副刊 · 文化专题',
description: '人物访谈与文化评论。深度内容排版,引用密集,多用 Quote 组件。',
color: '#CC2929',
},
{
href: '/blocks/en-feature',
lang: 'ENGLISH',
title: 'The Daily Chronicle · Long-form Feature',
description: 'Atlantic / New Yorker style long-form editorial. Single-column reading mode with multiple PullQuotes.',
color: '#1A1A1A',
},
{
href: '/blocks/jp-horizontal',
lang: 'JAPANESE · 日本語',
title: '朝日新聞 · 横組み',
description: 'Modern horizontal Japanese newspaper layout. Noto Serif JP, 24-column grid.',
color: '#1B2A4A',
},
{
href: '/blocks/jp-vertical',
lang: 'JAPANESE · 日本語',
title: '朝日新聞 · 縦組み',
description: 'Traditional vertical writing-mode (vertical-rl) Japanese layout.',
color: '#1B2A4A',
},
{
href: '/blocks/zh-editorial',
lang: 'CHINESE · 中文',
title: '社论 · 时事评论',
description: '双栏对开评论文章。引用密集,配以专家点评与读者来信。',
color: '#CC2929',
},
];
export default function BlocksIndex() {
return (
<Layout columns={24} maxWidth="1400px" padding="3rem 2rem 4rem">
<Section columns={24} gap="2rem">
<Article span={24}>
<div style={{ textAlign: 'center' }}>
<Kicker>Production-grade Blocks · Copy & Paste</Kicker>
</div>
<Headline weight="High" align="center">
Newspaper Blocks
</Headline>
<Subhead weight="Medium" style={{ textAlign: 'center' }}>
6 complete newspaper layouts in Chinese, English, and Japanese ready to copy.
</Subhead>
</Article>
</Section>
<Section columns={24} gap="2rem" style={{ marginTop: '3rem' }}>
{blocks.map((block, idx) => (
<Article key={block.href} span={24} style={{ marginBottom: '1.5rem' }}>
<Link href={block.href} style={{ textDecoration: 'none', color: 'inherit', display: 'block' }}>
<div style={{
border: '1px solid var(--nui-rule-hairline)',
background: 'var(--nui-bg-surface)',
padding: '2rem',
display: 'grid',
gridTemplateColumns: '1fr 3fr',
gap: '2rem',
alignItems: 'center',
}}>
<div style={{ borderRight: '1px solid var(--nui-rule-hairline)', paddingRight: '2rem' }}>
<div style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '11px',
fontWeight: 600,
fontVariantCaps: 'small-caps',
letterSpacing: '0.08em',
color: block.color,
marginBottom: '0.5rem',
}}>
{block.lang}
</div>
<div style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '11px',
color: 'var(--nui-text-muted)',
}}>
Block #{String(idx + 1).padStart(2, '0')}
</div>
</div>
<div>
<h3 style={{
fontFamily: 'var(--font-family-display)',
fontSize: '28px',
fontWeight: 600,
lineHeight: 1.15,
color: 'var(--nui-text-primary)',
margin: '0 0 0.5rem 0',
}}>
{block.title}
</h3>
<p style={{
fontFamily: 'var(--font-family-body)',
fontSize: '15px',
lineHeight: 1.5,
color: 'var(--nui-text-body)',
margin: 0,
}}>
{block.description}
</p>
<div style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '12px',
fontWeight: 600,
color: 'var(--nui-accent-primary)',
marginTop: '0.75rem',
fontVariantCaps: 'small-caps',
letterSpacing: '0.06em',
}}>
View block
</div>
</div>
</div>
</Link>
</Article>
))}
</Section>
</Layout>
);
}
@@ -0,0 +1,112 @@
'use client';
import { Layout, Section, Article, Rule, BodyText, Quote } from '@newspaperui/components';
const cn = { fontFamily: 'var(--font-family-cjk-serif)' };
const cnRed = { color: 'var(--nui-accent-cjk-red)' };
export default function ZhEditorial() {
return (
<Layout columns={24} maxWidth="1200px" padding="2rem 1.5rem">
{/* 社论报头 */}
<header style={{
borderTop: '3px solid var(--nui-text-primary)',
borderBottom: '1px solid var(--nui-rule-hairline)',
padding: '0.75rem 0',
marginBottom: '2rem',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'baseline',
}}>
<h1 style={{ ...cn, fontSize: '28px', fontWeight: 900, margin: 0, letterSpacing: '0.1em' }}> </h1>
<div style={{ ...cn, ...cnRed, fontSize: '14px', fontWeight: 600 }}>· ·</div>
<div style={{ ...cn, fontSize: '12px', color: 'var(--nui-text-muted)' }}>2026 5 19 · A2 </div>
</header>
{/* 双栏对开 */}
<Section columns={24} gap="2rem">
{/* 左侧:主社论 */}
<Article span={14} style={{ borderRight: '1px solid var(--nui-rule-hairline)', paddingRight: '2rem' }}>
<div style={{ ...cn, ...cnRed, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem', letterSpacing: '0.15em' }}></div>
<h2 style={{ ...cn, fontSize: '36px', fontWeight: 900, lineHeight: 1.2, color: 'var(--nui-text-primary)', margin: '0 0 0.75rem 0' }}>
</h2>
<h3 style={{ ...cn, fontSize: '18px', fontWeight: 500, lineHeight: 1.5, color: 'var(--nui-text-secondary)', margin: '0 0 1.5rem 0' }}>
</h3>
<div style={{ ...cn, fontSize: '12px', color: 'var(--nui-text-muted)', marginBottom: '1.5rem' }}>
</div>
<BodyText weight="High" columns={2} dropCap style={cn}>
<p></p>
<p></p>
<p>齿</p>
<p>2028 线</p>
<p></p>
<p></p>
<p></p>
<p></p>
</BodyText>
</Article>
{/* 右侧:专家评论 + 读者来信 */}
<Article span={10}>
<div style={{ ...cn, ...cnRed, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem', letterSpacing: '0.15em' }}></div>
<h3 style={{ ...cn, fontSize: '24px', fontWeight: 700, lineHeight: 1.3, color: 'var(--nui-text-primary)', margin: '0 0 0.5rem 0' }}>
</h3>
<div style={{ ...cn, fontSize: '12px', color: 'var(--nui-text-muted)', marginBottom: '1rem' }}>
·
</div>
<BodyText weight="Medium" style={cn}>
<p></p>
<p>线</p>
<p></p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1.5rem 0' }} />
<div style={{ ...cn, ...cnRed, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem', letterSpacing: '0.15em' }}></div>
<h3 style={{ ...cn, fontSize: '24px', fontWeight: 700, lineHeight: 1.3, color: 'var(--nui-text-primary)', margin: '0 0 0.5rem 0' }}>
</h3>
<div style={{ ...cn, fontSize: '12px', color: 'var(--nui-text-muted)', marginBottom: '1rem' }}>
·
</div>
<BodyText weight="Medium" style={cn}>
<p></p>
<p></p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1.5rem 0' }} />
<div style={{ ...cn, ...cnRed, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem', letterSpacing: '0.15em' }}></div>
<Quote variant="block" weight="Medium" style={cn}>
<p>线</p>
</Quote>
<div style={{ ...cn, fontSize: '12px', color: 'var(--nui-text-muted)', marginTop: '0.5rem' }}>
·
</div>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Quote variant="block" weight="Medium" style={cn}>
<p></p>
</Quote>
<div style={{ ...cn, fontSize: '12px', color: 'var(--nui-text-muted)', marginTop: '0.5rem' }}>
·
</div>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Quote variant="block" weight="Medium" style={cn}>
<p></p>
</Quote>
<div style={{ ...cn, fontSize: '12px', color: 'var(--nui-text-muted)', marginTop: '0.5rem' }}>
·
</div>
</Article>
</Section>
</Layout>
);
}
@@ -0,0 +1,105 @@
'use client';
import { Layout, Section, Article, BodyText, Quote, Figure, PullQuote } from '@newspaperui/components';
const cn = { fontFamily: 'var(--font-family-cjk-serif)' };
const cnRed = { color: 'var(--nui-accent-cjk-red)' };
export default function ZhFeature() {
return (
<Layout columns={24} maxWidth="1200px" padding="2rem 1.5rem">
{/* 副刊报头 */}
<header style={{
borderTop: '2px solid var(--nui-text-primary)',
borderBottom: '1px solid var(--nui-rule-hairline)',
padding: '0.75rem 0',
marginBottom: '2rem',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'baseline',
}}>
<h1 style={{ ...cn, fontSize: '32px', fontWeight: 900, margin: 0, letterSpacing: '0.05em' }}> </h1>
<div style={{ ...cn, ...cnRed, fontSize: '14px', fontWeight: 600 }}>· ·</div>
<div style={{ ...cn, fontSize: '12px', color: 'var(--nui-text-muted)' }}>2026 5 19 · C </div>
</header>
{/* 专题主标题 */}
<Section columns={24} gap="2rem" style={{ marginBottom: '2rem' }}>
<Article span={24}>
<div style={{ ...cn, ...cnRed, fontSize: '13px', fontWeight: 700, marginBottom: '0.5rem', letterSpacing: '0.15em', textAlign: 'center' }}>访</div>
<h2 style={{ ...cn, fontSize: '52px', fontWeight: 900, lineHeight: 1.15, color: 'var(--nui-text-primary)', textAlign: 'center', margin: 0 }}>
</h2>
<h3 style={{ ...cn, fontSize: '20px', fontWeight: 500, lineHeight: 1.5, color: 'var(--nui-text-secondary)', textAlign: 'center', margin: '0.75rem 0 1rem 0', maxWidth: '900px', marginLeft: 'auto', marginRight: 'auto' }}>
访
</h3>
<div style={{ ...cn, textAlign: 'center', fontSize: '13px', color: 'var(--nui-text-muted)', marginBottom: '0.5rem' }}>
·
</div>
</Article>
</Section>
{/* 主图 + 介绍 */}
<Section columns={24} gap="2rem" style={{ marginBottom: '2rem' }}>
<Article span={12}>
<Figure
src="https://images.unsplash.com/photo-1582408921715-18e7806365c1?auto=format&fit=crop&w=1200&q=80"
alt="林文渊在工作室"
caption="林文渊在故宫博物院文华殿筹备中。"
credit="摄影 黄翔"
/>
</Article>
<Article span={12}>
<BodyText weight="High" dropCap style={cn}>
<p>殿线穿广穿</p>
<p></p>
<p></p>
<p>访殿线</p>
</BodyText>
</Article>
</Section>
{/* 访谈正文(双栏) */}
<Section columns={24} gap="2rem" style={{ marginBottom: '2rem' }}>
<Article span={24}>
<BodyText weight="High" columns={2} style={cn}>
<p style={{ ...cnRed, fontWeight: 700, marginBottom: '0.5rem' }}></p>
<p>西</p>
</BodyText>
</Article>
<Article span={24}>
<PullQuote weight="High" align="center" author="林文渊" style={{ margin: '1rem 0 2rem' }}>
亿
</PullQuote>
</Article>
<Article span={24}>
<BodyText weight="High" columns={2} style={cn}>
<p style={{ ...cnRed, fontWeight: 700, marginBottom: '0.5rem' }}></p>
<p>西西</p>
<p></p>
<p></p>
<p style={{ ...cnRed, fontWeight: 700, marginTop: '1rem', marginBottom: '0.5rem' }}></p>
<p> A B 线</p>
<p style={{ ...cnRed, fontWeight: 700, marginTop: '1rem', marginBottom: '0.5rem' }}></p>
<p></p>
</BodyText>
</Article>
</Section>
{/* 尾声引语 */}
<Section columns={24} gap="2rem" style={{ marginTop: '2rem', paddingTop: '2rem', borderTop: '1px solid var(--nui-rule-hairline)' }}>
<Article span={24}>
<Quote variant="block" weight="High" style={{ ...cn, textAlign: 'center', maxWidth: '700px', margin: '0 auto', borderLeft: 'none' }}>
访殿
</Quote>
<div style={{ ...cn, fontSize: '12px', color: 'var(--nui-text-muted)', textAlign: 'center', marginTop: '1rem', letterSpacing: '0.1em' }}>
· 殿
</div>
</Article>
</Section>
</Layout>
);
}
@@ -0,0 +1,198 @@
'use client';
import { Layout, Section, Article, Rule, BodyText, Figure } from '@newspaperui/components';
const cn = { fontFamily: 'var(--font-family-cjk-serif)' };
const cnRed = { color: 'var(--nui-accent-cjk-red)' };
export default function ZhFrontPage() {
return (
<Layout columns={24} maxWidth="1280px" padding="1.5rem 1rem">
{/* 报头 */}
<header style={{
textAlign: 'center',
borderTop: '4px solid var(--nui-accent-cjk-red)',
borderBottom: '1px solid var(--nui-rule-decorative)',
paddingTop: '1rem',
paddingBottom: '0.5rem',
}}>
<div style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '11px',
color: 'var(--nui-text-muted)',
letterSpacing: '0.2em',
marginBottom: '0.25rem',
}}>RENMIN ZHOUBAO · </div>
<h1 style={{
...cn,
...cnRed,
fontSize: '88px',
fontWeight: 900,
margin: 0,
letterSpacing: '0.1em',
lineHeight: 1,
}}></h1>
<div style={{
...cn,
display: 'flex',
justifyContent: 'space-between',
fontSize: '12px',
color: 'var(--nui-text-secondary)',
padding: '0.5rem 1rem',
borderTop: '1px solid var(--nui-rule-hairline)',
marginTop: '0.5rem',
}}>
<span> 2026 · 5891 </span>
<span>2026 5 19 · · </span>
<span> 5 · 260 </span>
</div>
</header>
{/* 版面导航条 */}
<div style={{
...cn,
display: 'flex',
gap: '0',
fontSize: '12px',
borderTop: '1px solid var(--nui-rule-hairline)',
borderBottom: '1px solid var(--nui-rule-hairline)',
marginTop: '1rem',
}}>
{['01版 要闻', '02版 经济', '03版 国际', '04版 文化', '05版 体育', '06版 副刊'].map((v, i) => (
<div key={i} style={{
padding: '0.4rem 1rem',
borderRight: '1px solid var(--nui-rule-hairline)',
color: i === 0 ? 'var(--nui-accent-cjk-red)' : 'var(--nui-text-secondary)',
fontWeight: i === 0 ? 700 : 400,
cursor: 'pointer',
}}>{v}</div>
))}
</div>
{/* 头条区 */}
<Section columns={24} gap="1rem" style={{ marginTop: '1rem', paddingBottom: '1rem', borderBottom: '2px solid var(--nui-rule-decorative)' }}>
<Article span={24}>
<div style={{ ...cn, ...cnRed, fontSize: '13px', fontWeight: 700, marginBottom: '0.5rem', textAlign: 'center', letterSpacing: '0.1em' }}></div>
<h2 style={{ ...cn, fontSize: '56px', fontWeight: 900, lineHeight: 1.1, color: 'var(--nui-text-primary)', textAlign: 'center', margin: 0 }}>
</h2>
<h3 style={{ ...cn, fontSize: '24px', fontWeight: 500, lineHeight: 1.4, color: 'var(--nui-text-secondary)', textAlign: 'center', margin: '0.5rem 0 1rem 0' }}>
</h3>
<div style={{ ...cn, textAlign: 'center', fontSize: '12px', color: 'var(--nui-text-muted)', marginBottom: '1rem' }}>
·
</div>
<Figure
src="https://images.unsplash.com/photo-1529107386315-e1a2ed48a620?auto=format&fit=crop&w=1200&q=80"
alt="签署仪式现场"
caption="各国代表在布鲁塞尔会议中心签署协定。"
credit="新华社记者 摄"
style={{ marginBottom: '1rem' }}
/>
<BodyText weight="Medium" columns={3} dropCap style={cn}>
<p> </p>
<p> 2040 2028 </p>
<p> 1.2% 0.7%</p>
<p></p>
<p>便</p>
<p></p>
<p></p>
<p> 2028 </p>
<p> 18 20 </p>
</BodyText>
</Article>
</Section>
{/* 二条区:3 栏并列 */}
<Section columns={24} gap="1rem" style={{ marginTop: '1rem', paddingBottom: '1rem', borderBottom: '1px solid var(--nui-rule-decorative)' }}>
<Article span={8} style={{ border: '1px solid var(--nui-rule-hairline)', padding: '1rem', background: 'var(--nui-bg-surface)' }}>
<div style={{ ...cn, ...cnRed, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem' }}> </div>
<h3 style={{ ...cn, fontSize: '22px', fontWeight: 700, lineHeight: 1.3, color: 'var(--nui-text-primary)', margin: '0 0 0.5rem 0' }}></h3>
<BodyText weight="Low" style={cn}>
<p></p>
<p></p>
</BodyText>
<Rule variant="hairline" style={{ margin: '0.75rem 0' }} />
<h4 style={{ ...cn, fontSize: '17px', fontWeight: 600, lineHeight: 1.3, margin: '0 0 0.4rem 0' }}>线</h4>
<BodyText weight="Low" style={cn}>
<p>亿线线 A8 </p>
</BodyText>
<Rule variant="hairline" style={{ margin: '0.75rem 0' }} />
<h4 style={{ ...cn, fontSize: '17px', fontWeight: 600, lineHeight: 1.3, margin: '0 0 0.4rem 0' }}></h4>
<BodyText weight="Low" style={cn}>
<p> A10</p>
</BodyText>
</Article>
<Article span={8} style={{ border: '1px solid var(--nui-rule-hairline)', padding: '1rem', background: 'var(--nui-bg-surface)' }}>
<div style={{ ...cn, ...cnRed, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem' }}> </div>
<h3 style={{ ...cn, fontSize: '22px', fontWeight: 700, lineHeight: 1.3, color: 'var(--nui-text-primary)', margin: '0 0 0.5rem 0' }}> PMI </h3>
<BodyText weight="Low" style={cn}>
<p> 52.4</p>
<p></p>
</BodyText>
<Rule variant="hairline" style={{ margin: '0.75rem 0' }} />
<h4 style={{ ...cn, fontSize: '17px', fontWeight: 600, lineHeight: 1.3, margin: '0 0 0.4rem 0' }}> 3.7%</h4>
<BodyText weight="Low" style={cn}>
<p></p>
</BodyText>
<Rule variant="hairline" style={{ margin: '0.75rem 0' }} />
<h4 style={{ ...cn, fontSize: '17px', fontWeight: 600, lineHeight: 1.3, margin: '0 0 0.4rem 0' }}></h4>
<BodyText weight="Low" style={cn}>
<p></p>
</BodyText>
</Article>
<Article span={8} style={{ border: '1px solid var(--nui-rule-hairline)', padding: '1rem', background: 'var(--nui-bg-surface)' }}>
<div style={{ ...cn, ...cnRed, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem' }}> · </div>
<h3 style={{ ...cn, fontSize: '22px', fontWeight: 700, lineHeight: 1.3, color: 'var(--nui-text-primary)', margin: '0 0 0.5rem 0' }}></h3>
<BodyText weight="Low" style={cn}>
<p>殿</p>
<p></p>
</BodyText>
<Rule variant="hairline" style={{ margin: '0.75rem 0' }} />
<h4 style={{ ...cn, fontSize: '17px', fontWeight: 600, lineHeight: 1.3, margin: '0 0 0.4rem 0' }}></h4>
<BodyText weight="Low" style={cn}>
<p> 18%</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '0.75rem 0' }} />
<h4 style={{ ...cn, fontSize: '17px', fontWeight: 600, lineHeight: 1.3, margin: '0 0 0.4rem 0' }}></h4>
<BodyText weight="Low" style={cn}>
<p></p>
</BodyText>
</Article>
</Section>
{/* 简讯 + 要点提示 */}
<Section columns={24} gap="1rem" style={{ marginTop: '1rem' }}>
<Article span={6} style={{ background: 'var(--nui-bg-surface)', padding: '1rem', borderLeft: '3px solid var(--nui-accent-cjk-red)' }}>
<div style={{ ...cn, ...cnRed, fontSize: '11px', fontWeight: 700, marginBottom: '0.5rem', letterSpacing: '0.1em' }}></div>
<ul style={{ ...cn, fontSize: '14px', lineHeight: 1.7, paddingLeft: '1.2em', margin: 0, color: 'var(--nui-text-body)' }}>
<li> · A2</li>
<li> · A4</li>
<li> · B1</li>
<li> · C3</li>
<li> · C5</li>
<li> · D2</li>
<li> · E1</li>
<li> · F4</li>
</ul>
</Article>
<Article span={18}>
<div style={{ ...cn, ...cnRed, fontSize: '12px', fontWeight: 700, marginBottom: '0.5rem' }}> · </div>
<BodyText weight="Low" columns={4} style={cn}>
<p><strong></strong> 8000 西</p>
<p><strong></strong> </p>
<p><strong></strong> 退</p>
<p><strong>广</strong> 500 亿</p>
<p><strong></strong> </p>
<p><strong></strong> </p>
<p><strong></strong> </p>
<p><strong></strong> </p>
<p><strong></strong> 25 </p>
</BodyText>
</Article>
</Section>
</Layout>
);
}
@@ -32,6 +32,33 @@ export default function BlackletterFrontPage() {
<p>Verbände begrüßen die Pläne, mahnen aber Übergangsfristen für kleinere Betriebe an.
Wirtschaft, Seite 9.</p>
</BodyText>
<hr className="nui-rule-hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Haushaltsentwurf sorgt für Streit in der Koalition</Headline>
<BodyText weight="Low">
<p>Die Fraktionsvorsitzenden konnten sich nicht auf Kürzungen im Sozialbereich einigen.
Innenpolitik, Seite 3.</p>
</BodyText>
<hr className="nui-rule-hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Neue Studie belegt Rückgang der Artenvielfalt</Headline>
<BodyText weight="Low">
<p>Forscher der Universität Freiburg dokumentieren einen Verlust von 23 Prozent bei
Insektenpopulationen seit 2015. Wissenschaft, Seite 7.</p>
</BodyText>
<hr className="nui-rule-hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Frankfurter Buchmesse meldet Besucherrekord</Headline>
<BodyText weight="Low">
<p>Über 300.000 Besucher kamen in diesem Jahr, ein Anstieg von zwölf Prozent gegenüber
dem Vorjahr. Feuilleton, Seite 11.</p>
</BodyText>
<hr className="nui-rule-hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Bahn plant Ausbau der Nachtzugverbindungen</Headline>
<BodyText weight="Low">
<p>Ab Dezember sollen fünf neue Strecken das europäische Netz ergänzen. Wirtschaft, Seite 8.</p>
</BodyText>
</Article>
<Article span={18}>
@@ -66,6 +93,31 @@ export default function BlackletterFrontPage() {
mit einem Plus von 1,2 Prozent. Die Währung legte gegenüber dem Dollar um 0,7 Prozent zu.
Anleiherenditen, die während der Verhandlungen wegen fiskalischer Sorgen gestiegen waren, kehrten
auf das Niveau vor Beginn der Gespräche zurück.</p>
<p>Die weitreichendsten Bestimmungen des Rahmenabkommens betreffen die Schwerindustrie.
Zement-, Stahl- und Chemieproduzenten müssten ab 2028 eine gestaffelte CO-Abgabe
entrichten, deren Einnahmen in einen kontinentalen Investitionsfonds für klimafreundliche
Fertigung fließen sollen. Industrieverbände äußerten vorsichtige Zustimmung, während
Umweltgruppen die verbindliche Architektur lobten, aber warnten, der Zeitplan gebe
Verschmutzern zu viel Spielraum.</p>
<p>Die innenpolitischen Reaktionen fielen gemischt aus. Die Arbeitsbestimmungen des
Abkommens, die Mindeststandards für bezahlten Urlaub und Tarifverhandlungen festlegen,
stießen bei Gewerkschaften auf sofortige Zustimmung und bei Wirtschaftskammern auf
ebenso sofortige Bedenken. Der Vorsitzende des Bundesverbandes der Industrie warnte,
kleine Unternehmen würden ohne Übergangsunterstützung mit den Compliance-Kosten kämpfen.</p>
<p>Parlamentarische Führer in drei Hauptstädten signalisierten, dass die Ratifizierung
noch vor der Sommerpause erfolgen könnte. Zwei Regierungen kündigten jedoch an, vorher
Volksabstimmungen abhalten zu wollen ein Prozess, der sich voraussichtlich bis in den
Herbst hinziehen wird. Analysten des Zentrums für Handelsstudien schätzten, dass die
vollständige Umsetzung selbst im günstigsten Fall mindestens achtzehn Monate erfordern würde.</p>
<p>Für gewöhnliche Reisende und Verbraucher werden die unmittelbaren Auswirkungen bescheiden
sein. Grenzverfahren und Produktstandards unterliegen bis zur Ratifizierung weiterhin den
bestehenden Regelungen. Der längere Bogen, so argumentierten die Verhandlungsführer, sei
das Entscheidende: ein Kontinent historisch zerstrittener Nachbarn, der sich auf ein
einheitliches Regelwerk für das folgenreichste Jahrzehnt seit Menschengedenken einigt.</p>
</BodyText>
<PullQuote weight="High" author="Margarethe Lindqvist, Chefverhandlerin" align="left">
@@ -79,6 +131,21 @@ export default function BlackletterFrontPage() {
<p>Parlamentarische Führer in drei Hauptstädten signalisierten, dass die Ratifizierung noch vor
der Sommerpause erfolgen könnte. Zwei Regierungen kündigten an, vorher Volksabstimmungen abhalten
zu wollen.</p>
<p>Die Unterzeichnungszeremonie, ursprünglich für vergangenen Freitag geplant, wurde
dreimal verschoben, während die Verfasser konkurrierende Texte zur Streitbeilegung
abglichen. Der endgültige Kompromiss sieht ein Schiedsgericht aus neun Juristen vor,
je drei ernannt von jeder der drei regionalen Gruppierungen des Blocks.</p>
<p>Kritiker von rechts verurteilten das Rahmenwerk als Erosion nationaler Souveränität,
während Kritiker von links argumentierten, der Arbeitsstandard sei zu niedrig angesetzt,
um Arbeitnehmer in strengeren Regulierungsregimen wirksam zu schützen. Beide Lager
signalisierten, dass die Ratifizierungskämpfe heftig werden dürften.</p>
<p>Historiker der kontinentalen Integration merkten an, dass der Umfang des Abkommens
jede einzelne Vereinbarung seit den Nachkriegs-Wiederaufbauverträgen übertrifft. Was
dieses Abkommen anders mache, so Professor Elena Marchetti, sei dass es jeden Haushalt
berühre nicht nur durch den Handel, sondern durch die Luft und die Löhne.</p>
</BodyText>
</Article>
</Section>
@@ -0,0 +1,277 @@
'use client';
import {
Layout, Section, Article, Masthead, Rule,
Headline, Subhead, Kicker, BodyText, Byline, Dateline,
Figure, PullQuote,
} from '@newspaperui/components';
export default function FrontPage() {
return (
<Layout columns={24} maxWidth="1200px" padding="2rem 1.5rem">
<Masthead
variant="classic"
kicker="Late City Edition"
title="The Daily Chronicle"
edition="Vol. CXLIX · No. 51,895"
date="Tuesday, May 19, 2026"
price="$4.00"
/>
<Section columns={24} divider="bottom" gap="2rem" style={{ marginTop: '2rem' }}>
<Article span={5} style={{ borderRight: '1px solid var(--nui-rule-hairline)', paddingRight: '1.5rem' }}>
<Kicker>Inside Today</Kicker>
<Headline weight="Low" as="h3" style={{ marginTop: 0 }}>
Senate Approves Climate Resolution After Months of Debate
</Headline>
<BodyText weight="Low">
<p>The unanimous vote concludes a contentious legislative session marked by partisan disputes
and last-minute amendments. Page A6.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Tech Sector Gains as Inflation Eases</Headline>
<BodyText weight="Low">
<p>Major indices climbed for a fifth consecutive session as new data showed price growth
slowing across consumer goods. Business B1.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Drought Conditions Worsen Across the Plains</Headline>
<BodyText weight="Low">
<p>Officials in seven states have requested federal disaster relief as reservoir levels reach
historic lows. National A12.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">New Exhibit Opens at the Metropolitan</Headline>
<BodyText weight="Low">
<p>A retrospective of mid-century textile design draws record opening crowds. Arts C3.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">City Council Approves Transit Expansion</Headline>
<BodyText weight="Low">
<p>The $2.4 billion plan adds three new rail lines and extends service hours on existing routes. Metro A8.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">University Announces Record Enrollment</Headline>
<BodyText weight="Low">
<p>Applications rose 18 percent this cycle, driven by expanded financial aid programs. Education B4.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Harbor Restoration Project Begins</Headline>
<BodyText weight="Low">
<p>Engineers will dredge sediment and rebuild seawalls over a three-year timeline. Local A10.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Orchestra Names New Music Director</Headline>
<BodyText weight="Low">
<p>The appointment ends a two-year search following the previous director&rsquo;s retirement. Arts C1.</p>
</BodyText>
</Article>
<Article span={14}>
<div style={{ textAlign: 'center' }}><Kicker>Capitol · Breaking</Kicker></div>
<Headline weight="High" align="center">
Historic Accord Reshapes Continental Trade After Marathon Session
</Headline>
<Subhead weight="High" style={{ textAlign: 'center', marginTop: 0 }}>
Negotiators emerge with sweeping framework on tariffs, labor, and emissions; ratification expected within weeks
</Subhead>
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem', margin: '0.5rem 0 1rem', alignItems: 'baseline' }}>
<Byline>By Eleanor Whitcombe and Marcus Reyes</Byline>
<span style={{ color: 'var(--nui-text-muted)' }}>·</span>
<span style={{ fontFamily: 'var(--font-family-meta)', fontSize: '12px', color: 'var(--nui-text-muted)' }}>5 min read</span>
</div>
<Figure
src="https://images.unsplash.com/photo-1572949645841-094f3a9c4c94?auto=format&fit=crop&w=1200&q=80"
alt="Diplomats applaud after the final draft was approved"
caption="Negotiators applaud after the final draft was approved Monday evening at the Continental Conference Center."
credit="Photograph by Jane Doe / Pool"
/>
<BodyText weight="High" columns={3} dropCap style={{ marginTop: '1.5rem' }}>
<p><Dateline>Brussels </Dateline> After eleven consecutive days of negotiation that several
participants described as the most demanding in a generation, delegates from twenty-three nations
announced on Monday a sweeping framework to reorganize commerce across the continent. The accord,
which still requires ratification by member parliaments, would harmonize tariff schedules, set
common labor standards, and bind signatories to a shared emissions pathway through 2040.</p>
<p>Officials briefed on the talks said the breakthrough came shortly before midnight, when a
dispute over agricultural subsidies was resolved with a side letter granting transitional relief
to producers in five smaller economies. The chief negotiator, Margarethe Lindqvist, called the
outcome &ldquo;a long argument that finally became a conversation.&rdquo;</p>
<p>The framework&rsquo;s most consequential provisions target heavy industry. Cement, steel, and
chemical producers would face a graduated carbon levy beginning in 2028, with revenues recycled
into a continental investment fund for low-carbon manufacturing. Industry associations expressed
cautious support, while environmental groups praised the levy&rsquo;s binding architecture but warned
that the timeline gives polluters too much room to delay.</p>
<p>Markets reacted with measured optimism. The continental composite index closed up 1.2 percent,
led by capital-goods makers expected to benefit from infrastructure investment. The currency
strengthened against the dollar by 0.7 percent. Bond yields, which had climbed throughout the
negotiations on fiscal-stability concerns, retreated to levels seen before the talks began.</p>
<p>Domestic political reaction was mixed. The accord&rsquo;s labor provisions, which establish minimum
standards for paid leave and collective bargaining, drew immediate praise from union federations
and equally immediate concern from chambers of commerce. The chairman of the Federation of
Industries warned that small firms would struggle with compliance costs absent transitional support.</p>
<p>Parliamentary leaders in three capitals signaled that ratification could occur before the
summer recess. Two governments, however, indicated that they would seek public referenda before
committing, a process likely to extend into the autumn. Analysts at the Centre for Trade Studies
estimated that full implementation, even on the most expedited timeline, would require at least
eighteen months.</p>
<p>For ordinary travelers and consumers, the immediate effects will be modest. Border procedures
and product standards remain governed by existing arrangements pending ratification. The longer
arc is what matters: a continent of historically fractious neighbors agreeing on a single set of
rules for the most consequential decade in living memory.</p>
<p>The accord&rsquo;s environmental chapter, which drew the most sustained opposition during
negotiations, establishes a continental carbon market linked to existing national schemes.
Permits would be tradeable across borders beginning in 2030, with a price floor set at
forty-five units per ton of carbon dioxide equivalent. Economists at the Institute for
Climate Economics estimated that the floor alone would reduce emissions by eight to twelve
percent within the first five years of operation.</p>
<p>Labor unions in the industrial heartland expressed qualified support. The secretary-general
of the Metalworkers&rsquo; Federation said the transition fund &ldquo;acknowledges what we have argued
for years: that decarbonization cannot be built on the backs of workers.&rdquo; But she cautioned
that the fund&rsquo;s governance structure, which gives equal weight to employer and employee
representatives, could slow disbursements at a moment when speed matters most.</p>
<p>Small and medium enterprises, which employ roughly sixty percent of the continental
workforce, face a distinct set of challenges. The accord exempts firms below a revenue
threshold from the carbon levy for three years, but compliance with the new labor standards
is immediate. Business associations in four countries have already requested technical
assistance programs to help smaller firms adapt their payroll and reporting systems.</p>
<p>Historians of continental integration noted that the accord&rsquo;s scope exceeds any single
agreement since the postwar reconstruction treaties. &ldquo;What makes this different,&rdquo; said
Professor Elena Marchetti of the University of Turin, &ldquo;is that it touches every household&mdash;
not just through trade, but through the air they breathe and the wages they earn.&rdquo;</p>
</BodyText>
<PullQuote weight="High" author="Margarethe Lindqvist, Chief Negotiator" align="center" style={{ margin: '2rem 0' }}>
A long argument that finally became a conversation.
</PullQuote>
<BodyText weight="High" columns={2} style={{ marginTop: '1rem' }}>
<p>The accord&rsquo;s signing ceremony, originally scheduled for last Friday, was delayed three times
as drafters reconciled competing texts on dispute resolution. The final compromise establishes
an arbitration panel of nine jurists, three appointed by each of the bloc&rsquo;s three regional
groupings, with binding authority over commercial disputes exceeding twenty million units.</p>
<p>Critics on the populist right denounced the framework as an erosion of national sovereignty,
while critics on the left argued that the labor floor was set too low to meaningfully protect
workers in tighter regulatory regimes. Both camps signaled that ratification battles would be
fierce, particularly in legislatures with narrow majorities.</p>
</BodyText>
</Article>
<Article span={5} style={{ borderLeft: '1px solid var(--nui-rule-hairline)', paddingLeft: '1.5rem' }}>
<Kicker>Foreign Desk</Kicker>
<Headline weight="Medium" as="h2">
Coastal Nations Pledge Joint Action on Maritime Pollution
</Headline>
<Subhead weight="Medium">
Pact follows years of stalled regional talks and a cascade of recent shipping accidents.
</Subhead>
<Byline>By Tomás Almeida</Byline>
<BodyText weight="Medium" style={{ marginTop: '0.75rem' }}>
<p><Dateline>Lisbon </Dateline> Eleven coastal nations announced a binding compact to coordinate
cleanup operations and harmonize liability rules for vessels exceeding fifty thousand tons. The
agreement establishes a shared rapid-response fund and creates a regional inspectorate empowered
to detain non-compliant ships in any signatory port.</p>
<p>Maritime industry groups received the news with caution. A spokesperson for the Continental
Shipping Council acknowledged that &ldquo;stronger common rules are overdue&rdquo; but warned that
implementation costs could fall disproportionately on smaller operators.</p>
<p>The compact takes effect on January 1, pending technical annexes. Environmental observers
described the pact as the most consequential maritime accord in a decade.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Fisheries Report Warns of Declining Stocks</Headline>
<BodyText weight="Low">
<p>Annual survey data shows a 14 percent drop in key commercial species across the northern
shelf. Scientists attribute the decline to warming waters and overfishing in adjacent
unregulated zones. Environment A9.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Rail Strike Averted After Late-Night Deal</Headline>
<BodyText weight="Low">
<p>Workers accepted a revised pay offer minutes before the midnight deadline. Services
resume on normal schedules. Transport B2.</p>
</BodyText>
</Article>
</Section>
<Section columns={24} divider="top" gap="2rem" style={{ marginTop: '2rem', paddingTop: '2rem' }}>
<Article span={24}>
<Kicker>National · Investigation</Kicker>
<Headline weight="Medium" as="h2">
Records Reveal Years of Overlooked Warnings at Aging Reservoirs
</Headline>
<Subhead weight="Medium">
Internal inspection memoranda, obtained through public records requests, suggest that
structural concerns flagged repeatedly by field engineers were not escalated to senior staff.
</Subhead>
<Byline style={{ marginBottom: '1rem' }}>By Ravi Nair, Anita Kowalski, and Charles Weston</Byline>
<BodyText weight="High" columns={4}>
<p><Dateline>Sacramento </Dateline> A six-month review of more than four thousand pages of
inspection records, interviews with twenty-three current and former engineers, and reconstructions
of three near-failure incidents reveals a pattern of unheeded warnings about the structural
integrity of mid-twentieth-century earthen dams across the western states.</p>
<p>The records show that field engineers documented concerns about seepage, erosion, and spillway
capacity in repeated annual assessments dating back at least fifteen years. In several instances,
those concerns were rated &ldquo;moderate&rdquo; in the field reports but downgraded to &ldquo;low&rdquo; by the time they
reached senior officials. The pattern was particularly pronounced at three facilities serving
regions of more than two million residents.</p>
<p>Officials at the Department of Water Resources, asked to review excerpts of the records, said
in a written statement that &ldquo;every reservoir under our oversight has been deemed safe for current
operations&rdquo; but did not specifically address the discrepancies between field and final ratings.
The agency declined to make senior staff available for interviews.</p>
<p>The findings come amid renewed scrutiny of aging infrastructure following the partial collapse
of an earthen embankment in March that displaced more than fifteen hundred residents. Federal
inspectors who responded to that incident found the proximate cause to be precisely the type of
seepage concern that field engineers had flagged in three of the past four annual assessments.</p>
<p>The investigative review found that of forty-seven reservoirs surveyed, sixteen had at least
one instance in which a &ldquo;moderate&rdquo; or &ldquo;high&rdquo; field rating was downgraded before reaching senior
management. In nine cases, the downgrades persisted for three or more consecutive years. None of
the affected facilities have publicly disclosed the discrepancies.</p>
<p>Engineering professional associations have, in recent years, called for an independent review
of inspection workflows in the western states. A spokesperson for the Society of Hydraulic
Engineers said the Society was &ldquo;deeply concerned&rdquo; by the patterns described and would convene a
working group to examine reform options.</p>
</BodyText>
</Article>
</Section>
</Layout>
);
}
+6 -2
View File
@@ -1,15 +1,19 @@
import './globals.css';
import type { Metadata } from 'next';
import { Header } from '../components/Header';
export const metadata: Metadata = {
title: 'NewspaperUI — Production Newspaper Components',
description: '生产级报纸布局组件库,参考 InDesign 与经典严肃风排版传统,24 列栅格、跨栏、视觉权重和主题系统',
description: '生产级报纸布局组件库',
};
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="zh">
<body>{children}</body>
<body>
<Header />
{children}
</body>
</html>
);
}
+249 -178
View File
@@ -1,205 +1,276 @@
'use client';
import {
Layout, Section, Article, Masthead, Rule,
Headline, Subhead, Kicker, BodyText, Byline, Dateline,
Figure, PullQuote,
Layout,
Section,
Article,
Masthead,
Headline,
Subhead,
Kicker,
BodyText,
} from '@newspaperui/components';
import Link from 'next/link';
export default function FrontPage() {
const demos = [
{
href: '/blocks/zh-frontpage',
lang: '中文 · Chinese',
title: '人民周报 · 头版',
description: '思源宋体 + 克制朱红 + 紧凑排版。中文报纸传统视觉语言。',
color: '#CC2929',
},
{
href: '/blocks/zh-feature',
lang: '中文 · Chinese',
title: '人民周报 · 副刊专题',
description: '深度专题排版:访谈、人物、文化评论。',
color: '#CC2929',
},
{
href: '/examples/nyt-frontpage',
lang: 'English',
title: 'The Daily Chronicle · NYT Style',
description:
'Classic American serious newspaper. Cormorant Garamond masthead, multi-column flow with drop cap.',
color: '#1A1A1A',
},
{
href: '/blocks/en-feature',
lang: 'English',
title: 'The Daily Chronicle · Long-form Feature',
description: 'Editorial long-form piece with pull quotes and editorial design.',
color: '#1A1A1A',
},
{
href: '/blocks/jp-horizontal',
lang: '日本語 · Japanese',
title: '朝日新聞 · 横組み',
description: 'Modern horizontal Japanese newspaper layout. Noto Serif JP.',
color: '#1B2A4A',
},
{
href: '/blocks/jp-vertical',
lang: '日本語 · Japanese',
title: '朝日新聞 · 縦組み',
description: 'Traditional vertical writing-mode Japanese layout.',
color: '#1B2A4A',
},
{
href: '/examples/blackletter-frontpage',
lang: 'Deutsch',
title: 'Die Frankfurter Zeitung',
description: 'Blackletter masthead with UnifrakturMaguntia. German broadsheet tradition.',
color: '#1A1A1A',
},
];
export default function LandingPage() {
return (
<Layout columns={24} maxWidth="1200px" padding="2rem 1.5rem">
<Layout columns={24} maxWidth="1400px" padding="3rem 2rem 4rem">
<Masthead
variant="classic"
kicker="Late City Edition"
title="The Daily Chronicle"
edition="Vol. CXLIX · No. 51,895"
date="Tuesday, May 19, 2026"
price="$4.00"
kicker="Production Newspaper Components"
title="NewspaperUI"
edition="Vol. 01 · No. 1"
date="May 2026"
price="MIT License"
/>
<Section columns={24} divider="bottom" gap="2rem" style={{ marginTop: '2rem' }}>
<Article span={5} style={{ borderRight: '1px solid var(--nui-rule-hairline)', paddingRight: '1.5rem' }}>
<Kicker>Inside Today</Kicker>
<Headline weight="Low" as="h3" style={{ marginTop: 0 }}>
Senate Approves Climate Resolution After Months of Debate
<Section columns={24} gap="2rem" style={{ marginTop: '3rem' }}>
<Article span={6}>
<Kicker>About</Kicker>
<Headline weight="Low" as="h2" style={{ marginTop: 0 }}>
</Headline>
<BodyText weight="Low">
<p>The unanimous vote concludes a contentious legislative session marked by partisan disputes
and last-minute amendments. Page A6.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Tech Sector Gains as Inflation Eases</Headline>
<BodyText weight="Low">
<p>Major indices climbed for a fifth consecutive session as new data showed price growth
slowing across consumer goods. Business B1.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Drought Conditions Worsen Across the Plains</Headline>
<BodyText weight="Low">
<p>Officials in seven states have requested federal disaster relief as reservoir levels reach
historic lows. National A12.</p>
</BodyText>
<Rule variant="hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">New Exhibit Opens at the Metropolitan</Headline>
<BodyText weight="Low">
<p>A retrospective of mid-century textile design draws record opening crowds. Arts C3.</p>
<BodyText weight="Medium">
<p>
InDesign NYT / The Times / FAZ 24 CSS Grid +
Multi-column
</p>
</BodyText>
</Article>
<Article span={14}>
<div style={{ textAlign: 'center' }}><Kicker>Capitol · Breaking</Kicker></div>
<Headline weight="High" align="center">
Historic Accord Reshapes Continental Trade After Marathon Session
<Article span={12}>
<Headline weight="Medium" align="center">
Print-grade typography, on the modern web.
</Headline>
<Subhead weight="High" style={{ textAlign: 'center', marginTop: 0 }}>
Negotiators emerge with sweeping framework on tariffs, labor, and emissions; ratification expected within weeks
<Subhead
weight="High"
style={{ textAlign: 'center', marginTop: '0.5rem' }}
>
18 components, 24-column grid, classic serif typography, real multi-column flow.
</Subhead>
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem', margin: '0.5rem 0 1rem', alignItems: 'baseline' }}>
<Byline>By Eleanor Whitcombe and Marcus Reyes</Byline>
<span style={{ color: 'var(--nui-text-muted)' }}>·</span>
<span style={{ fontFamily: 'var(--font-family-meta)', fontSize: '12px', color: 'var(--nui-text-muted)' }}>5 min read</span>
</Article>
<Article span={6}>
<Kicker>Quick Start</Kicker>
<Headline weight="Low" as="h2" style={{ marginTop: 0 }}>
Install
</Headline>
<BodyText weight="Medium">
<p style={{ fontFamily: 'var(--font-family-meta)', fontSize: '13px' }}>
<code>pnpm add @newspaperui/components @newspaperui/theme</code>
</p>
</BodyText>
<div style={{ marginTop: '1rem' }}>
<Link
href="/grid-system"
style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '13px',
color: 'var(--nui-accent-primary)',
textDecoration: 'none',
fontWeight: 600,
}}
>
Documentation
</Link>
</div>
<Figure
src="https://images.unsplash.com/photo-1572949645841-094f3a9c4c94?auto=format&fit=crop&w=1200&q=80"
alt="Diplomats applaud after the final draft was approved"
caption="Negotiators applaud after the final draft was approved Monday evening at the Continental Conference Center."
credit="Photograph by Jane Doe / Pool"
/>
<BodyText weight="High" columns={3} dropCap style={{ marginTop: '1.5rem' }}>
<p><Dateline>Brussels </Dateline> After eleven consecutive days of negotiation that several
participants described as the most demanding in a generation, delegates from twenty-three nations
announced on Monday a sweeping framework to reorganize commerce across the continent. The accord,
which still requires ratification by member parliaments, would harmonize tariff schedules, set
common labor standards, and bind signatories to a shared emissions pathway through 2040.</p>
<p>Officials briefed on the talks said the breakthrough came shortly before midnight, when a
dispute over agricultural subsidies was resolved with a side letter granting transitional relief
to producers in five smaller economies. The chief negotiator, Margarethe Lindqvist, called the
outcome &ldquo;a long argument that finally became a conversation.&rdquo;</p>
<p>The framework&rsquo;s most consequential provisions target heavy industry. Cement, steel, and
chemical producers would face a graduated carbon levy beginning in 2028, with revenues recycled
into a continental investment fund for low-carbon manufacturing. Industry associations expressed
cautious support, while environmental groups praised the levy&rsquo;s binding architecture but warned
that the timeline gives polluters too much room to delay.</p>
<p>Markets reacted with measured optimism. The continental composite index closed up 1.2 percent,
led by capital-goods makers expected to benefit from infrastructure investment. The currency
strengthened against the dollar by 0.7 percent. Bond yields, which had climbed throughout the
negotiations on fiscal-stability concerns, retreated to levels seen before the talks began.</p>
<p>Domestic political reaction was mixed. The accord&rsquo;s labor provisions, which establish minimum
standards for paid leave and collective bargaining, drew immediate praise from union federations
and equally immediate concern from chambers of commerce. The chairman of the Federation of
Industries warned that small firms would struggle with compliance costs absent transitional support.</p>
<p>Parliamentary leaders in three capitals signaled that ratification could occur before the
summer recess. Two governments, however, indicated that they would seek public referenda before
committing, a process likely to extend into the autumn. Analysts at the Centre for Trade Studies
estimated that full implementation, even on the most expedited timeline, would require at least
eighteen months.</p>
<p>For ordinary travelers and consumers, the immediate effects will be modest. Border procedures
and product standards remain governed by existing arrangements pending ratification. The longer
arc is what matters: a continent of historically fractious neighbors agreeing on a single set of
rules for the most consequential decade in living memory.</p>
</BodyText>
<PullQuote weight="High" author="Margarethe Lindqvist, Chief Negotiator" align="center" style={{ margin: '2rem 0' }}>
A long argument that finally became a conversation.
</PullQuote>
<BodyText weight="High" columns={2} style={{ marginTop: '1rem' }}>
<p>The accord&rsquo;s signing ceremony, originally scheduled for last Friday, was delayed three times
as drafters reconciled competing texts on dispute resolution. The final compromise establishes
an arbitration panel of nine jurists, three appointed by each of the bloc&rsquo;s three regional
groupings, with binding authority over commercial disputes exceeding twenty million units.</p>
<p>Critics on the populist right denounced the framework as an erosion of national sovereignty,
while critics on the left argued that the labor floor was set too low to meaningfully protect
workers in tighter regulatory regimes. Both camps signaled that ratification battles would be
fierce, particularly in legislatures with narrow majorities.</p>
</BodyText>
</Article>
<Article span={5} style={{ borderLeft: '1px solid var(--nui-rule-hairline)', paddingLeft: '1.5rem' }}>
<Kicker>Foreign Desk</Kicker>
<Headline weight="Medium" as="h2">
Coastal Nations Pledge Joint Action on Maritime Pollution
</Headline>
<Subhead weight="Medium">
Pact follows years of stalled regional talks and a cascade of recent shipping accidents.
</Subhead>
<Byline>By Tomás Almeida</Byline>
<BodyText weight="Medium" style={{ marginTop: '0.75rem' }}>
<p><Dateline>Lisbon </Dateline> Eleven coastal nations announced a binding compact to coordinate
cleanup operations and harmonize liability rules for vessels exceeding fifty thousand tons. The
agreement establishes a shared rapid-response fund and creates a regional inspectorate empowered
to detain non-compliant ships in any signatory port.</p>
<p>Maritime industry groups received the news with caution. A spokesperson for the Continental
Shipping Council acknowledged that &ldquo;stronger common rules are overdue&rdquo; but warned that
implementation costs could fall disproportionately on smaller operators.</p>
<p>The compact takes effect on January 1, pending technical annexes. Environmental observers
described the pact as the most consequential maritime accord in a decade.</p>
</BodyText>
</Article>
</Section>
<Section columns={24} divider="top" gap="2rem" style={{ marginTop: '2rem', paddingTop: '2rem' }}>
<Section
columns={24}
divider="top"
gap="2rem"
style={{ marginTop: '4rem', paddingTop: '3rem' }}
>
<Article span={24}>
<Kicker>National · Investigation</Kicker>
<Headline weight="Medium" as="h2">
Records Reveal Years of Overlooked Warnings at Aging Reservoirs
<div style={{ textAlign: 'center' }}>
<Kicker>Live Demos · Production-grade Examples</Kicker>
</div>
<Headline weight="High" align="center">
Multi-language Newspaper Showcase
</Headline>
<Subhead weight="Medium">
Internal inspection memoranda, obtained through public records requests, suggest that
structural concerns flagged repeatedly by field engineers were not escalated to senior staff.
<Subhead weight="Medium" style={{ textAlign: 'center' }}>
7 complete newspaper layouts in Chinese, English, German, and Japanese
</Subhead>
<Byline style={{ marginBottom: '1rem' }}>By Ravi Nair, Anita Kowalski, and Charles Weston</Byline>
</Article>
</Section>
<BodyText weight="High" columns={4}>
<p><Dateline>Sacramento </Dateline> A six-month review of more than four thousand pages of
inspection records, interviews with twenty-three current and former engineers, and reconstructions
of three near-failure incidents reveals a pattern of unheeded warnings about the structural
integrity of mid-twentieth-century earthen dams across the western states.</p>
<Section columns={24} gap="2rem" style={{ marginTop: '2rem' }}>
{demos.map((demo, idx) => (
<Article key={demo.href} span={24} style={{ marginBottom: '2rem' }}>
<Link
href={demo.href}
style={{ textDecoration: 'none', color: 'inherit', display: 'block' }}
>
<div
style={{
border: '1px solid var(--nui-rule-hairline)',
background: 'var(--nui-bg-surface)',
padding: '2rem',
display: 'grid',
gridTemplateColumns: '1fr 3fr',
gap: '2rem',
alignItems: 'center',
}}
>
<div
style={{
borderRight: '1px solid var(--nui-rule-hairline)',
paddingRight: '2rem',
}}
>
<div
style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '11px',
fontWeight: 600,
fontVariantCaps: 'small-caps',
letterSpacing: '0.08em',
color: demo.color,
marginBottom: '0.5rem',
}}
>
{demo.lang}
</div>
<div
style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '11px',
color: 'var(--nui-text-muted)',
}}
>
Demo #{String(idx + 1).padStart(2, '0')}
</div>
</div>
<div>
<h3
style={{
fontFamily: 'var(--font-family-display)',
fontSize: '28px',
fontWeight: 600,
lineHeight: 1.15,
color: 'var(--nui-text-primary)',
margin: '0 0 0.5rem 0',
}}
>
{demo.title}
</h3>
<p
style={{
fontFamily: 'var(--font-family-body)',
fontSize: '15px',
lineHeight: 1.5,
color: 'var(--nui-text-body)',
margin: 0,
}}
>
{demo.description}
</p>
<div
style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '12px',
fontWeight: 600,
color: 'var(--nui-accent-primary)',
marginTop: '0.75rem',
fontVariantCaps: 'small-caps',
letterSpacing: '0.06em',
}}
>
View demo
</div>
</div>
</div>
</Link>
</Article>
))}
</Section>
<p>The records show that field engineers documented concerns about seepage, erosion, and spillway
capacity in repeated annual assessments dating back at least fifteen years. In several instances,
those concerns were rated &ldquo;moderate&rdquo; in the field reports but downgraded to &ldquo;low&rdquo; by the time they
reached senior officials. The pattern was particularly pronounced at three facilities serving
regions of more than two million residents.</p>
<p>Officials at the Department of Water Resources, asked to review excerpts of the records, said
in a written statement that &ldquo;every reservoir under our oversight has been deemed safe for current
operations&rdquo; but did not specifically address the discrepancies between field and final ratings.
The agency declined to make senior staff available for interviews.</p>
<p>The findings come amid renewed scrutiny of aging infrastructure following the partial collapse
of an earthen embankment in March that displaced more than fifteen hundred residents. Federal
inspectors who responded to that incident found the proximate cause to be precisely the type of
seepage concern that field engineers had flagged in three of the past four annual assessments.</p>
<p>The investigative review found that of forty-seven reservoirs surveyed, sixteen had at least
one instance in which a &ldquo;moderate&rdquo; or &ldquo;high&rdquo; field rating was downgraded before reaching senior
management. In nine cases, the downgrades persisted for three or more consecutive years. None of
the affected facilities have publicly disclosed the discrepancies.</p>
<p>Engineering professional associations have, in recent years, called for an independent review
of inspection workflows in the western states. A spokesperson for the Society of Hydraulic
Engineers said the Society was &ldquo;deeply concerned&rdquo; by the patterns described and would convene a
working group to examine reform options.</p>
<Section
columns={24}
divider="top"
gap="2rem"
style={{ marginTop: '4rem', paddingTop: '2rem' }}
>
<Article span={12}>
<Kicker>Design Philosophy</Kicker>
<Headline weight="Low" as="h3" style={{ marginTop: 0 }}>
Print Tradition, Web Implementation
</Headline>
<BodyText weight="Low">
<p>
NewspaperUI InDesign
token visualWeights
</p>
<p>
Hybrid CSS Grid CSS Multi-column Web
</p>
</BodyText>
</Article>
<Article span={12}>
<Kicker>Tech Stack</Kicker>
<Headline weight="Low" as="h3" style={{ marginTop: 0 }}>
React 18 · TypeScript 5 · CSS Grid + Multi-column
</Headline>
<BodyText weight="Low">
<p>
4 packages<code>@newspaperui/theme</code><code>@newspaperui/utils</code>
<code>@newspaperui/components</code>18 components<code>@newspaperui/docs</code>
</p>
<p>Built with pnpm workspaces + Turborepo. Vite for libraries, Next.js 15 for docs.</p>
</BodyText>
</Article>
</Section>
+89
View File
@@ -0,0 +1,89 @@
'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
const navItems = [
{ label: 'Docs', href: '/grid-system' },
{ label: 'Components', href: '/components/article' },
{ label: 'Themes', href: '/theme' },
{ label: 'Blocks', href: '/blocks' },
];
export function Header() {
const pathname = usePathname();
return (
<header
style={{
position: 'sticky',
top: 0,
zIndex: 50,
background: 'var(--nui-bg-page)',
borderBottom: '1px solid var(--nui-rule-hairline)',
backdropFilter: 'blur(8px)',
}}
>
<div
style={{
maxWidth: '1400px',
margin: '0 auto',
padding: '1rem 2rem',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: '2rem',
}}
>
<Link
href="/"
style={{
fontFamily: 'var(--font-family-masthead)',
fontSize: '24px',
fontWeight: 700,
color: 'var(--nui-text-primary)',
textDecoration: 'none',
letterSpacing: '0.02em',
}}
>
NewspaperUI
</Link>
<nav style={{ display: 'flex', gap: '2rem' }}>
{navItems.map((item) => {
const active =
pathname === item.href ||
(item.href !== '/' && pathname.startsWith(item.href));
return (
<Link
key={item.href}
href={item.href}
style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '14px',
fontWeight: 500,
color: active
? 'var(--nui-accent-primary)'
: 'var(--nui-text-secondary)',
textDecoration: 'none',
}}
>
{item.label}
</Link>
);
})}
<a
href="https://github.com"
target="_blank"
rel="noreferrer"
style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '14px',
color: 'var(--nui-text-muted)',
textDecoration: 'none',
}}
>
GitHub
</a>
</nav>
</div>
</header>
);
}
+2 -2
View File
@@ -48,9 +48,9 @@ export function Sidebar() {
fontFamily: 'var(--font-family-meta)',
fontSize: '14px',
position: 'sticky',
top: 0,
top: 65,
alignSelf: 'flex-start',
maxHeight: '100vh',
maxHeight: 'calc(100vh - 65px)',
overflowY: 'auto',
}}
>
+3
View File
@@ -3,6 +3,9 @@ import rehypePrettyCode from 'rehype-pretty-code';
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
basePath: process.env.NEXT_PUBLIC_BASE_PATH || '',
images: { unoptimized: true },
pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'],
transpilePackages: ['@newspaperui/components', '@newspaperui/theme', '@newspaperui/utils'],
};
+3
View File
@@ -1,2 +1,5 @@
/* Google Fonts: Cormorant Garamond (masthead), Source Serif 4 (display/headline/body), Inter (meta), UnifrakturMaguntia (blackletter preset) */
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@500;600;700&family=Source+Serif+4:opsz,wght@8..60,400;8..60,500;8..60,600;8..60,700&family=Inter:wght@400;500;600;700&family=UnifrakturMaguntia&display=swap');
/* CJK: Noto Serif SC (Chinese), Noto Serif JP (Japanese) */
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700;900&family=Noto+Serif+JP:wght@400;500;600;700;900&display=swap');
+7
View File
@@ -7,6 +7,13 @@
--font-family-body: "Source Serif 4", Georgia, "Times New Roman", serif;
--font-family-meta: "Inter", system-ui, sans-serif;
/* CJK font families */
--font-family-cjk-serif: "Noto Serif SC", "Noto Serif JP", "Source Serif 4", serif;
--font-family-cjk-jp: "Noto Serif JP", "Source Serif 4", serif;
/* CJK accent (Chinese newspaper red, restrained) */
--nui-accent-cjk-red: #CC2929;
/* page background */
--nui-bg-page: #F7F4ED;
--nui-bg-surface: #FBF9F4;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 778 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB