diff --git a/.claude/scheduled_tasks.lock b/.claude/scheduled_tasks.lock new file mode 100644 index 0000000..14442e1 --- /dev/null +++ b/.claude/scheduled_tasks.lock @@ -0,0 +1 @@ +{"sessionId":"9eea8633-2610-41cb-8b8f-1223ddb5e487","pid":60045,"procStart":"Tue May 19 12:24:21 2026","acquiredAt":1779203525468} \ No newline at end of file diff --git a/.playwright-mcp/page-2026-05-19T14-59-29-094Z.yml b/.playwright-mcp/page-2026-05-19T14-59-29-094Z.yml new file mode 100644 index 0000000..822c5b4 --- /dev/null +++ b/.playwright-mcp/page-2026-05-19T14-59-29-094Z.yml @@ -0,0 +1,74 @@ +- 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 framework’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’s 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 accord’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. + - 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 accord’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’s 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] \ No newline at end of file diff --git a/.playwright-mcp/page-2026-05-19T14-59-57-959Z.yml b/.playwright-mcp/page-2026-05-19T14-59-57-959Z.yml new file mode 100644 index 0000000..822c5b4 --- /dev/null +++ b/.playwright-mcp/page-2026-05-19T14-59-57-959Z.yml @@ -0,0 +1,74 @@ +- 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 framework’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’s 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 accord’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. + - 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 accord’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’s 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] \ No newline at end of file diff --git a/.playwright-mcp/page-2026-05-19T15-27-09-291Z.yml b/.playwright-mcp/page-2026-05-19T15-27-09-291Z.yml new file mode 100644 index 0000000..57c74bb --- /dev/null +++ b/.playwright-mcp/page-2026-05-19T15-27-09-291Z.yml @@ -0,0 +1,39 @@ +- 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] \ No newline at end of file diff --git a/.playwright-mcp/page-2026-05-19T15-27-23-515Z.yml b/.playwright-mcp/page-2026-05-19T15-27-23-515Z.yml new file mode 100644 index 0000000..57c74bb --- /dev/null +++ b/.playwright-mcp/page-2026-05-19T15-27-23-515Z.yml @@ -0,0 +1,39 @@ +- 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] \ No newline at end of file diff --git a/.playwright-mcp/page-2026-05-19T15-28-19-300Z.yml b/.playwright-mcp/page-2026-05-19T15-28-19-300Z.yml new file mode 100644 index 0000000..b0f8a84 --- /dev/null +++ b/.playwright-mcp/page-2026-05-19T15-28-19-300Z.yml @@ -0,0 +1,309 @@ +- 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 chancellor’s 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" \ No newline at end of file diff --git a/.playwright-mcp/page-2026-05-19T15-28-45-172Z.yml b/.playwright-mcp/page-2026-05-19T15-28-45-172Z.yml new file mode 100644 index 0000000..44eb867 --- /dev/null +++ b/.playwright-mcp/page-2026-05-19T15-28-45-172Z.yml @@ -0,0 +1,121 @@ +- 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 \ No newline at end of file diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..d993858 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,240 @@ +# Skill: Agent-Driven 从 0 到 1 落地复杂前端项目 + +## 适用场景 + +- 从设计文档(design.md / PRD)出发,构建完整的组件库 / 应用 +- 项目涉及多个 package / 多层架构(theme → utils → components → docs) +- 需要达到「生产级」视觉和代码质量 +- 单人操作但希望并行推进多个模块 + +--- + +## 核心工作流(5 阶段) + +``` +需求分析 → 技术规划 → 并行实施 → 视觉验证 → 设计复评 + ↑ | + └──── 如果复评 < 目标分 → 回到规划 ────────────┘ +``` + +--- + +## 阶段 1:需求分析(不写代码) + +### 1.1 读蓝本,提炼决策点 + +读 design.md,列出所有需要用户决策的方向性问题(不超过 4 个)。用 `AskUserQuestion` 一次性收集,避免来回。 + +**关键决策点模板**: +- 视觉风格基调?(给 2-3 个带 ASCII preview 的选项) +- 核心技术机制?(给 2-3 个方案对比) +- 交付物范围?(MVP vs 完整版) +- 现有代码处理?(保留 / 重写 / 增量) + +### 1.2 派发探索 Agent(只读) + +并行派 2 个 Explore agent: +- Agent A:探索现有代码结构、工具链版本、可复用的好东西 +- Agent B:做领域调研(视觉系统 / 技术方案 / 竞品参考) + +**产出**:结构化报告(缺口矩阵 + 可复用清单 + 调研结论) + +--- + +## 阶段 2:技术规划(Plan Mode) + +### 2.1 进入 Plan Mode + +用 `EnterPlanMode`,基于阶段 1 的探索结果写 plan 文件。 + +### 2.2 Plan 文件结构 + +```markdown +# 项目名 重做/新建 计划 + +## Context(为什么做、做什么、预期结果) + +## 范围与边界(保留什么 / 重写什么 / 不做什么) + +## 1-N. 各 Package 详细设计 + - 文件清单 + - 关键代码模板(不是伪代码,是可直接落地的 TSX) + - 依赖关系 + +## 实施顺序(Stage 1 → N,标注串行/并行) + +## 验证方案(自动化 + 视觉清单) + +## 风险与权衡 +``` + +### 2.3 关键原则 + +- **Plan 里写真实代码模板**,不写「大概这样做」。Agent 执行时直接复制粘贴,减少发挥空间 +- **标注依赖关系**:哪些 Stage 可并行、哪些必须串行 +- **验证清单要具体**:不写「检查样式是否正确」,写「Headline fontSize ≥ 48px, fontWeight === 600」 + +--- + +## 阶段 3:并行实施 + +### 3.1 任务拆分 + +用 `TaskCreate` 按 Stage 建任务,用 `addBlockedBy` 标注依赖: + +``` +Stage 1 (基础设施) ← 无依赖,先做 +Stage 2 (组件层) ← blocked by Stage 1 +Stage 3 (Demo) ← blocked by Stage 2 +Stage 4 (文档) ← blocked by Stage 2(可与 Stage 3 并行) +Stage 5 (验证) ← blocked by Stage 3 + 4 +``` + +### 3.2 Agent 派发策略 + +| 场景 | 做法 | +|---|---| +| 有依赖的 Stage | 串行:等前一个 Agent 完成再派下一个 | +| 无依赖的 Stage | 并行:同一条消息里派多个 Agent | +| Agent 需要协调 | 用 `SendMessage` 通知另一个 Agent 上游已就绪 | + +### 3.3 Agent Prompt 黄金模板 + +``` +你需要在 [路径] 实现 [什么]。 + +## 上游依赖(已就绪) +[列出可 import 的模块和 API] + +## 任务 +### 1. [具体文件] — [完整代码] +### 2. [具体文件] — [完整代码] +... + +## 验证步骤 +[具体命令 + 期望输出] + +## 约束 +- 严格按上面代码写,不要发挥 +- 不引入新依赖 +- 完成后直接报告,不要询问 +``` + +**关键**:给 Agent 的 prompt 越具体、代码越完整,产出质量越高。不要给 Agent 留设计决策空间。 + +### 3.4 每个 Stage 完成后 + +- 跑 `pnpm build` + `pnpm test` 确认不破坏 +- 标记 TaskUpdate status=completed +- 解锁下游 Stage + +--- + +## 阶段 4:视觉验证 + +### 4.1 自动化验证 + +```bash +pnpm build # 全包构建 +pnpm test # 全测试通过 +pnpm dev # 启动 dev server +``` + +### 4.2 Playwright DOM 实测 + +不依赖截图肉眼判断,用 `browser_evaluate` 直接读 computed style: + +```javascript +// 验证字体、字号、颜色、布局属性 +const cs = getComputedStyle(element); +return { + fontFamily: cs.fontFamily, + fontSize: cs.fontSize, + fontWeight: cs.fontWeight, + columnCount: cs.columnCount, + backgroundColor: cs.backgroundColor, +}; +``` + +### 4.3 视觉验收清单 + +提前在 Plan 里写好 10-15 项具体的验收条件,每项都是可自动化检测的: + +``` +- [ ] Masthead fontFamily 包含 "Cormorant Garamond" +- [ ] Headline fontSize >= 48px +- [ ] BodyText columnCount === "3" +- [ ] body backgroundColor === "rgb(247, 244, 237)" +``` + +--- + +## 阶段 5:设计复评 + +### 5.1 派发 UI Designer Agent + +给 Designer Agent: +- 截图路径 +- 关键文件路径 +- 第一次评估结果(如果是迭代) +- 明确的评分维度和输出格式 + +### 5.2 目标分数 + +- 首次实现目标:≥ 8/10 +- 迭代后目标:≥ 9/10 +- 如果 < 目标分,回到阶段 2 重新规划问题区域 + +--- + +## 反模式(避免) + +| 反模式 | 正确做法 | +|---|---| +| 给 Agent 模糊指令「实现组件库」 | 给完整代码模板 + 文件路径 | +| 一个 Agent 做所有事 | 按 Stage 拆分,每个 Agent 职责单一 | +| 先写代码再想设计 | Plan Mode 先对齐,用户批准再动手 | +| 只跑 build 就算完成 | Playwright 实测 computed style | +| 截图肉眼看「差不多」 | 量化验收清单(字号/颜色/布局属性) | +| 一次性全部并行 | 按依赖关系分层,基础设施必须先完成 | +| Agent 报错就放弃 | 分析根因,调整 prompt 重试(最多 3 次) | + +--- + +## 时间分配参考 + +| 阶段 | 占比 | 说明 | +|---|---|---| +| 需求分析 + 探索 | 15% | 磨刀不误砍柴工 | +| 技术规划 | 20% | Plan 越详细,实施越快 | +| 并行实施 | 45% | Agent 并行,人只做协调 | +| 验证 + 复评 | 15% | 量化验收,不靠感觉 | +| 迭代修复 | 5% | 如果规划到位,这步很轻 | + +--- + +## 可复用的 Agent 类型 + +| Agent 类型 | 用途 | +|---|---| +| Explore | 只读探索代码结构、生成报告 | +| UI Designer | 视觉系统调研、设计复评打分 | +| Frontend Developer | 写代码、跑构建、跑测试 | +| Minimal Change Engineer | 精准修复特定问题,不扩大范围 | + +--- + +## Checklist:启动新项目时 + +1. [ ] 有 design.md / PRD 蓝本? +2. [ ] 用 AskUserQuestion 收集 3-4 个方向性决策? +3. [ ] 派 Explore agent 做现状分析 + 领域调研? +4. [ ] 进入 Plan Mode 写详细计划(含代码模板)? +5. [ ] 用户批准 plan? +6. [ ] 按依赖关系拆 TaskCreate + addBlockedBy? +7. [ ] Stage 1 基础设施先串行完成? +8. [ ] Stage 2+ 尽量并行派发? +9. [ ] 每个 Stage 完成后跑 build + test? +10. [ ] Playwright 量化验收 10+ 项? +11. [ ] Designer Agent 复评 ≥ 目标分? +12. [ ] 同步 design.md / README? diff --git a/packages/components/src/Layout/Article.tsx b/packages/components/src/Layout/Article.tsx new file mode 100644 index 0000000..571486a --- /dev/null +++ b/packages/components/src/Layout/Article.tsx @@ -0,0 +1,32 @@ +'use client'; +import React, { ReactNode, CSSProperties } from 'react'; +import { clampSpan, cx } from '@newspaperui/utils'; +import { useSection } from './Section'; + +export interface ArticleProps { + span?: number; + breakable?: boolean; + className?: string; + style?: CSSProperties; + children: ReactNode; +} + +export const Article: React.FC = ({ + span, breakable = true, className, style, children, +}) => { + const section = useSection(); + const cols = span ? clampSpan(span, section.columns) : section.columns; + return ( +
+ {children} +
+ ); +}; diff --git a/packages/components/src/Layout/Layer.tsx b/packages/components/src/Layout/Layer.tsx new file mode 100644 index 0000000..8ad2eb3 --- /dev/null +++ b/packages/components/src/Layout/Layer.tsx @@ -0,0 +1,26 @@ +'use client'; +import React, { ReactNode, CSSProperties } from 'react'; + +export interface LayerProps { + position?: 'absolute' | 'fixed' | 'sticky'; + top?: string | number; + left?: string | number; + right?: string | number; + bottom?: string | number; + zIndex?: number; + className?: string; + style?: CSSProperties; + children: ReactNode; +} + +export const Layer: React.FC = ({ + position = 'absolute', top, left, right, bottom, zIndex, + className, style, children, +}) => ( +
+ {children} +
+); diff --git a/packages/components/src/Layout/Masthead.tsx b/packages/components/src/Layout/Masthead.tsx new file mode 100644 index 0000000..ae62b6d --- /dev/null +++ b/packages/components/src/Layout/Masthead.tsx @@ -0,0 +1,81 @@ +'use client'; +import React from 'react'; +import { cx } from '@newspaperui/utils'; + +export interface MastheadProps { + title: string; + kicker?: string; + edition?: string; + date?: string; + price?: string; + variant?: 'classic' | 'blackletter' | 'modern'; + className?: string; +} + +export const Masthead: React.FC = ({ + title, kicker, edition, date, price, variant = 'classic', className, +}) => { + const fontFamily = + variant === 'blackletter' + ? 'var(--font-family-blackletter)' + : 'var(--font-family-masthead)'; + const align = variant === 'modern' ? 'left' : 'center'; + + return ( +
+
+ {kicker && ( +
+ {kicker} +
+ )} +

+ {title} +

+ {(edition || date || price) && ( +
+ {edition && {edition}} + {date && {date}} + {price && {price}} +
+ )} +
+
+ ); +}; diff --git a/packages/components/src/Layout/Rule.tsx b/packages/components/src/Layout/Rule.tsx new file mode 100644 index 0000000..59099f6 --- /dev/null +++ b/packages/components/src/Layout/Rule.tsx @@ -0,0 +1,56 @@ +'use client'; +import React, { CSSProperties } from 'react'; +import { cx } from '@newspaperui/utils'; + +export interface RuleProps { + variant?: 'hairline' | 'double' | 'thick'; + orientation?: 'horizontal' | 'vertical'; + span?: number; // 横向时占多少列 (1 / -1 全跨) + className?: string; + style?: CSSProperties; +} + +export const Rule: React.FC = ({ + variant = 'hairline', orientation = 'horizontal', span, className, style, +}) => { + const isHorizontal = orientation === 'horizontal'; + const baseStyle: CSSProperties = isHorizontal + ? { width: '100%', border: 0, margin: 0 } + : { height: '100%', width: '1px', border: 0, margin: 0 }; + + const variantStyle: CSSProperties = (() => { + if (variant === 'hairline') + return isHorizontal + ? { borderTop: '1px solid var(--nui-rule-hairline)' } + : { background: 'var(--nui-rule-hairline)' }; + if (variant === 'thick') + return isHorizontal + ? { borderTop: '3px solid var(--nui-rule-decorative)' } + : { width: '3px', background: 'var(--nui-rule-decorative)' }; + // double + return isHorizontal + ? { + height: '6px', + background: + 'linear-gradient(to bottom, var(--nui-rule-decorative) 0 1px, transparent 1px 4px, var(--nui-rule-decorative) 4px 6px)', + } + : { + width: '6px', + background: + 'linear-gradient(to right, var(--nui-rule-decorative) 0 1px, transparent 1px 4px, var(--nui-rule-decorative) 4px 6px)', + }; + })(); + + return ( +
+ ); +}; diff --git a/packages/components/src/Layout/Section.tsx b/packages/components/src/Layout/Section.tsx new file mode 100644 index 0000000..f1b70b6 --- /dev/null +++ b/packages/components/src/Layout/Section.tsx @@ -0,0 +1,53 @@ +'use client'; +import React, { createContext, useContext, ReactNode, CSSProperties } from 'react'; +import { clampSpan, cx } from '@newspaperui/utils'; +import { useLayout } from './Layout'; + +export interface SectionProps { + columns: number; // section 内部的栅格列数 (≤ layout.columns) + gap?: string; // 默认 'var(--nui-gutter)' + breakable?: boolean; // 是否允许 print 分页断开,默认 true + divider?: 'none' | 'top' | 'bottom' | 'both'; // hairline 分隔 + className?: string; + style?: CSSProperties; + children: ReactNode; +} + +interface SectionContextValue { columns: number; } +const SectionContext = createContext({ columns: 24 }); +export const useSection = () => useContext(SectionContext); + +export const Section: React.FC = ({ + columns, gap = 'var(--nui-gutter)', breakable = true, divider = 'none', + className, style, children, +}) => { + const layout = useLayout(); + const cols = clampSpan(columns, layout.columns); + + const dividerStyle: CSSProperties = {}; + if (divider === 'top' || divider === 'both') + dividerStyle.borderTop = '1px solid var(--nui-rule-hairline)'; + if (divider === 'bottom' || divider === 'both') + dividerStyle.borderBottom = '1px solid var(--nui-rule-hairline)'; + + return ( + +
+ {children} +
+
+ ); +}; diff --git a/packages/components/src/Text/Dateline.tsx b/packages/components/src/Text/Dateline.tsx new file mode 100644 index 0000000..ccee087 --- /dev/null +++ b/packages/components/src/Text/Dateline.tsx @@ -0,0 +1,31 @@ +'use client'; +import React, { ReactNode, CSSProperties } from 'react'; +import { visualWeights, resolveFontSize } from '@newspaperui/theme'; +import { cx } from '@newspaperui/utils'; + +export interface DatelineProps { + className?: string; + style?: CSSProperties; + children: ReactNode; // e.g. "LONDON —" +} + +export const Dateline: React.FC = ({ className, style, children }) => { + const config = visualWeights.Dateline.Standard!; + return ( + + {children} + + ); +}; diff --git a/packages/components/src/Text/Kicker.tsx b/packages/components/src/Text/Kicker.tsx new file mode 100644 index 0000000..51b386a --- /dev/null +++ b/packages/components/src/Text/Kicker.tsx @@ -0,0 +1,31 @@ +'use client'; +import React, { ReactNode, CSSProperties } from 'react'; +import { visualWeights, resolveFontSize } from '@newspaperui/theme'; +import { cx } from '@newspaperui/utils'; + +export interface KickerProps { + className?: string; + style?: CSSProperties; + children: ReactNode; +} + +export const Kicker: React.FC = ({ className, style, children }) => { + const config = visualWeights.Kicker.Standard!; + return ( +
+ {children} +
+ ); +}; diff --git a/packages/components/src/__tests__/BodyText.test.tsx b/packages/components/src/__tests__/BodyText.test.tsx new file mode 100644 index 0000000..800cdb0 --- /dev/null +++ b/packages/components/src/__tests__/BodyText.test.tsx @@ -0,0 +1,53 @@ +import { describe, it, expect } from 'vitest'; +import { render } from '@testing-library/react'; +import { Layout } from '../layout/Layout'; +import { Section } from '../layout/Section'; +import { BodyText } from '../text/BodyText'; + +describe('BodyText', () => { + it('enables multi-column flow when columns >= 2', () => { + const { container } = render( + +
+ +

p1

+
+
+
, + ); + const root = container.querySelector('.nui-bodytext') as HTMLElement; + expect(root.style.columnCount).toBe('3'); + expect(root.style.columnGap).toBe('var(--nui-gutter)'); + expect(root.classList.contains('nui-column-rule')).toBe(true); + expect(root.getAttribute('data-columns')).toBe('3'); + }); + + it('applies the nui-drop-cap class when dropCap is true', () => { + const { container } = render( + +
+ +

p

+
+
+
, + ); + const root = container.querySelector('.nui-bodytext') as HTMLElement; + expect(root.classList.contains('nui-drop-cap')).toBe(true); + }); + + it('does not enable multi-column flow when columns is 1 (default)', () => { + const { container } = render( + +
+ +

p

+
+
+
, + ); + const root = container.querySelector('.nui-bodytext') as HTMLElement; + expect(root.style.columnCount).toBe(''); + expect(root.classList.contains('nui-column-rule')).toBe(false); + }); +}); diff --git a/packages/components/src/__tests__/Headline.test.tsx b/packages/components/src/__tests__/Headline.test.tsx new file mode 100644 index 0000000..daae3b6 --- /dev/null +++ b/packages/components/src/__tests__/Headline.test.tsx @@ -0,0 +1,53 @@ +import { describe, it, expect } from 'vitest'; +import { render } from '@testing-library/react'; +import { Layout } from '../layout/Layout'; +import { Section } from '../layout/Section'; +import { Headline } from '../text/Headline'; + +describe('Headline', () => { + it('renders h1 for weight="High" and h2 for weight="Medium"', () => { + const { container, rerender } = render( + +
+ A +
+
, + ); + expect(container.querySelector('h1')).not.toBeNull(); + + rerender( + +
+ B +
+
, + ); + expect(container.querySelector('h2')).not.toBeNull(); + }); + + it('respects "as" prop overriding default tag', () => { + const { container } = render( + +
+ + X + +
+
, + ); + expect(container.querySelector('h1')).toBeNull(); + expect(container.querySelector('h2')).not.toBeNull(); + }); + + it('uses CSS variable references for fontFamily', () => { + const { container } = render( + +
+ X +
+
, + ); + const h1 = container.querySelector('h1') as HTMLElement; + expect(h1.style.fontFamily).toContain('var(--font-family-'); + }); +}); diff --git a/packages/components/src/__tests__/Masthead.test.tsx b/packages/components/src/__tests__/Masthead.test.tsx new file mode 100644 index 0000000..0b0b5bb --- /dev/null +++ b/packages/components/src/__tests__/Masthead.test.tsx @@ -0,0 +1,31 @@ +import { describe, it, expect } from 'vitest'; +import { render, screen } from '@testing-library/react'; +import { Masthead } from '../layout/Masthead'; + +describe('Masthead', () => { + it('renders title as an h1', () => { + render(); + const h1 = screen.getByRole('heading', { level: 1 }); + expect(h1.textContent).toBe('The Daily Times'); + }); + + it('uses the blackletter font family when variant="blackletter"', () => { + render(); + const h1 = screen.getByRole('heading', { level: 1 }) as HTMLElement; + expect(h1.style.fontFamily).toContain('--font-family-blackletter'); + }); + + it('renders edition, date, and price when provided', () => { + render( + , + ); + expect(screen.getByText('Late Edition')).toBeInTheDocument(); + expect(screen.getByText('May 19, 2026')).toBeInTheDocument(); + expect(screen.getByText('$3.00')).toBeInTheDocument(); + }); +}); diff --git a/packages/docs/app/(docs)/components/article/page.tsx b/packages/docs/app/(docs)/components/article/page.tsx new file mode 100644 index 0000000..f508062 --- /dev/null +++ b/packages/docs/app/(docs)/components/article/page.tsx @@ -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 ( + +
+
+ + Article + Layer + + + Article 是栅格内的文章块,通过 grid-column span 跨栏。Layer 是脱离文档流的浮动层。 + + + + Article API + + + + + 跨栏 Demo + + +
+
+ 短讯 + ... +
+
+ 主稿 + ... +
+
+`} + > + +
+
+ + 短讯 + + +

+ Markets responded cautiously through the morning session. The pound + traded sideways against the dollar, gilts firmed by three basis points. +

+
+
+
+ + 主稿 + + +

+ 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. +

+
+
+
+
+
+ + + Layer API + + +

+ Layer 脱离栅格流,使用 CSS position 定位。适合浮动拉引、浮动广告、sticky 导航等场景。 +

+
+ + + +
+ 主要文章 + ... +
+ + + +`} + > + +
+
+
+ + 主要文章 + + +

