From 5f65d741edba41882c2811cea33fed24f2b764cc Mon Sep 17 00:00:00 2001 From: sunzhongyi Date: Thu, 21 May 2026 10:04:35 +0800 Subject: [PATCH] feat: responsive system, engineering infra, new components, performance - Section: responsive prop with media query injection - visual-weights: fontSize clamp() for responsive sizing - variables.css: add border-radius/shadow/transition/z-index tokens - ESLint flat config + Prettier + Changeset init - New components: Footer, NewsSidebar, BreakingNewsBanner - Image/Figure: loading=lazy, aspectRatio, sizes props --- .changeset/README.md | 8 + .changeset/config.json | 11 + .prettierignore | 5 + .prettierrc | 7 + eslint.config.js | 22 + package.json | 12 +- packages/components/package.json | 30 +- packages/components/src/index.ts | 8 +- packages/components/src/layout/Article.tsx | 2 +- .../src/layout/BreakingNewsBanner.tsx | 48 + packages/components/src/layout/Footer.tsx | 57 + packages/components/src/layout/Masthead.tsx | 2 +- packages/components/src/layout/Rule.tsx | 2 +- packages/components/src/layout/Section.tsx | 17 +- packages/components/src/layout/Sidebar.tsx | 47 + packages/components/src/media/Figure.tsx | 27 +- packages/components/src/media/Image.tsx | 15 +- packages/components/src/media/PullQuote.tsx | 4 +- packages/components/src/media/Video.tsx | 2 +- packages/components/src/text/BodyText.tsx | 4 +- packages/components/src/text/Byline.tsx | 4 +- packages/components/src/text/Caption.tsx | 4 +- packages/components/src/text/Dateline.tsx | 4 +- packages/components/src/text/Headline.tsx | 4 +- packages/components/src/text/Kicker.tsx | 4 +- packages/components/src/text/Quote.tsx | 4 +- packages/components/src/text/Subhead.tsx | 4 +- .../app/(docs)/components/article/page.tsx | 2 +- .../app/(docs)/components/masthead/page.tsx | 2 +- .../docs/app/(docs)/components/media/page.tsx | 2 +- .../docs/app/(docs)/components/rule/page.tsx | 2 +- .../app/(docs)/examples/responsive/page.tsx | 2 +- .../app/(docs)/examples/spanning/page.tsx | 2 +- packages/docs/app/(docs)/grid-system/page.tsx | 2 +- packages/docs/app/(docs)/text/page.tsx | 4 +- packages/docs/app/(docs)/theme/page.tsx | 2 +- packages/docs/app/blocks/en-feature/page.tsx | 2 +- .../docs/app/blocks/jp-horizontal/page.tsx | 2 +- packages/docs/app/blocks/page.tsx | 2 +- .../docs/app/blocks/zh-editorial/page.tsx | 2 +- packages/docs/app/blocks/zh-feature/page.tsx | 2 +- .../docs/app/blocks/zh-frontpage/page.tsx | 2 +- .../examples/blackletter-frontpage/page.tsx | 2 +- .../docs/app/examples/nyt-frontpage/page.tsx | 2 +- packages/docs/app/globals.css | 2 +- packages/docs/app/page.tsx | 8 +- packages/docs/components/Sidebar.tsx | 2 +- packages/docs/next.config.mjs | 2 +- packages/docs/package.json | 10 +- packages/theme/package.json | 24 +- packages/theme/src/variables.css | 22 + packages/theme/src/visual-weights.ts | 12 +- packages/utils/package.json | 22 +- pnpm-lock.yaml | 2362 ++++++++++++++++- 54 files changed, 2759 insertions(+), 101 deletions(-) create mode 100644 .changeset/README.md create mode 100644 .changeset/config.json create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 eslint.config.js create mode 100644 packages/components/src/layout/BreakingNewsBanner.tsx create mode 100644 packages/components/src/layout/Footer.tsx create mode 100644 packages/components/src/layout/Sidebar.tsx diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 0000000..654c6d4 --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets). + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md). diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000..5c58ec9 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.1.4/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "restricted", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..16550bd --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +dist +out +.next +node_modules +pnpm-lock.yaml diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..4cbc711 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "printWidth": 100, + "tabWidth": 2 +} diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..18f28ee --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,22 @@ +import js from '@eslint/js'; +import tseslint from 'typescript-eslint'; +import react from 'eslint-plugin-react'; +import reactHooks from 'eslint-plugin-react-hooks'; + +export default tseslint.config( + js.configs.recommended, + ...tseslint.configs.recommended, + { + files: ['**/*.{ts,tsx}'], + plugins: { react, 'react-hooks': reactHooks }, + rules: { + 'react/react-in-jsx-scope': 'off', + '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], + '@typescript-eslint/no-explicit-any': 'warn', + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/exhaustive-deps': 'warn', + }, + settings: { react: { version: 'detect' } }, + }, + { ignores: ['**/dist/**', '**/node_modules/**', '**/.next/**', '**/out/**', 'packages/docs/**'] }, +); diff --git a/package.json b/package.json index 526714a..d882609 100644 --- a/package.json +++ b/package.json @@ -2,17 +2,25 @@ "name": "newspaperui", "version": "0.0.0", "private": true, + "type": "module", "description": "A newspaper-style UI component library", "scripts": { "build": "turbo run build", "dev": "turbo run dev", - "lint": "turbo run lint", + "lint": "eslint packages/*/src/", "test": "turbo run test", "clean": "turbo run clean && rm -rf node_modules" }, "devDependencies": { + "@changesets/cli": "^2.31.0", + "@eslint/js": "^10.0.1", + "eslint": "^10.4.0", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^7.1.1", + "prettier": "^3.8.3", "turbo": "^2.3.3", - "typescript": "^5.7.2" + "typescript": "^5.7.2", + "typescript-eslint": "^8.59.4" }, "packageManager": "pnpm@9.15.4", "engines": { diff --git a/packages/components/package.json b/packages/components/package.json index a9b4529..f2ee5ff 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,7 +1,7 @@ { - "name": "@newspaperui/components", - "version": "0.0.0", - "description": "React components for newspaperui", + "name": "newspaperui-components", + "version": "0.1.0", + "description": "Production-grade newspaper layout React components", "type": "module", "main": "./dist/index.cjs", "module": "./dist/index.js", @@ -29,8 +29,8 @@ "react-dom": "^18.3.1" }, "dependencies": { - "@newspaperui/theme": "workspace:*", - "@newspaperui/utils": "workspace:*" + "newspaperui-theme": "workspace:*", + "newspaperui-utils": "workspace:*" }, "devDependencies": { "@testing-library/react": "^16.1.0", @@ -45,5 +45,23 @@ "vite": "^5.4.11", "vite-plugin-dts": "^4.3.0", "vitest": "^2.1.8" + }, + "license": "MIT", + "author": "sunzhongyi", + "repository": { + "type": "git", + "url": "https://github.com/joisun/newspaperui.git" + }, + "keywords": [ + "newspaper", + "react", + "components", + "layout", + "typography", + "css-grid", + "multi-column" + ], + "publishConfig": { + "access": "public" } -} +} \ No newline at end of file diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 79ff6ba..3f85b6e 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -1,4 +1,4 @@ -import '@newspaperui/theme'; +import 'newspaperui-theme'; // layout export { Layout, useLayout } from './layout/Layout'; @@ -13,6 +13,12 @@ export { Masthead } from './layout/Masthead'; export type { MastheadProps } from './layout/Masthead'; export { Rule } from './layout/Rule'; export type { RuleProps } from './layout/Rule'; +export { Footer } from './layout/Footer'; +export type { FooterProps } from './layout/Footer'; +export { Sidebar as NewsSidebar } from './layout/Sidebar'; +export type { SidebarProps as NewsSidebarProps } from './layout/Sidebar'; +export { BreakingNewsBanner } from './layout/BreakingNewsBanner'; +export type { BreakingNewsBannerProps } from './layout/BreakingNewsBanner'; // text export { Headline } from './text/Headline'; diff --git a/packages/components/src/layout/Article.tsx b/packages/components/src/layout/Article.tsx index 8ef263c..22668c2 100644 --- a/packages/components/src/layout/Article.tsx +++ b/packages/components/src/layout/Article.tsx @@ -1,6 +1,6 @@ 'use client'; import React, { ReactNode, CSSProperties } from 'react'; -import { clampSpan, cx } from '@newspaperui/utils'; +import { clampSpan, cx } from 'newspaperui-utils'; import { useSection } from './Section'; export interface ArticleProps { diff --git a/packages/components/src/layout/BreakingNewsBanner.tsx b/packages/components/src/layout/BreakingNewsBanner.tsx new file mode 100644 index 0000000..1269c5f --- /dev/null +++ b/packages/components/src/layout/BreakingNewsBanner.tsx @@ -0,0 +1,48 @@ +'use client'; +import React, { ReactNode, CSSProperties } from 'react'; +import { cx } from 'newspaperui-utils'; + +export interface BreakingNewsBannerProps { + label?: string; + className?: string; + style?: CSSProperties; + children: ReactNode; +} + +/** + * BreakingNewsBanner — 突发新闻横幅 + * + * @example + * + * Major earthquake strikes coastal region + * + */ +export const BreakingNewsBanner: React.FC = ({ + label = 'BREAKING', className, style, children, +}) => ( +
+ {label} + {children} +
+); diff --git a/packages/components/src/layout/Footer.tsx b/packages/components/src/layout/Footer.tsx new file mode 100644 index 0000000..35cf582 --- /dev/null +++ b/packages/components/src/layout/Footer.tsx @@ -0,0 +1,57 @@ +'use client'; +import React, { ReactNode, CSSProperties } from 'react'; +import { cx } from 'newspaperui-utils'; + +export interface FooterProps { + copyright?: string; + edition?: string; + links?: Array<{ label: string; href: string }>; + className?: string; + style?: CSSProperties; + children?: ReactNode; +} + +/** + * Footer — 报纸页脚/版权信息区 + * + * @example + *