This commit is contained in:
sunzhongyi
2026-05-20 01:30:49 +08:00
parent 7dded89537
commit 610805a374
42 changed files with 3451 additions and 0 deletions
@@ -0,0 +1,219 @@
'use client';
import {
Layout,
Section,
Article,
Layer,
Headline,
Subhead,
BodyText,
} from '@newspaperui/components';
import { Demo } from '@/components/Demo';
import { PropsTable } from '@/components/PropsTable';
export default function ArticlePage() {
return (
<Layout columns={24} maxWidth="900px" padding="2rem">
<Section columns={24}>
<Article span={24}>
<Headline weight="Medium" as="h1">
Article + Layer
</Headline>
<Subhead weight="Medium">
Article grid-column span Layer
</Subhead>
<Headline weight="Low" as="h2">
Article API
</Headline>
<PropsTable
data={[
{
name: 'span',
type: 'number',
description: '跨多少列(≤ Section.columns)。缺省时占满全宽。',
},
{
name: 'breakable',
type: 'boolean',
default: 'true',
description: '允许打印时跨页断开。',
},
{
name: 'className',
type: 'string',
description: '自定义 CSS 类名。',
},
{
name: 'style',
type: 'CSSProperties',
description: '自定义内联样式。',
},
{
name: 'children',
type: 'ReactNode',
required: true,
description: '文章内容。',
},
]}
/>
<Headline weight="Low" as="h2">
Demo
</Headline>
<Demo
title="8 + 16 跨栏"
description="左侧 8 列 + 右侧 16 列,模拟短讯 + 主稿布局。"
code={`<Layout columns={24}>
<Section columns={24}>
<Article span={8}>
<Headline weight="Low">短讯</Headline>
<BodyText>...</BodyText>
</Article>
<Article span={16}>
<Headline weight="Medium">主稿</Headline>
<BodyText columns={2}>...</BodyText>
</Article>
</Section>
</Layout>`}
>
<Layout columns={24} padding="0">
<Section columns={24}>
<Article span={8}>
<Headline weight="Low" as="h3">
</Headline>
<BodyText weight="Low">
<p>
Markets responded cautiously through the morning session. The pound
traded sideways against the dollar, gilts firmed by three basis points.
</p>
</BodyText>
</Article>
<Article span={16}>
<Headline weight="Medium" as="h3">
稿
</Headline>
<BodyText columns={2}>
<p>
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.
</p>
<p>
Critics inside the cabinet caution that the timing risks overshadowing
the chancellor&rsquo;s autumn statement, while supporters describe the
proposals as the most coherent strategic blueprint in a generation.
</p>
</BodyText>
</Article>
</Section>
</Layout>
</Demo>
<Headline weight="Low" as="h2" style={{ marginTop: '2rem' }}>
Layer API
</Headline>
<BodyText weight="Low">
<p>
Layer 使 CSS position 广sticky
</p>
</BodyText>
<PropsTable
data={[
{
name: 'position',
type: "'absolute' | 'fixed' | 'sticky'",
default: "'absolute'",
description: 'CSS position 属性。',
},
{
name: 'top',
type: 'string | number',
description: '距离顶部的距离。',
},
{
name: 'left',
type: 'string | number',
description: '距离左侧的距离。',
},
{
name: 'right',
type: 'string | number',
description: '距离右侧的距离。',
},
{
name: 'bottom',
type: 'string | number',
description: '距离底部的距离。',
},
{
name: 'zIndex',
type: 'number',
description: 'z-index 层级。',
},
{
name: 'children',
type: 'ReactNode',
required: true,
description: '浮动层内容。',
},
]}
/>
<Demo
title="Layer 浮动拉引"
description="在文章旁边添加浮动的拉引文字。父容器需要 position: relative。"
code={`<div style={{ position: 'relative', minHeight: '200px' }}>
<Article span={16}>
<Headline weight="Low">主要文章</Headline>
<BodyText>...</BodyText>
</Article>
<Layer position="absolute" top="0" right="0">
<aside>浮动内容</aside>
</Layer>
</div>`}
>
<Layout columns={24} padding="0">
<Section columns={24}>
<div style={{ position: 'relative', minHeight: '200px', gridColumn: 'span 24' }}>
<Article span={16}>
<Headline weight="Low" as="h3">
</Headline>
<BodyText>
<p>
In Manchester, regional officials greeted the announcement with
measured optimism. The mayor&rsquo;s office is expected to issue a
formal response by week&rsquo;s end.
</p>
</BodyText>
</Article>
<Layer position="absolute" top="0" right="0">
<aside
style={{
width: '180px',
padding: '1rem',
borderTop: '1px solid var(--nui-rule-hairline)',
borderBottom: '1px solid var(--nui-rule-hairline)',
fontFamily: 'var(--font-family-display)',
fontSize: '18px',
lineHeight: 1.3,
color: 'var(--nui-text-primary)',
}}
>
&ldquo;We have lobbied for this kind of clarity for the better part of
a decade.&rdquo;
</aside>
</Layer>
</div>
</Section>
</Layout>
</Demo>
</Article>
</Section>
</Layout>
);
}
@@ -0,0 +1,148 @@
'use client';
import {
Layout,
Section,
Article,
Headline,
Subhead,
BodyText,
Masthead,
} from '@newspaperui/components';
import { Demo } from '@/components/Demo';
import { PropsTable } from '@/components/PropsTable';
export default function MastheadPage() {
return (
<Layout columns={24} maxWidth="900px" padding="2rem">
<Section columns={24}>
<Article span={24}>
<Headline weight="Medium" as="h1">
Masthead
</Headline>
<Subhead weight="Medium">
variant 线
</Subhead>
<Headline weight="Low" as="h2">
API
</Headline>
<PropsTable
data={[
{
name: 'title',
type: 'string',
required: true,
description: '报名文字。',
},
{
name: 'variant',
type: "'classic' | 'blackletter' | 'modern'",
default: "'classic'",
description: '视觉风格。',
},
{
name: 'kicker',
type: 'string',
description: '报名上方的小标(如 "All the News That\'s Fit to Print")。',
},
{
name: 'edition',
type: 'string',
description: '版次(如 "Vol. CLXXII No. 59,678")。',
},
{
name: 'date',
type: 'string',
description: '日期(如 "Monday, May 19, 2026")。',
},
{
name: 'price',
type: 'string',
description: '售价(如 "$3.00")。',
},
]}
/>
<Headline weight="Low" as="h2">
Classic
</Headline>
<Demo
title="classic variant"
description="双线居中,Cormorant Garamond 衬线。"
code={`<Masthead
variant="classic"
title="The Daily Chronicle"
kicker="All the News That's Fit to Print"
edition="Vol. CLXXII No. 59,678"
date="Monday, May 19, 2026"
price="$3.00"
/>`}
>
<Masthead
variant="classic"
title="The Daily Chronicle"
kicker="All the News That's Fit to Print"
edition="Vol. CLXXII No. 59,678"
date="Monday, May 19, 2026"
price="$3.00"
/>
</Demo>
<Headline weight="Low" as="h2">
Blackletter
</Headline>
<Demo
title="blackletter variant"
description="UnifrakturMaguntia 哥特体,The Times 风格。"
code={`<Masthead
variant="blackletter"
title="The Evening Standard"
edition="Late Final Edition"
date="Monday, May 19, 2026"
price="£2.50"
/>`}
>
<Masthead
variant="blackletter"
title="The Evening Standard"
edition="Late Final Edition"
date="Monday, May 19, 2026"
price="£2.50"
/>
</Demo>
<Headline weight="Low" as="h2">
Modern
</Headline>
<Demo
title="modern variant"
description="左对齐 + accent 强调色,适合数字优先的出版物。"
code={`<Masthead
variant="modern"
title="The Observer"
kicker="Sunday Edition"
date="May 19, 2026"
/>`}
>
<Masthead
variant="modern"
title="The Observer"
kicker="Sunday Edition"
date="May 19, 2026"
/>
</Demo>
<Headline weight="Low" as="h2">
使
</Headline>
<BodyText weight="Low">
<p>
Masthead <code>gridColumn: 1 / -1</code> Section
Layout Section Rule 线
</p>
</BodyText>
</Article>
</Section>
</Layout>
);
}
@@ -0,0 +1,166 @@
'use client';
import {
Layout,
Section,
Article,
Headline,
Subhead,
BodyText,
Figure,
PullQuote,
} from '@newspaperui/components';
import { Demo } from '@/components/Demo';
import { PropsTable } from '@/components/PropsTable';
export default function MediaPage() {
return (
<Layout columns={24} maxWidth="900px" padding="2rem">
<Section columns={24}>
<Article span={24}>
<Headline weight="Medium" as="h1">
</Headline>
<Subhead weight="Medium">
ImageFigureVideoPullQuote
</Subhead>
<Headline weight="Low" as="h2">
Image
</Headline>
<BodyText weight="Low">
<p>
<code>display: block; width: 100%</code> Section
span
</p>
</BodyText>
<PropsTable
data={[
{ name: 'src', type: 'string', required: true, description: '图片 URL。' },
{ name: 'alt', type: 'string', required: true, description: '替代文本。' },
{ name: 'span', type: 'number', description: '跨栏数。' },
]}
/>
<Headline weight="Low" as="h2">
Figure
</Headline>
<BodyText weight="Low">
<p>
Image + Caption + Credit figcaption
</p>
</BodyText>
<PropsTable
data={[
{ name: 'src', type: 'string', required: true, description: '图片 URL。' },
{ name: 'alt', type: 'string', required: true, description: '替代文本。' },
{ name: 'caption', type: 'string', description: '图片说明。' },
{ name: 'credit', type: 'string', description: '摄影师/来源(small-caps 渲染)。' },
{ name: 'span', type: 'number', description: '跨栏数。' },
]}
/>
<Demo
title="Figure 带 caption 和 credit"
description="使用 Unsplash 占位图演示完整效果。"
code={`<Figure
src="https://images.unsplash.com/photo-1495020689067-958852a7765e?w=800&h=400&fit=crop"
alt="Newspapers on a wooden table"
caption="A view of the morning editions, arranged on the newsroom table."
credit="Photograph by Roman Kraft / Unsplash"
/>`}
>
<Figure
src="https://images.unsplash.com/photo-1495020689067-958852a7765e?w=800&h=400&fit=crop"
alt="Newspapers on a wooden table"
caption="A view of the morning editions, arranged on the newsroom table."
credit="Photograph by Roman Kraft / Unsplash"
/>
</Demo>
<Headline weight="Low" as="h2">
Video
</Headline>
<PropsTable
data={[
{ name: 'src', type: 'string', required: true, description: '视频 URL。' },
{ name: 'poster', type: 'string', description: '封面图 URL。' },
{ name: 'caption', type: 'string', description: '视频说明。' },
{ name: 'credit', type: 'string', description: '来源。' },
{ name: 'controls', type: 'boolean', default: 'true', description: '显示播放控件。' },
{ name: 'span', type: 'number', description: '跨栏数。' },
]}
/>
<BodyText weight="Low">
<p>
Video Figure <code>&lt;video&gt;</code>
caption/credit
</p>
</BodyText>
<Headline weight="Low" as="h2">
PullQuote
</Headline>
<BodyText weight="Low">
<p>
hairline + Display BodyText
<code>spanAllColumns</code> <code>column-span: all</code>
</p>
</BodyText>
<PropsTable
data={[
{ name: 'weight', type: "'High' | 'Medium'", default: "'High'", description: '视觉权重。' },
{ name: 'span', type: 'number', description: '在 Section 栅格内跨栏。' },
{ name: 'spanAllColumns', type: 'boolean', default: 'false', description: '在多栏 BodyText 内跨所有栏。' },
{ name: 'author', type: 'string', description: '引用来源。' },
{ name: 'align', type: "'left' | 'center'", default: "'left'", description: '文本对齐。' },
]}
/>
<Demo
title="PullQuote 独立使用"
code={`<PullQuote author="Senior Cabinet Official">
We have lobbied for this kind of clarity for the better part of a decade.
</PullQuote>`}
>
<PullQuote author="Senior Cabinet Official">
We have lobbied for this kind of clarity for the better part of a decade.
</PullQuote>
</Demo>
<Demo
title="PullQuote 在多栏 BodyText 内跨栏"
description="spanAllColumns 使 PullQuote 通过 column-span: all 跨越所有文字栏。"
code={`<BodyText columns={3}>
<p>...</p>
<PullQuote spanAllColumns author="...">...</PullQuote>
<p>...</p>
</BodyText>`}
>
<BodyText columns={3}>
<p>
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.
</p>
<PullQuote spanAllColumns author="Senior Cabinet Official">
The most coherent strategic blueprint in a generation.
</PullQuote>
<p>
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&rsquo;s modest outflows.
</p>
<p>
In Manchester, regional officials greeted the announcement with measured
optimism. The mayor&rsquo;s office is expected to issue a formal response by
week&rsquo;s end, focusing on commitments to the trans-Pennine corridor.
</p>
</BodyText>
</Demo>
</Article>
</Section>
</Layout>
);
}
@@ -0,0 +1,134 @@
'use client';
import {
Layout,
Section,
Article,
Headline,
Subhead,
BodyText,
Rule,
} from '@newspaperui/components';
import { Demo } from '@/components/Demo';
import { PropsTable } from '@/components/PropsTable';
export default function RulePage() {
return (
<Layout columns={24} maxWidth="900px" padding="2rem">
<Section columns={24}>
<Article span={24}>
<Headline weight="Medium" as="h1">
Rule 线
</Headline>
<Subhead weight="Medium">
线 variant hairlinedoublethick
</Subhead>
<Headline weight="Low" as="h2">
API
</Headline>
<PropsTable
data={[
{
name: 'variant',
type: "'hairline' | 'double' | 'thick'",
default: "'hairline'",
description: '线型。',
},
{
name: 'orientation',
type: "'horizontal' | 'vertical'",
default: "'horizontal'",
description: '方向。',
},
{
name: 'span',
type: 'number',
description: '横向时占多少列。缺省时 1 / -1 全跨。',
},
{
name: 'className',
type: 'string',
description: '自定义 CSS 类名。',
},
{
name: 'style',
type: 'CSSProperties',
description: '自定义内联样式。',
},
]}
/>
<Headline weight="Low" as="h2">
variant
</Headline>
<Demo title="hairline / double / thick" description="水平分隔线对照。">
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
<div>
<BodyText weight="Low">
<p>hairline</p>
</BodyText>
<Rule variant="hairline" />
</div>
<div>
<BodyText weight="Low">
<p>double</p>
</BodyText>
<Rule variant="double" />
</div>
<div>
<BodyText weight="Low">
<p>thick</p>
</BodyText>
<Rule variant="thick" />
</div>
</div>
</Demo>
<Headline weight="Low" as="h2">
</Headline>
<Demo
title="垂直分隔线"
description="在两栏之间放置垂直 Rule。"
code={`<div style={{ display: 'flex', gap: '1.5rem', height: '120px' }}>
<div>左栏内容</div>
<Rule variant="hairline" orientation="vertical" />
<div>右栏内容</div>
</div>`}
>
<div style={{ display: 'flex', gap: '1.5rem', height: '120px', alignItems: 'stretch' }}>
<div style={{ flex: 1 }}>
<BodyText weight="Low">
<p>
Markets responded cautiously through the morning session. The pound
traded sideways against the dollar.
</p>
</BodyText>
</div>
<Rule variant="hairline" orientation="vertical" />
<div style={{ flex: 1 }}>
<BodyText weight="Low">
<p>
Analysts at three of the City&rsquo;s largest houses framed the move as
a holding pattern.
</p>
</BodyText>
</div>
</div>
</Demo>
<Headline weight="Low" as="h2">
使
</Headline>
<BodyText weight="Low">
<p>
Rule Section <code>gridColumn: 1 / -1</code>
<code>span</code> prop Rule
flex
</p>
</BodyText>
</Article>
</Section>
</Layout>
);
}
@@ -0,0 +1,258 @@
'use client';
import {
Layout,
Section,
Article,
Headline,
Subhead,
BodyText,
Rule,
} from '@newspaperui/components';
import { CodeBlock } from '@/components/CodeBlock';
export default function ResponsivePage() {
return (
<Layout columns={24} maxWidth="900px" padding="2rem">
<Section columns={24}>
<Article span={24}>
<Headline weight="Medium" as="h1">
</Headline>
<Subhead weight="Medium">
NewspaperUI CSS media query + container query
JavaScript
</Subhead>
<Headline weight="Low" as="h2">
</Headline>
<BodyText>
<p>
</p>
</BodyText>
<div style={{ overflowX: 'auto', margin: '1rem 0 2rem' }}>
<table
style={{
width: '100%',
borderCollapse: 'collapse',
fontFamily: 'var(--font-family-meta)',
fontSize: '13px',
}}
>
<thead>
<tr style={{ borderBottom: '2px solid var(--nui-rule-decorative)' }}>
<th style={{ textAlign: 'left', padding: '0.5rem' }}></th>
<th style={{ textAlign: 'left', padding: '0.5rem' }}></th>
<th style={{ textAlign: 'left', padding: '0.5rem' }}></th>
<th style={{ textAlign: 'left', padding: '0.5rem' }}></th>
</tr>
</thead>
<tbody>
<tr style={{ borderBottom: '1px solid var(--nui-rule-hairline)' }}>
<td style={{ padding: '0.5rem' }}>Mobile</td>
<td style={{ padding: '0.5rem' }}>&lt; 768px</td>
<td style={{ padding: '0.5rem' }}>1 </td>
<td style={{ padding: '0.5rem' }}>BodyText columns=1</td>
</tr>
<tr style={{ borderBottom: '1px solid var(--nui-rule-hairline)', background: 'var(--nui-bg-surface)' }}>
<td style={{ padding: '0.5rem' }}>Tablet</td>
<td style={{ padding: '0.5rem' }}>768px - 1024px</td>
<td style={{ padding: '0.5rem' }}>12 </td>
<td style={{ padding: '0.5rem' }}>BodyText columns=2</td>
</tr>
<tr style={{ borderBottom: '1px solid var(--nui-rule-hairline)' }}>
<td style={{ padding: '0.5rem' }}>Desktop</td>
<td style={{ padding: '0.5rem' }}>&gt; 1024px</td>
<td style={{ padding: '0.5rem' }}>24 </td>
<td style={{ padding: '0.5rem' }}></td>
</tr>
</tbody>
</table>
</div>
<Headline weight="Low" as="h2">
</Headline>
<BodyText>
<p>
NewspaperUI 使 JavaScript responsive CSS
media query container query
</p>
<p>
Section <code>gridTemplateColumns</code> inline style
CSS
</p>
</BodyText>
<CodeBlock
title="自定义响应式 CSS"
language="css"
code={`/* 在你的 globals.css 或组件 CSS 中 */
@media (max-width: 768px) {
.nui-section {
grid-template-columns: 1fr !important;
}
.nui-article {
grid-column: span 1 !important;
}
}
@media (min-width: 769px) and (max-width: 1024px) {
.nui-section[data-columns="24"] {
grid-template-columns: repeat(12, 1fr) !important;
}
}`}
/>
<BodyText>
<p>
使 container query Section
</p>
</BodyText>
<CodeBlock
title="Container Query 方案"
language="css"
code={`/* 给 Section 添加 container-type */
.nui-section {
container-type: inline-size;
}
@container (max-width: 600px) {
.nui-article {
grid-column: 1 / -1 !important;
}
}`}
/>
<Rule variant="hairline" />
<Headline weight="Low" as="h2">
</Headline>
<BodyText weight="Low">
<p>
使
DevTools responsive mode
</p>
</BodyText>
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem', margin: '1.5rem 0' }}>
<div>
<div
className="nui-small-caps"
style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '11px',
color: 'var(--nui-text-muted)',
letterSpacing: '0.08em',
marginBottom: '0.5rem',
}}
>
Desktop (1024px+) &mdash; 24
</div>
<div
style={{
border: '1px solid var(--nui-rule-hairline)',
padding: '1rem',
background: 'var(--nui-bg-surface)',
}}
>
<Layout columns={24} padding="0" maxWidth="100%">
<Section columns={24}>
<Article span={6}>
<Headline weight="Low" as="h4">Briefing</Headline>
<BodyText weight="Low"><p>Short news items.</p></BodyText>
</Article>
<Article span={12}>
<Headline weight="Medium" as="h4">Lead Story</Headline>
<BodyText><p>Main article content with full detail.</p></BodyText>
</Article>
<Article span={6}>
<Headline weight="Low" as="h4">Markets</Headline>
<BodyText weight="Low"><p>FTSE, gilts, sterling.</p></BodyText>
</Article>
</Section>
</Layout>
</div>
</div>
<div>
<div
className="nui-small-caps"
style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '11px',
color: 'var(--nui-text-muted)',
letterSpacing: '0.08em',
marginBottom: '0.5rem',
}}
>
Tablet (768-1024px) &mdash; 12
</div>
<div
style={{
border: '1px solid var(--nui-rule-hairline)',
padding: '1rem',
background: 'var(--nui-bg-surface)',
maxWidth: '600px',
}}
>
<Layout columns={12} padding="0" maxWidth="100%">
<Section columns={12}>
<Article span={6}>
<Headline weight="Low" as="h4">Lead Story</Headline>
<BodyText weight="Low"><p>Main article.</p></BodyText>
</Article>
<Article span={6}>
<Headline weight="Low" as="h4">Secondary</Headline>
<BodyText weight="Low"><p>Supporting content.</p></BodyText>
</Article>
</Section>
</Layout>
</div>
</div>
<div>
<div
className="nui-small-caps"
style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '11px',
color: 'var(--nui-text-muted)',
letterSpacing: '0.08em',
marginBottom: '0.5rem',
}}
>
Mobile (&lt;768px) &mdash;
</div>
<div
style={{
border: '1px solid var(--nui-rule-hairline)',
padding: '1rem',
background: 'var(--nui-bg-surface)',
maxWidth: '375px',
}}
>
<Layout columns={1} padding="0" maxWidth="100%">
<Section columns={1}>
<Article span={1}>
<Headline weight="Low" as="h4">Lead Story</Headline>
<BodyText weight="Low"><p>Full-width single column.</p></BodyText>
</Article>
<Article span={1}>
<Headline weight="Low" as="h4">Secondary</Headline>
<BodyText weight="Low"><p>Stacked below.</p></BodyText>
</Article>
</Section>
</Layout>
</div>
</div>
</div>
</Article>
</Section>
</Layout>
);
}
@@ -0,0 +1,236 @@
'use client';
import {
Layout,
Section,
Article,
Headline,
Subhead,
BodyText,
Rule,
} from '@newspaperui/components';
import { Demo } from '@/components/Demo';
export default function SpanningPage() {
return (
<Layout columns={24} maxWidth="900px" padding="2rem">
<Section columns={24}>
<Article span={24}>
<Headline weight="Medium" as="h1">
</Headline>
<Subhead weight="Medium">
24
</Subhead>
</Article>
</Section>
<Rule variant="hairline" />
<Section columns={24}>
<Article span={24}>
<Headline weight="Low" as="h2">
8 + 16
</Headline>
</Article>
</Section>
<Demo title="8 + 16" description="短讯 + 主稿。">
<Layout columns={24} padding="0">
<Section columns={24}>
<Article span={8}>
<Headline weight="Low" as="h3">
Briefing
</Headline>
<BodyText weight="Low">
<p>
Markets responded cautiously through the morning session. The pound
traded sideways against the dollar.
</p>
</BodyText>
</Article>
<Article span={16}>
<Headline weight="Medium" as="h3">
Infrastructure Review Tabled
</Headline>
<BodyText>
<p>
Whitehall officials confirmed late Tuesday that the long-anticipated
review of national infrastructure funding will be tabled before the
recess. The 248-page document recommends a recalibration of regional
priorities.
</p>
</BodyText>
</Article>
</Section>
</Layout>
</Demo>
<Section columns={24}>
<Article span={24}>
<Headline weight="Low" as="h2">
6 + 12 + 6
</Headline>
</Article>
</Section>
<Demo title="6 + 12 + 6" description="三栏对称布局,中间主体 + 两侧辅助。">
<Layout columns={24} padding="0">
<Section columns={24}>
<Article span={6}>
<Headline weight="Low" as="h3">
Weather
</Headline>
<BodyText weight="Low">
<p>Partly cloudy, 18C. Wind NW 12 mph. Sunset 20:47.</p>
</BodyText>
</Article>
<Article span={12}>
<Headline weight="Medium" as="h3">
Chancellor Outlines Spending Envelope
</Headline>
<BodyText>
<p>
The chancellor confirmed a three-year spending envelope that prioritizes
rail electrification and regional connectivity. The announcement was
greeted with cautious optimism across the House.
</p>
</BodyText>
</Article>
<Article span={6}>
<Headline weight="Low" as="h3">
Markets
</Headline>
<BodyText weight="Low">
<p>FTSE 100: 7,842 (-0.2%). Gilts +3bp. Sterling flat.</p>
</BodyText>
</Article>
</Section>
</Layout>
</Demo>
<Section columns={24}>
<Article span={24}>
<Headline weight="Low" as="h2">
12 + 12
</Headline>
</Article>
</Section>
<Demo title="12 + 12" description="对称双栏,适合对比报道或并列文章。">
<Layout columns={24} padding="0">
<Section columns={24}>
<Article span={12}>
<Headline weight="Low" as="h3">
View from Westminster
</Headline>
<BodyText>
<p>
Critics inside the cabinet caution that the timing risks overshadowing
the chancellor&rsquo;s autumn statement. The opposition has called for a
full debate before any commitments are made.
</p>
</BodyText>
</Article>
<Article span={12}>
<Headline weight="Low" as="h3">
View from the Regions
</Headline>
<BodyText>
<p>
In Manchester, regional officials greeted the announcement with measured
optimism. The mayor&rsquo;s office is expected to issue a formal response
by week&rsquo;s end.
</p>
</BodyText>
</Article>
</Section>
</Layout>
</Demo>
<Section columns={24}>
<Article span={24}>
<Headline weight="Low" as="h2">
4 + 16 + 4
</Headline>
</Article>
</Section>
<Demo title="4 + 16 + 4" description="窄侧栏 + 宽主体,适合带注释的长文。">
<Layout columns={24} padding="0">
<Section columns={24}>
<Article span={4}>
<BodyText weight="Low">
<p style={{ fontStyle: 'italic', fontSize: '12px' }}>
Editor&rsquo;s note: This report was filed before the evening session.
</p>
</BodyText>
</Article>
<Article span={16}>
<Headline weight="Medium" as="h3">
A Standing Technical Commission
</Headline>
<BodyText>
<p>
Beyond the immediate fiscal arithmetic, the review&rsquo;s most
consequential proposal may be its quietest: a standing technical
commission, modeled on Australia&rsquo;s Infrastructure Australia, to
depoliticize project sequencing.
</p>
</BodyText>
</Article>
<Article span={4}>
<BodyText weight="Low">
<p style={{ fontStyle: 'italic', fontSize: '12px' }}>
Related: &ldquo;How Australia reformed infrastructure planning&rdquo;
&mdash; p. 12
</p>
</BodyText>
</Article>
</Section>
</Layout>
</Demo>
<Section columns={24}>
<Article span={24}>
<Headline weight="Low" as="h2">
24
</Headline>
</Article>
</Section>
<Demo title="24 全宽" description="单篇全宽文章,适合社论或特稿。">
<Layout columns={24} padding="0">
<Section columns={24}>
<Article span={24}>
<Headline weight="High" as="h3">
The Quiet Revolution in Treasury Forecasting
</Headline>
<BodyText columns={4} dropCap>
<p>
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.
</p>
<p>
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&rsquo;s modest outflows.
</p>
<p>
In Manchester, regional officials greeted the announcement with measured
optimism. The mayor&rsquo;s office is expected to issue a formal response
by week&rsquo;s end, focusing on commitments to the trans-Pennine
corridor and the long-deferred upgrade of suburban tram capacity.
</p>
<p>
Beyond the immediate fiscal arithmetic, the review&rsquo;s most
consequential proposal may be its quietest: a standing technical
commission to depoliticize project sequencing. Whether that body acquires
teeth will be determined by the legislation expected in the spring.
</p>
</BodyText>
</Article>
</Section>
</Layout>
</Demo>
</Layout>
);
}
@@ -0,0 +1,225 @@
'use client';
import {
Layout,
Section,
Article,
Headline,
Subhead,
BodyText,
} from '@newspaperui/components';
import { Demo } from '@/components/Demo';
import { PropsTable } from '@/components/PropsTable';
export default function GridSystemPage() {
return (
<Layout columns={24} maxWidth="900px" padding="2rem">
<Section columns={24}>
<Article span={24}>
<Headline weight="Medium" as="h1">
</Headline>
<Subhead weight="Medium">
24 Layout Section grid-template-columns
Article grid-column span CSS Grid
</Subhead>
<Headline weight="Low" as="h2">
24
</Headline>
<BodyText>
<p>
24 24
2 / 3 / 4 / 6 / 8 / 12 1/32/31/43/4
</p>
</BodyText>
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(24, 1fr)',
gap: '4px',
margin: '1.5rem 0 2rem',
}}
>
{Array.from({ length: 24 }, (_, i) => (
<div
key={i}
style={{
background: 'var(--nui-bg-surface)',
border: '1px solid var(--nui-rule-hairline)',
textAlign: 'center',
padding: '0.5rem 0',
fontFamily: 'var(--font-family-meta)',
fontSize: '11px',
color: 'var(--nui-text-muted)',
letterSpacing: '0.04em',
}}
>
{i + 1}
</div>
))}
</div>
<Headline weight="Low" as="h2">
Layout API
</Headline>
<BodyText>
<p>
<code>Layout</code> LayoutContextSection
useLayout clamp
</p>
</BodyText>
<PropsTable
data={[
{
name: 'columns',
type: 'number',
default: '24',
description: '栅格总列数。决定子 Section 的最大 columns。',
},
{
name: 'maxWidth',
type: 'string',
default: "'1280px'",
description: '页面最大宽度。',
},
{
name: 'padding',
type: 'string',
default: "'var(--nui-space-6)'",
description: '页面内边距。',
},
{
name: 'theme',
type: "'light' | 'dark'",
description:
'强制主题;省略时跟随 documentElement.dataset.theme。',
},
{
name: 'children',
type: 'ReactNode',
required: true,
description: '子内容(通常是若干 Section)。',
},
]}
/>
<Headline weight="Low" as="h2">
Section API
</Headline>
<BodyText>
<p>
<code>Section</code>
<code>display: grid; grid-template-columns: repeat(N, 1fr)</code>
Article grid-column span
</p>
</BodyText>
<PropsTable
data={[
{
name: 'columns',
type: 'number',
required: true,
description: 'Section 内部栅格列数(≤ Layout.columns)。',
},
{
name: 'gap',
type: 'string',
default: "'var(--nui-gutter)'",
description: '栏间间距。',
},
{
name: 'breakable',
type: 'boolean',
default: 'true',
description: '允许打印时跨页断开。',
},
{
name: 'divider',
type: "'none' | 'top' | 'bottom' | 'both'",
default: "'none'",
description: '上下方向的 hairline 分隔线。',
},
]}
/>
<Headline weight="Low" as="h2">
Article API
</Headline>
<BodyText>
<p>
<code>Article</code> Section grid-column span N
span Section
</p>
</BodyText>
<PropsTable
data={[
{
name: 'span',
type: 'number',
description: '跨多少列(0 &lt; span ≤ Section.columns)。',
},
{
name: 'breakable',
type: 'boolean',
default: 'true',
description: '允许打印时跨页断开。',
},
{
name: 'children',
type: 'ReactNode',
required: true,
description: '文章内容。',
},
]}
/>
<Headline weight="Low" as="h2">
</Headline>
<Demo
title="8 + 16 跨栏"
description="左侧短讯 8 列 + 右侧主稿 16 列。"
code={`<Layout columns={24}>
<Section columns={24}>
<Article span={8}>
<Headline weight="Low">短讯</Headline>
<BodyText>...</BodyText>
</Article>
<Article span={16}>
<Headline weight="Medium">主稿</Headline>
<BodyText>...</BodyText>
</Article>
</Section>
</Layout>`}
>
<Layout columns={24} padding="0">
<Section columns={24}>
<Article span={8}>
<Headline weight="Low" as="h3">
</Headline>
<BodyText weight="Low">
<p> 8 </p>
</BodyText>
</Article>
<Article span={16}>
<Headline weight="Medium" as="h3">
稿
</Headline>
<BodyText>
<p>
16 稿
</p>
</BodyText>
</Article>
</Section>
</Layout>
</Demo>
</Article>
</Section>
</Layout>
);
}
+19
View File
@@ -0,0 +1,19 @@
import { Sidebar } from '../../components/Sidebar';
export default function DocsLayout({ children }: { children: React.ReactNode }) {
return (
<div style={{ display: 'flex', minHeight: '100vh' }}>
<Sidebar />
<main
style={{
flex: 1,
padding: '2rem 3rem',
maxWidth: 'calc(100% - 240px)',
overflow: 'auto',
}}
>
{children}
</main>
</div>
);
}
+266
View File
@@ -0,0 +1,266 @@
'use client';
import {
Layout,
Section,
Article,
Headline,
Subhead,
Kicker,
BodyText,
Quote,
Byline,
Dateline,
Caption,
} from '@newspaperui/components';
import { visualWeights, resolveFontSize } from '@newspaperui/theme';
import { Demo } from '@/components/Demo';
const longText = `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.`;
const longText2 = `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.`;
const longText3 = `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.`;
const longText4 = `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.`;
interface WeightRow {
component: string;
weight: string;
fontFamily: string;
fontSize: string;
fontWeight: number;
lineHeight: number;
color: string;
}
function buildWeightRows(): WeightRow[] {
const rows: WeightRow[] = [];
for (const [comp, weights] of Object.entries(visualWeights)) {
for (const [w, cfg] of Object.entries(weights)) {
if (!cfg) continue;
rows.push({
component: comp,
weight: w,
fontFamily: cfg.fontFamily,
fontSize: resolveFontSize(cfg.fontSize),
fontWeight: cfg.fontWeight,
lineHeight: cfg.lineHeight,
color: cfg.color,
});
}
}
return rows;
}
export default function TextPage() {
const weightRows = buildWeightRows();
return (
<Layout columns={24} maxWidth="900px" padding="2rem">
<Section columns={24}>
<Article span={24}>
<Headline weight="Medium" as="h1">
</Headline>
<Subhead weight="Medium">
Headline Caption
token
</Subhead>
<Headline weight="Low" as="h2">
Headline
</Headline>
<Demo title="High / Medium / Low">
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
<div>
<Kicker>weight=&quot;High&quot;</Kicker>
<Headline weight="High" as="h3">
A Quiet Revolution in the Treasury Forecast
</Headline>
</div>
<div>
<Kicker>weight=&quot;Medium&quot;</Kicker>
<Headline weight="Medium" as="h3">
Whitehall Confirms Infrastructure Review
</Headline>
</div>
<div>
<Kicker>weight=&quot;Low&quot;</Kicker>
<Headline weight="Low" as="h3">
Briefing: regional rail commitments
</Headline>
</div>
</div>
</Demo>
<Headline weight="Low" as="h2">
Subhead
</Headline>
<Demo title="High / Medium">
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
<Subhead weight="High">
A measured recalibration of regional priorities is expected to define the
chancellor&rsquo;s autumn agenda.
</Subhead>
<Subhead weight="Medium">
Officials emphasized that the headline figures should be read as a planning
envelope rather than a binding allocation.
</Subhead>
</div>
</Demo>
<Headline weight="Low" as="h2">
Kicker
</Headline>
<Demo title="朱红 small-caps,挂在 Headline 上方">
<div>
<Kicker>POLITICS · WHITEHALL</Kicker>
<Headline weight="Medium" as="h3">
A Standing Technical Commission, Quietly Proposed
</Headline>
</div>
</Demo>
<Headline weight="Low" as="h2">
BodyText
</Headline>
<Demo title="单栏" description="默认形态,适合中等宽度的文章正文。">
<BodyText>
<p>{longText}</p>
<p>{longText2}</p>
</BodyText>
</Demo>
<Demo
title="三栏 + 首字下沉"
description="开启 columns={3} 与 dropCap,第一段首字母自动下沉占 2-3 行。"
code={`<BodyText columns={3} dropCap>
<p>...</p>
<p>...</p>
</BodyText>`}
>
<BodyText columns={3} dropCap>
<p>{longText}</p>
<p>{longText2}</p>
<p>{longText3}</p>
<p>{longText4}</p>
</BodyText>
</Demo>
<Demo
title="两栏(无 dropCap"
description="columns={2},栏间细线由 nui-column-rule 提供。"
>
<BodyText columns={2}>
<p>{longText}</p>
<p>{longText2}</p>
<p>{longText3}</p>
</BodyText>
</Demo>
<Headline weight="Low" as="h2">
Quote
</Headline>
<Demo title="block / inline 对照">
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
<Quote variant="block">
We have lobbied for this kind of clarity for the better part of a decade.
</Quote>
<BodyText>
<p>
<Quote variant="inline">
</Quote>
</p>
</BodyText>
</div>
</Demo>
<Headline weight="Low" as="h2">
Byline / Dateline / Caption
</Headline>
<Demo title="元信息组件">
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
<div>
<Byline>BY ALICE SMITH</Byline>
<Dateline>LONDON &mdash;</Dateline>
</div>
<figure style={{ margin: 0 }}>
<div
style={{
height: '160px',
background: 'var(--nui-bg-surface)',
border: '1px solid var(--nui-rule-hairline)',
}}
/>
<Caption credit="Photograph by Jane Doe">
A view of the Treasury terrace at dusk; the new commission will report
here from May.
</Caption>
</figure>
</div>
</Demo>
<Headline weight="Low" as="h2">
</Headline>
<BodyText weight="Low">
<p>
<code>visualWeights</code>
token theme
</p>
</BodyText>
<div style={{ overflowX: 'auto', margin: '1rem 0 2rem' }}>
<table
style={{
width: '100%',
borderCollapse: 'collapse',
fontFamily: 'var(--font-family-meta)',
fontSize: '13px',
}}
>
<thead>
<tr style={{ borderBottom: '2px solid var(--nui-rule-decorative)' }}>
<th style={{ textAlign: 'left', padding: '0.5rem' }}></th>
<th style={{ textAlign: 'left', padding: '0.5rem' }}></th>
<th style={{ textAlign: 'left', padding: '0.5rem' }}></th>
<th style={{ textAlign: 'left', padding: '0.5rem' }}></th>
<th style={{ textAlign: 'left', padding: '0.5rem' }}></th>
<th style={{ textAlign: 'left', padding: '0.5rem' }}></th>
<th style={{ textAlign: 'left', padding: '0.5rem' }}></th>
</tr>
</thead>
<tbody>
{weightRows.map((row, idx) => (
<tr
key={`${row.component}-${row.weight}`}
style={{
borderBottom: '1px solid var(--nui-rule-hairline)',
background:
idx % 2 === 0 ? 'transparent' : 'var(--nui-bg-surface)',
}}
>
<td style={{ padding: '0.5rem' }}>{row.component}</td>
<td style={{ padding: '0.5rem' }}>{row.weight}</td>
<td style={{ padding: '0.5rem', fontSize: '11px' }}>
<code>{row.fontFamily}</code>
</td>
<td style={{ padding: '0.5rem' }}>{row.fontSize}</td>
<td style={{ padding: '0.5rem' }}>{row.fontWeight}</td>
<td style={{ padding: '0.5rem' }}>{row.lineHeight}</td>
<td style={{ padding: '0.5rem', fontSize: '11px' }}>
<code>{row.color}</code>
</td>
</tr>
))}
</tbody>
</table>
</div>
</Article>
</Section>
</Layout>
);
}
+216
View File
@@ -0,0 +1,216 @@
'use client';
import {
Layout,
Section,
Article,
Headline,
Subhead,
BodyText,
} from '@newspaperui/components';
import { ThemeToggle } from '@/components/ThemeToggle';
interface Swatch {
token: string;
hex: string;
label?: string;
}
const textSwatches: Swatch[] = [
{ token: '--nui-text-primary', hex: '#1A1A1A', label: '标题、主文本' },
{ token: '--nui-text-body', hex: '#22201C', label: '正文' },
{ token: '--nui-text-secondary', hex: '#4A4742', label: 'Subhead、次级' },
{ token: '--nui-text-muted', hex: '#6E6A63', label: 'Caption、注释' },
{ token: '--nui-text-quote', hex: '#2E2A24', label: 'Quote 主体' },
];
const surfaceSwatches: Swatch[] = [
{ token: '--nui-bg-page', hex: '#F7F4ED', label: 'Warm off-white 页面底' },
{ token: '--nui-bg-surface', hex: '#FBF9F4', label: '次级面板背景' },
{ token: '--nui-rule-hairline', hex: '#C9C2B2', label: '细线分隔' },
{ token: '--nui-rule-decorative', hex: '#1A1A1A', label: '强调线' },
{ token: '--nui-highlight', hex: '#F2E9C8', label: '旧报纸黄' },
];
const accentSwatches: Swatch[] = [
{ token: '--nui-accent-primary', hex: '#7A1F1F', label: 'Brick red, Kicker / Masthead 强调' },
{ token: '--nui-accent-ink-blue', hex: '#1B2A4A', label: 'The Times 蓝' },
{ token: '--nui-highlight', hex: '#F2E9C8', label: '高亮底色' },
];
interface FontFamily {
token: string;
sample: string;
description: string;
}
const families: FontFamily[] = [
{
token: '--font-family-masthead',
sample: 'The Daily Chronicle',
description: 'Cormorant Garamond — 报头',
},
{
token: '--font-family-blackletter',
sample: 'The Daily Chronicle',
description: 'UnifrakturMaguntia — Blackletter preset',
},
{
token: '--font-family-display',
sample: 'A Quiet Revolution',
description: 'Source Serif 4 — Display 大字头条',
},
{
token: '--font-family-headline',
sample: 'Whitehall confirms review',
description: 'Source Serif 4 — Headline / Subhead',
},
{
token: '--font-family-body',
sample: 'In Manchester, regional officials greeted the announcement.',
description: 'Source Serif 4 — 正文',
},
{
token: '--font-family-meta',
sample: 'BY ALICE SMITH · LONDON',
description: 'Inter — small-caps 元信息',
},
];
function SwatchGrid({ swatches }: { swatches: Swatch[] }) {
return (
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))',
gap: '0.75rem',
margin: '1rem 0 1.5rem',
}}
>
{swatches.map((s) => (
<div
key={s.token}
style={{ border: '1px solid var(--nui-rule-hairline)', overflow: 'hidden' }}
>
<div style={{ background: s.hex, height: '64px' }} />
<div
style={{
padding: '0.5rem 0.75rem',
fontFamily: 'var(--font-family-meta)',
fontSize: '11px',
background: 'var(--nui-bg-surface)',
}}
>
<code style={{ display: 'block', fontSize: '11px' }}>{s.token}</code>
<div
style={{
color: 'var(--nui-text-muted)',
marginTop: '0.15rem',
letterSpacing: '0.04em',
}}
>
{s.hex}
{s.label ? ` · ${s.label}` : ''}
</div>
</div>
</div>
))}
</div>
);
}
export default function ThemePage() {
return (
<Layout columns={24} maxWidth="900px" padding="2rem">
<Section columns={24}>
<Article span={24}>
<Headline weight="Medium" as="h1">
</Headline>
<Subhead weight="Medium">
+ warm off-white使#000使#FFF
</Subhead>
<Headline weight="Low" as="h2">
</Headline>
<BodyText weight="Low">
<p>
#14110D
</p>
</BodyText>
<div style={{ margin: '1rem 0 2rem' }}>
<ThemeToggle />
</div>
<Headline weight="Low" as="h2">
token
</Headline>
<SwatchGrid swatches={textSwatches} />
<Headline weight="Low" as="h2">
线 token
</Headline>
<SwatchGrid swatches={surfaceSwatches} />
<Headline weight="Low" as="h2">
token
</Headline>
<SwatchGrid swatches={accentSwatches} />
<Headline weight="Low" as="h2">
</Headline>
<BodyText weight="Low">
<p>
Cormorant Garamond Source Serif 4
穿Inter small-caps Blackletter preset
UnifrakturMaguntia
</p>
</BodyText>
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '1rem',
margin: '1rem 0 2rem',
}}
>
{families.map((f) => (
<div
key={f.token}
style={{
borderTop: '1px solid var(--nui-rule-hairline)',
paddingTop: '0.75rem',
}}
>
<div
className="nui-small-caps"
style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '11px',
color: 'var(--nui-text-muted)',
letterSpacing: '0.08em',
marginBottom: '0.25rem',
}}
>
{f.token} &middot; {f.description}
</div>
<div
style={{
fontFamily: `var(${f.token})`,
fontSize: '32px',
color: 'var(--nui-text-primary)',
lineHeight: 1.1,
}}
>
{f.sample}
</div>
</div>
))}
</div>
</Article>
</Section>
</Layout>
);
}
@@ -0,0 +1,87 @@
'use client';
import {
Layout, Section, Article, Masthead,
Headline, Subhead, Kicker, BodyText, Byline, Dateline,
Figure, PullQuote,
} from '@newspaperui/components';
export default function BlackletterFrontPage() {
return (
<Layout columns={24} maxWidth="1200px" padding="2rem 1.5rem">
<Masthead
variant="blackletter"
title="Die Frankfurter Zeitung"
edition="Nr. 117 · 142. Jahrgang"
date="Dienstag, 19. Mai 2026"
price="€ 3,80"
/>
<Section columns={24} divider="bottom" gap="2rem" style={{ marginTop: '2rem' }}>
<Article span={6} style={{ borderRight: '1px solid var(--nui-rule-hairline)', paddingRight: '1.25rem' }}>
<Kicker>Im Blatt</Kicker>
<Headline weight="Low" as="h3" style={{ marginTop: 0 }}>
Bundestag billigt Klimapaket nach langer Debatte
</Headline>
<BodyText weight="Low">
<p>Die einstimmige Abstimmung beendet eine umstrittene Sitzungsperiode. Politik, Seite 4.</p>
</BodyText>
<hr className="nui-rule-hairline" style={{ margin: '1rem 0' }} />
<Headline weight="Low" as="h3">Industrie sieht in Reform Chance und Risiko</Headline>
<BodyText weight="Low">
<p>Verbände begrüßen die Pläne, mahnen aber Übergangsfristen für kleinere Betriebe an.
Wirtschaft, Seite 9.</p>
</BodyText>
</Article>
<Article span={18}>
<Kicker>Politik · Eilmeldung</Kicker>
<Headline weight="High">
Historischer Pakt nach langem Verhandlungsmarathon beschlossen
</Headline>
<Subhead weight="High">
Delegierte aus dreiundzwanzig Nationen einigen sich auf einen Rahmen für Zölle, Arbeit und Emissionen
</Subhead>
<Byline>Von Eleonore Witkomm und Markus Reyes</Byline>
<Figure
src="https://images.unsplash.com/photo-1551836022-aadb801c60ae?auto=format&fit=crop&w=1200&q=80"
alt="Verhandlungsführer am Konferenztisch"
caption="Die Delegationen applaudieren nach der Verabschiedung des Schlussdokuments am Montagabend."
credit="Foto: Jane Doe / Pool"
/>
<BodyText weight="High" columns={3} dropCap style={{ marginTop: '1.5rem' }}>
<p><Dateline>Brüssel </Dateline> 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.</p>
<p>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.</p>
<p>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.</p>
</BodyText>
<PullQuote weight="High" author="Margarethe Lindqvist, Chefverhandlerin" align="left">
Ein langer Streit, der schließlich zum Gespräch wurde.
</PullQuote>
<BodyText weight="High" columns={2}>
<p>Das Rahmenabkommen sieht eine schrittweise CO-Abgabe für Schwerindustrie ab 2028 vor.
Einnahmen sollen in einen Investitionsfonds für klimafreundliche Fertigung fließen.</p>
<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>
</BodyText>
</Article>
</Section>
</Layout>
);
}
+28
View File
@@ -0,0 +1,28 @@
'use client';
import { useState } from 'react';
export function ThemeToggle() {
const [dark, setDark] = useState(false);
return (
<button
onClick={() => {
const next = !dark;
setDark(next);
document.documentElement.dataset.theme = next ? 'dark' : '';
}}
style={{
fontFamily: 'var(--font-family-meta)',
fontSize: '12px',
textTransform: 'uppercase',
letterSpacing: '0.08em',
padding: '0.5rem 1rem',
background: 'transparent',
border: '1px solid var(--nui-rule-decorative)',
color: 'var(--nui-text-primary)',
cursor: 'pointer',
}}
>
{dark ? 'Light Mode' : 'Dark Mode'}
</button>
);
}