+ In Manchester, regional officials greeted the announcement with + measured optimism. The mayor’s office is expected to issue a + formal response by week’s end. +

+
+
+ + + +
+
+
+
+
+
+
+ ); +} diff --git a/packages/docs/app/(docs)/components/masthead/page.tsx b/packages/docs/app/(docs)/components/masthead/page.tsx new file mode 100644 index 0000000..4800ed2 --- /dev/null +++ b/packages/docs/app/(docs)/components/masthead/page.tsx @@ -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 ( + +
+
+ + Masthead 报头 + + + 报头是报纸的门面。三个 variant 覆盖经典双线居中、哥特体、现代左对齐三种风格。 + + + + API + + + + + Classic + + `} + > + + + + + Blackletter + + `} + > + + + + + Modern + + `} + > + + + + + 使用建议 + + +

+ Masthead 默认 gridColumn: 1 / -1,在 Section 内自动全宽。 + 通常放在 Layout 的第一个 Section 中,后接 Rule 分隔线。 +

+
+
+
+
+ ); +} diff --git a/packages/docs/app/(docs)/components/media/page.tsx b/packages/docs/app/(docs)/components/media/page.tsx new file mode 100644 index 0000000..96d0bf6 --- /dev/null +++ b/packages/docs/app/(docs)/components/media/page.tsx @@ -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 ( + +
+
+ + 媒体组件 + + + Image、Figure、Video、PullQuote — 报纸版面中的视觉元素。 + + + + Image + + +

+ 基础图片组件。display: block; width: 100%,在 Section 栅格内通过 + span 跨栏。 +

+
+ + + + Figure + + +

+ 组合 Image + Caption + Credit 的语义容器。自动渲染 figcaption。 +

+
+ + `} + > +
+ + + + Video + + + +

+ Video 组件与 Figure 结构类似,包裹 <video> 标签并附带 + caption/credit。 +

+
+ + + PullQuote + + +

+ 上下双 hairline + Display 字体的拉引组件。在多栏 BodyText 内设置 + spanAllColumns 可跨所有栏(通过 column-span: all)。 +

+
+ + + + We have lobbied for this kind of clarity for the better part of a decade. +`} + > + + We have lobbied for this kind of clarity for the better part of a decade. + + + + +

...

+ ... +

...

+`} + > + +

+ 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. +

+ + The most coherent strategic blueprint in a generation. + +

+ 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. +

+

+ In Manchester, regional officials greeted the announcement with measured + optimism. The mayor’s office is expected to issue a formal response by + week’s end, focusing on commitments to the trans-Pennine corridor. +

+
+
+
+
+
+ ); +} diff --git a/packages/docs/app/(docs)/components/rule/page.tsx b/packages/docs/app/(docs)/components/rule/page.tsx new file mode 100644 index 0000000..96bc84c --- /dev/null +++ b/packages/docs/app/(docs)/components/rule/page.tsx @@ -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 ( + +
+
+ + Rule 分隔线 + + + 显式分隔线组件。三个 variant 覆盖 hairline、double、thick,支持水平和垂直方向。 + + + + API + + + + + 水平方向三种 variant + + +
+
+ +

hairline

+
+ +
+
+ +

double

+
+ +
+
+ +

thick

+
+ +
+
+
+ + + 垂直方向 + + +
左栏内容
+ +
右栏内容
+`} + > +
+
+ +

+ Markets responded cautiously through the morning session. The pound + traded sideways against the dollar. +

+
+
+ +
+ +

+ Analysts at three of the City’s largest houses framed the move as + a holding pattern. +

+
+
+
+
+ + + 使用建议 + + +

+ Rule 在 Section 栅格内默认 gridColumn: 1 / -1 全跨。 + 如果只需要跨部分列,传入 span prop。垂直 Rule 适合放在 + flex 容器中作为栏间分隔。 +

+
+
+
+
+ ); +} diff --git a/packages/docs/app/(docs)/examples/responsive/page.tsx b/packages/docs/app/(docs)/examples/responsive/page.tsx new file mode 100644 index 0000000..16c3f60 --- /dev/null +++ b/packages/docs/app/(docs)/examples/responsive/page.tsx @@ -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 ( + +
+
+ + 响应式设计 + + + NewspaperUI 的响应式策略完全基于 CSS media query + container query, + 不依赖 JavaScript 运行时计算。 + + + + 断点说明 + + +

+ 三个核心断点覆盖移动、平板、桌面: +

+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
断点宽度栏数建议说明
Mobile< 768px1 栏(全宽)单栏堆叠,BodyText columns=1
Tablet768px - 1024px12 列两栏布局,BodyText columns=2
Desktop> 1024px24 列完整多栏布局
+
+ + + 实施手法 + + +

+ NewspaperUI 不再使用 JavaScript responsive 函数。所有响应式行为通过 CSS + media query 和 container query 实现,零运行时开销。 +

+

+ Section 的 gridTemplateColumns 是 inline style,因此需要在 + 消费侧用 CSS 覆盖。推荐做法: +

+
+ + + + +

+ 或者使用 container query 让 Section 根据自身宽度自适应: +

+
+ + + + + + + 视口效果预览 + + +

+ 下面三个区块模拟桌面、平板、移动端的视觉效果。实际项目中建议使用浏览器 + DevTools 的 responsive mode 进行测试。 +

+
+ +
+
+
+ Desktop (1024px+) — 24 列完整布局 +
+
+ +
+
+ Briefing +

Short news items.

+
+
+ Lead Story +

Main article content with full detail.

+
+
+ Markets +

FTSE, gilts, sterling.

+
+
+
+
+
+ +
+
+ Tablet (768-1024px) — 12 列简化 +
+
+ +
+
+ Lead Story +

Main article.

+
+
+ Secondary +

Supporting content.

+
+
+
+
+
+ +
+
+ Mobile (<768px) — 单栏堆叠 +
+
+ +
+
+ Lead Story +

Full-width single column.

+
+
+ Secondary +

Stacked below.

+
+
+
+
+
+
+
+
+
+ ); +} diff --git a/packages/docs/app/(docs)/examples/spanning/page.tsx b/packages/docs/app/(docs)/examples/spanning/page.tsx new file mode 100644 index 0000000..a949097 --- /dev/null +++ b/packages/docs/app/(docs)/examples/spanning/page.tsx @@ -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 ( + +
+
+ + 跨栏布局示例 + + + 五种常见栏宽组合,演示 24 列栅格的灵活性。 + +
+
+ + + +
+
+ + 8 + 16 + +
+
+ + +
+
+ + Briefing + + +

+ Markets responded cautiously through the morning session. The pound + traded sideways against the dollar. +

+
+
+
+ + Infrastructure Review Tabled + + +

+ 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. +

+
+
+
+
+
+ +
+
+ + 6 + 12 + 6 + +
+
+ + +
+
+ + Weather + + +

Partly cloudy, 18C. Wind NW 12 mph. Sunset 20:47.

+
+
+
+ + Chancellor Outlines Spending Envelope + + +

+ 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. +

+
+
+
+ + Markets + + +

FTSE 100: 7,842 (-0.2%). Gilts +3bp. Sterling flat.

+
+
+
+
+
+ +
+
+ + 12 + 12 + +
+
+ + +
+
+ + View from Westminster + + +

+ Critics inside the cabinet caution that the timing risks overshadowing + the chancellor’s autumn statement. The opposition has called for a + full debate before any commitments are made. +

+
+
+
+ + View from the Regions + + +

+ In Manchester, regional officials greeted the announcement with measured + optimism. The mayor’s office is expected to issue a formal response + by week’s end. +

+
+
+
+
+
+ +
+
+ + 4 + 16 + 4 + +
+
+ + +
+
+ +

+ Editor’s note: This report was filed before the evening session. +

+
+
+
+ + A Standing Technical Commission + + +

+ 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. +

+
+
+
+ +

+ Related: “How Australia reformed infrastructure planning” + — p. 12 +

+
+
+
+
+
+ +
+
+ + 24 全宽 + +
+
+ + +
+
+ + The Quiet Revolution in Treasury Forecasting + + +

+ 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. +

+

+ 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. +

+

+ In Manchester, regional officials greeted the announcement with measured + optimism. 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. +

+

+ Beyond the immediate fiscal arithmetic, the review’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. +

+
+
+
+
+
+
+ ); +} diff --git a/packages/docs/app/(docs)/grid-system/page.tsx b/packages/docs/app/(docs)/grid-system/page.tsx new file mode 100644 index 0000000..f1da1eb --- /dev/null +++ b/packages/docs/app/(docs)/grid-system/page.tsx @@ -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 ( + +
+
+ + 栅格系统 + + + 24 列由 Layout 提供上下文,Section 在栅格内分配 grid-template-columns, + Article 用 grid-column span 跨栏。所有跨栏统一通过 CSS Grid 完成。 + + + + 24 列可视化 + + +

+ 下面的网格演示了 24 列的等宽分布。每个数字标签对应一列。报纸排版偏好 24 + 列是因为它能整除 2 / 3 / 4 / 6 / 8 / 12,足够灵活地实现 1/3、2/3、1/4、3/4 + 这类常见栏宽组合。 +

+
+ +
+ {Array.from({ length: 24 }, (_, i) => ( +
+ {i + 1} +
+ ))} +
+ + + Layout API + + +

+ Layout 是顶层容器,提供 LayoutContext。Section 通过 + useLayout 读取列数上限并自动 clamp。 +

+
+ + + + Section API + + +

+ Section 是栅格容器, + display: grid; grid-template-columns: repeat(N, 1fr) + 。子 Article 通过 grid-column span 占位。 +

+
+ + + + Article API + + +

+ Article 在 Section 栅格内用 grid-column span N 占位。 + span 缺省时占满 Section 全宽。 +

+
+ + + + 实例 + + +
+
+ 短讯 + ... +
+
+ 主稿 + ... +
+
+`} + > + +
+
+ + 短讯 + + +

占 8 列。短讯栏适合放编辑选编、精选事件、快速通读型小段。

+
+
+
+ + 主稿 + + +

+ 占 16 列。主稿区域承载头版头条、深度报道,可启用 + 多栏文字流以增强阅读节奏。 +

+
+
+
+
+
+
+
+
+ ); +} diff --git a/packages/docs/app/(docs)/layout.tsx b/packages/docs/app/(docs)/layout.tsx new file mode 100644 index 0000000..8b7b7b6 --- /dev/null +++ b/packages/docs/app/(docs)/layout.tsx @@ -0,0 +1,19 @@ +import { Sidebar } from '../../components/Sidebar'; + +export default function DocsLayout({ children }: { children: React.ReactNode }) { + return ( +
+ +
+ {children} +
+
+ ); +} diff --git a/packages/docs/app/(docs)/text/page.tsx b/packages/docs/app/(docs)/text/page.tsx new file mode 100644 index 0000000..c962666 --- /dev/null +++ b/packages/docs/app/(docs)/text/page.tsx @@ -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 ( + +
+
+ + 文本组件 + + + 从 Headline 到 Caption 的完整文本谱系。每个组件按视觉权重映射到字体、字号、字重、 + 行高与颜色 token,避免硬编码样式。 + + + + Headline 三档 + + +
+
+ weight="High" + + A Quiet Revolution in the Treasury Forecast + +
+
+ weight="Medium" + + Whitehall Confirms Infrastructure Review + +
+
+ weight="Low" + + Briefing: regional rail commitments + +
+
+
+ + + Subhead 两档 + + +
+ + A measured recalibration of regional priorities is expected to define the + chancellor’s autumn agenda. + + + Officials emphasized that the headline figures should be read as a planning + envelope rather than a binding allocation. + +
+
+ + + Kicker + + +
+ POLITICS · WHITEHALL + + A Standing Technical Commission, Quietly Proposed + +
+
+ + + BodyText 多栏文字流 + + + + +

{longText}

+

{longText2}

+
+
+ + +

...

+

...

+`} + > + +

{longText}

+

{longText2}

+

{longText3}

+

{longText4}

+
+
+ + + +

{longText}

+

{longText2}

+

{longText3}

+
+
+ + + Quote 引用 + + +
+ + We have lobbied for this kind of clarity for the better part of a decade. + + +

+ 按一位资深内阁人士的说法,这份评估 + + 是一个时代以来最连贯的战略蓝图 + + ,但能否落地仍取决于春季立法。 +

+
+
+
+ + + Byline / Dateline / Caption + + +
+
+ BY ALICE SMITH + LONDON — +
+
+
+ + A view of the Treasury terrace at dusk; the new commission will report + here from May. + +
+
+
+ + + 视觉权重映射表 + + +

+ 下表从 visualWeights 数据动态生成,反映组件实际渲染时所用的 + token。修改 theme 后表格自动同步。 +

+
+
+ + + + + + + + + + + + + + {weightRows.map((row, idx) => ( + + + + + + + + + + ))} + +
组件权重字体字号字重行高颜色
{row.component}{row.weight} + {row.fontFamily} + {row.fontSize}{row.fontWeight}{row.lineHeight} + {row.color} +
+
+
+
+
+ ); +} diff --git a/packages/docs/app/(docs)/theme/page.tsx b/packages/docs/app/(docs)/theme/page.tsx new file mode 100644 index 0000000..f582c6c --- /dev/null +++ b/packages/docs/app/(docs)/theme/page.tsx @@ -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 ( +
+ {swatches.map((s) => ( +
+
+
+ {s.token} +
+ {s.hex} + {s.label ? ` · ${s.label}` : ''} +
+
+
+ ))} +
+ ); +} + +export default function ThemePage() { + return ( + +
+
+ + 主题与颜色 + + + 设计哲学:暖灰系 + warm off-white。不使用纯黑(#000)也不使用纯白(#FFF), + 把屏幕配色带回纸面的温度。 + + + + 主题切换 + + +

+ 点击切换深色模式。深色基调采用暖深棕黑(#14110D)而非冷蓝黑,保持报纸的纸性触感。 +

+
+
+ +
+ + + 文字色 token + + + + + 背景与分隔线 token + + + + + 强调色 token + + + + + 字体家族 + + +

+ 全部经典严肃风字体:Cormorant Garamond 承担报头与展示,Source Serif 4 + 贯穿正文与标题,Inter 处理 small-caps 元信息。Blackletter preset 通过 + UnifrakturMaguntia 切入哥特报头。 +

+
+
+ {families.map((f) => ( +
+
+ {f.token} · {f.description} +
+
+ {f.sample} +
+
+ ))} +
+
+
+
+ ); +} diff --git a/packages/docs/app/examples/blackletter-frontpage/page.tsx b/packages/docs/app/examples/blackletter-frontpage/page.tsx new file mode 100644 index 0000000..5f35a07 --- /dev/null +++ b/packages/docs/app/examples/blackletter-frontpage/page.tsx @@ -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 ( + + + +
+
+ Im Blatt + + Bundestag billigt Klimapaket nach langer Debatte + + +

Die einstimmige Abstimmung beendet eine umstrittene Sitzungsperiode. Politik, Seite 4.

+
+
+ Industrie sieht in Reform Chance und Risiko + +

Verbände begrüßen die Pläne, mahnen aber Übergangsfristen für kleinere Betriebe an. + Wirtschaft, Seite 9.

+
+
+ +
+ Politik · Eilmeldung + + Historischer Pakt nach langem Verhandlungsmarathon beschlossen + + + Delegierte aus dreiundzwanzig Nationen einigen sich auf einen Rahmen für Zölle, Arbeit und Emissionen + + Von Eleonore Witkomm und Markus Reyes + +
+ + +

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.

+ +

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.

+ +

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.

+
+ + + Ein langer Streit, der schließlich zum Gespräch wurde. + + + +

Das Rahmenabkommen sieht eine schrittweise CO₂-Abgabe für Schwerindustrie ab 2028 vor. + Einnahmen sollen in einen Investitionsfonds für klimafreundliche Fertigung fließen.

+ +

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.

+
+
+
+
+ ); +} diff --git a/packages/docs/components/ThemeToggle.tsx b/packages/docs/components/ThemeToggle.tsx new file mode 100644 index 0000000..0874246 --- /dev/null +++ b/packages/docs/components/ThemeToggle.tsx @@ -0,0 +1,28 @@ +'use client'; +import { useState } from 'react'; + +export function ThemeToggle() { + const [dark, setDark] = useState(false); + return ( + + ); +} diff --git a/packages/theme/src/fonts.css b/packages/theme/src/fonts.css new file mode 100644 index 0000000..f11b589 --- /dev/null +++ b/packages/theme/src/fonts.css @@ -0,0 +1,2 @@ +/* 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'); diff --git a/packages/theme/src/typography.css b/packages/theme/src/typography.css new file mode 100644 index 0000000..1f9deb7 --- /dev/null +++ b/packages/theme/src/typography.css @@ -0,0 +1,81 @@ +/* === Drop Cap === */ +.nui-drop-cap > p:first-of-type::first-letter, +.nui-drop-cap > :first-child::first-letter { + float: left; + font-family: var(--font-family-display); + font-weight: 700; + font-size: 4.2em; + line-height: 0.82; + margin: 0.05em 0.1em 0 0; + color: var(--nui-text-primary); +} + +/* === Small Caps (real OpenType, not text-transform fake) === */ +.nui-small-caps { + font-variant-caps: small-caps; + font-feature-settings: "smcp" 1, "c2sc" 1; + letter-spacing: 0.06em; + font-family: var(--font-family-meta); +} + +/* === Paragraph Flow: 首段不缩进,后续段落首行缩进 1em,无段间空行 === */ +.nui-paragraph-flow > p { + margin: 0; + orphans: 3; + widows: 3; + hyphens: auto; + break-inside: avoid-column; +} +.nui-paragraph-flow > p + p { text-indent: 1em; } +.nui-paragraph-flow > p.nui-no-indent + p { text-indent: 0; } + +/* === Old-style Figures === */ +.nui-osf { + font-feature-settings: "onum" 1, "kern" 1, "liga" 1; + font-variant-numeric: oldstyle-nums proportional-nums; +} + +/* === Tabular / Lining Figures (for headlines, tables) === */ +.nui-tnum { + font-feature-settings: "lnum" 1, "tnum" 1; + font-variant-numeric: lining-nums tabular-nums; +} + +/* === Hanging Punctuation === */ +.nui-hanging-punctuation { hanging-punctuation: first allow-end last; } + +/* === Column Rule (for multi-column body text) === */ +.nui-column-rule { + column-rule: 1px solid var(--nui-rule-hairline); +} + +/* === Avoid breaking inside (used by PullQuote, Figure, h2/h3 in column flow) === */ +.nui-avoid-break { + break-inside: avoid; + page-break-inside: avoid; +} + +/* === Headline span all columns (used inside multi-column flow) === */ +.nui-span-all-columns { column-span: all; } + +/* === Masthead double-rule === */ +.nui-masthead-rule-top, +.nui-masthead-rule-bottom { + height: 8px; + background: + linear-gradient(to bottom, + var(--nui-rule-decorative) 0, + var(--nui-rule-decorative) 1px, + transparent 1px, + transparent 5px, + var(--nui-rule-decorative) 5px, + var(--nui-rule-decorative) 8px + ); +} + +/* === Single hairline rule === */ +.nui-rule-hairline { + border: 0; + border-top: 1px solid var(--nui-rule-hairline); + margin: 0; +} diff --git a/packages/utils/src/__tests__/cx.test.ts b/packages/utils/src/__tests__/cx.test.ts new file mode 100644 index 0000000..6bdf38e --- /dev/null +++ b/packages/utils/src/__tests__/cx.test.ts @@ -0,0 +1,16 @@ +import { describe, it, expect } from 'vitest'; +import { cx } from '../cx'; + +describe('cx', () => { + it('joins truthy strings', () => { + expect(cx('a', 'b', 'c')).toBe('a b c'); + }); + + it('filters out falsy values', () => { + expect(cx('a', false, 'b', null, undefined, 'c')).toBe('a b c'); + }); + + it('returns empty string when all falsy', () => { + expect(cx(false, null, undefined)).toBe(''); + }); +}); diff --git a/packages/utils/src/cx.ts b/packages/utils/src/cx.ts new file mode 100644 index 0000000..8f48eeb --- /dev/null +++ b/packages/utils/src/cx.ts @@ -0,0 +1,6 @@ +type ClassValue = string | false | null | undefined; + +/** Tiny className joiner. Filters out falsy values. */ +export function cx(...args: ClassValue[]): string { + return args.filter(Boolean).join(' '); +} diff --git a/screenshots/01-frontpage-fold.png b/screenshots/01-frontpage-fold.png new file mode 100644 index 0000000..b2ceab7 Binary files /dev/null and b/screenshots/01-frontpage-fold.png differ diff --git a/screenshots/01b-frontpage-viewport.jpeg b/screenshots/01b-frontpage-viewport.jpeg new file mode 100644 index 0000000..9055fcf Binary files /dev/null and b/screenshots/01b-frontpage-viewport.jpeg differ diff --git a/screenshots/02-frontpage-full.png b/screenshots/02-frontpage-full.png new file mode 100644 index 0000000..0a37790 Binary files /dev/null and b/screenshots/02-frontpage-full.png differ diff --git a/screenshots/03-blackletter-fold.png b/screenshots/03-blackletter-fold.png new file mode 100644 index 0000000..1898176 Binary files /dev/null and b/screenshots/03-blackletter-fold.png differ diff --git a/screenshots/04-text-fold.png b/screenshots/04-text-fold.png new file mode 100644 index 0000000..a54f3f1 Binary files /dev/null and b/screenshots/04-text-fold.png differ diff --git a/screenshots/05-text-full.png b/screenshots/05-text-full.png new file mode 100644 index 0000000..29984cd Binary files /dev/null and b/screenshots/05-text-full.png differ diff --git a/screenshots/06-theme-light.png b/screenshots/06-theme-light.png new file mode 100644 index 0000000..74cedc9 Binary files /dev/null and b/screenshots/06-theme-light.png differ diff --git a/screenshots/07-theme-dark.png b/screenshots/07-theme-dark.png new file mode 100644 index 0000000..6e01c17 Binary files /dev/null and b/screenshots/07-theme-dark.png differ