This commit is contained in:
sunzhongyi
2026-05-19 21:09:56 +08:00
commit f3e6b95be9
78 changed files with 10099 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
{
"name": "@newspaperui/theme",
"version": "0.0.0",
"description": "Theme tokens and CSS variables for newspaperui",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
},
"./variables.css": "./src/variables.css",
"./tailwind.config": "./src/tailwind.config.js"
},
"files": [
"dist",
"src/variables.css",
"src/tailwind.config.js"
],
"scripts": {
"build": "vite build",
"dev": "vite build --watch",
"lint": "tsc --noEmit",
"clean": "rm -rf dist"
},
"devDependencies": {
"typescript": "^5.7.2",
"vite": "^5.4.11",
"vite-plugin-dts": "^4.3.0"
}
}
+21
View File
@@ -0,0 +1,21 @@
/**
* @newspaperui/theme
* Theme tokens and CSS variables for newspaperui
*/
// Import CSS variables
import './variables.css';
// Export visual weight types and configuration
export type {
VisualWeight,
ComponentType,
VisualWeightConfig,
} from './visual-weights';
export { visualWeights, resolveFontSize } from './visual-weights';
// Export Tailwind config for consumers
export { default as tailwindConfig } from './tailwind.config.js';
export const version = '0.0.0';
+103
View File
@@ -0,0 +1,103 @@
/**
* Tailwind CSS Configuration for NewspaperUI
* Extends Tailwind with newspaper-specific utilities and 24-column grid
*/
const config = {
theme: {
extend: {
colors: {
nui: {
text: {
primary: 'var(--nui-color-text-primary)',
secondary: 'var(--nui-color-text-secondary)',
tertiary: 'var(--nui-color-text-tertiary)',
quaternary: 'var(--nui-color-text-quaternary)',
muted: 'var(--nui-color-text-muted)',
},
gray: {
50: 'var(--nui-color-gray-50)',
100: 'var(--nui-color-gray-100)',
200: 'var(--nui-color-gray-200)',
300: 'var(--nui-color-gray-300)',
400: 'var(--nui-color-gray-400)',
500: 'var(--nui-color-gray-500)',
600: 'var(--nui-color-gray-600)',
700: 'var(--nui-color-gray-700)',
800: 'var(--nui-color-gray-800)',
900: 'var(--nui-color-gray-900)',
},
accent: {
primary: 'var(--nui-color-accent-primary)',
secondary: 'var(--nui-color-accent-secondary)',
tertiary: 'var(--nui-color-accent-tertiary)',
},
},
},
spacing: {
'nui-gutter': 'var(--nui-gutter)',
'nui-gutter-sm': 'var(--nui-gutter-sm)',
'nui-gutter-lg': 'var(--nui-gutter-lg)',
},
fontFamily: {
'nui-serif': 'var(--nui-font-serif)',
'nui-serif-display': 'var(--nui-font-serif-display)',
'nui-sans': 'var(--nui-font-sans)',
'nui-sans-condensed': 'var(--nui-font-sans-condensed)',
'nui-mono': 'var(--nui-font-mono)',
},
fontSize: {
'nui-xs': 'var(--nui-font-size-xs)',
'nui-sm': 'var(--nui-font-size-sm)',
'nui-base': 'var(--nui-font-size-base)',
'nui-lg': 'var(--nui-font-size-lg)',
'nui-xl': 'var(--nui-font-size-xl)',
'nui-2xl': 'var(--nui-font-size-2xl)',
'nui-3xl': 'var(--nui-font-size-3xl)',
'nui-4xl': 'var(--nui-font-size-4xl)',
'nui-5xl': 'var(--nui-font-size-5xl)',
'nui-6xl': 'var(--nui-font-size-6xl)',
},
fontWeight: {
'nui-normal': 'var(--nui-font-weight-normal)',
'nui-medium': 'var(--nui-font-weight-medium)',
'nui-semibold': 'var(--nui-font-weight-semibold)',
'nui-bold': 'var(--nui-font-weight-bold)',
},
lineHeight: {
'nui-tight': 'var(--nui-line-height-tight)',
'nui-snug': 'var(--nui-line-height-snug)',
'nui-normal': 'var(--nui-line-height-normal)',
'nui-relaxed': 'var(--nui-line-height-relaxed)',
'nui-loose': 'var(--nui-line-height-loose)',
'nui-body': 'var(--nui-line-height-body)',
},
maxWidth: {
'nui-grid': 'var(--nui-grid-max-width)',
},
// 24-column grid utilities
gridTemplateColumns: {
'nui-24': 'repeat(24, minmax(0, 1fr))',
'nui-16': 'repeat(16, minmax(0, 1fr))',
'nui-12': 'repeat(12, minmax(0, 1fr))',
},
gridColumn: {
'span-13': 'span 13 / span 13',
'span-14': 'span 14 / span 14',
'span-15': 'span 15 / span 15',
'span-16': 'span 16 / span 16',
'span-17': 'span 17 / span 17',
'span-18': 'span 18 / span 18',
'span-19': 'span 19 / span 19',
'span-20': 'span 20 / span 20',
'span-21': 'span 21 / span 21',
'span-22': 'span 22 / span 22',
'span-23': 'span 23 / span 23',
'span-24': 'span 24 / span 24',
},
},
},
plugins: [],
};
export default config;
+127
View File
@@ -0,0 +1,127 @@
/**
* NewspaperUI Theme Variables
* Global CSS variables for newspaper layout system
*/
:root {
/* ========== Color System ========== */
/* Primary text colors */
--nui-color-text-primary: #111111;
--nui-color-text-secondary: #222222;
--nui-color-text-tertiary: #333333;
--nui-color-text-quaternary: #444444;
--nui-color-text-muted: #555555;
/* Gray scale */
--nui-color-gray-50: #fafafa;
--nui-color-gray-100: #f5f5f5;
--nui-color-gray-200: #e5e5e5;
--nui-color-gray-300: #d4d4d4;
--nui-color-gray-400: #a3a3a3;
--nui-color-gray-500: #737373;
--nui-color-gray-600: #525252;
--nui-color-gray-700: #404040;
--nui-color-gray-800: #262626;
--nui-color-gray-900: #171717;
/* Accent colors */
--nui-color-accent-primary: #0066cc;
--nui-color-accent-secondary: #cc0000;
--nui-color-accent-tertiary: #006600;
/* ========== Spacing System ========== */
/* Gutter (column gap) */
--nui-gutter: 1rem;
--nui-gutter-sm: 0.75rem;
--nui-gutter-lg: 1.5rem;
/* Margin */
--nui-margin-xs: 0.25rem;
--nui-margin-sm: 0.5rem;
--nui-margin-md: 0.75rem;
--nui-margin-lg: 1rem;
--nui-margin-xl: 1.5rem;
/* Padding */
--nui-padding-xs: 0.25rem;
--nui-padding-sm: 0.5rem;
--nui-padding-md: 0.75rem;
--nui-padding-lg: 1rem;
--nui-padding-xl: 1.5rem;
/* ========== Font System ========== */
/* Serif fonts for headlines and body text */
--nui-font-serif: 'Georgia', 'Times New Roman', serif;
--nui-font-serif-display: 'Playfair Display', 'Georgia', serif;
/* Sans-serif fonts for UI elements */
--nui-font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
--nui-font-sans-condensed: 'Arial Narrow', 'Helvetica Condensed', sans-serif;
/* Monospace for code */
--nui-font-mono: 'Courier New', Courier, monospace;
/* ========== Grid System ========== */
/* 24-column grid */
--nui-grid-columns: 24;
--nui-grid-max-width: 1440px;
--nui-grid-container-padding: 2rem;
/* Responsive breakpoints */
--nui-breakpoint-sm: 768px;
--nui-breakpoint-md: 1024px;
--nui-breakpoint-lg: 1440px;
/* ========== Typography Scale ========== */
/* Font sizes */
--nui-font-size-xs: 0.75rem; /* 12px */
--nui-font-size-sm: 0.875rem; /* 14px */
--nui-font-size-base: 1rem; /* 16px */
--nui-font-size-lg: 1.125rem; /* 18px */
--nui-font-size-xl: 1.25rem; /* 20px */
--nui-font-size-2xl: 1.5rem; /* 24px */
--nui-font-size-3xl: 1.75rem; /* 28px */
--nui-font-size-4xl: 2rem; /* 32px */
--nui-font-size-5xl: 2.25rem; /* 36px */
--nui-font-size-6xl: 3rem; /* 48px */
/* Font weights */
--nui-font-weight-normal: 400;
--nui-font-weight-medium: 500;
--nui-font-weight-semibold: 600;
--nui-font-weight-bold: 700;
/* Line heights */
--nui-line-height-tight: 1.1;
--nui-line-height-snug: 1.2;
--nui-line-height-normal: 1.25;
--nui-line-height-relaxed: 1.3;
--nui-line-height-loose: 1.4;
--nui-line-height-body: 1.5;
}
[data-theme="dark"] {
/* Primary text colors */
--nui-color-text-primary: #eeeeee;
--nui-color-text-secondary: #dddddd;
--nui-color-text-tertiary: #cccccc;
--nui-color-text-quaternary: #bbbbbb;
--nui-color-text-muted: #aaaaaa;
/* Gray scale */
--nui-color-gray-50: #171717;
--nui-color-gray-100: #262626;
--nui-color-gray-200: #404040;
--nui-color-gray-300: #525252;
--nui-color-gray-400: #737373;
--nui-color-gray-500: #a3a3a3;
--nui-color-gray-600: #d4d4d4;
--nui-color-gray-700: #e5e5e5;
--nui-color-gray-800: #f5f5f5;
--nui-color-gray-900: #fafafa;
/* Accent colors */
--nui-color-accent-primary: #4da6ff;
--nui-color-accent-secondary: #ff6666;
--nui-color-accent-tertiary: #66cc66;
}
+164
View File
@@ -0,0 +1,164 @@
/**
* Resolves a fontSize value to a single CSS string.
* For range tuples [min, max], returns the lower bound (min).
*/
export function resolveFontSize(fontSize: string | [string, string]): string {
return Array.isArray(fontSize) ? fontSize[0] : fontSize;
}
export type VisualWeight = 'High' | 'Medium' | 'Low' | 'Standard';
export type ComponentType =
| 'Headline'
| 'Subhead'
| 'BodyText'
| 'Quote'
| 'PullQuote'
| 'Byline'
| 'Caption';
export interface VisualWeightConfig {
fontSize: string | [string, string];
fontWeight: number;
lineHeight: number;
color: string;
span: number | [number, number];
margin: string;
}
/**
* Visual weight configuration mapping
* Maps component types and their visual weights to specific styling configurations
*/
export const visualWeights: Record<
ComponentType,
Partial<Record<VisualWeight, VisualWeightConfig>>
> = {
Headline: {
High: {
fontSize: ['36px', '48px'],
fontWeight: 700,
lineHeight: 1.1,
color: '#111',
span: [6, 8],
margin: '0 0 1rem 0',
},
Medium: {
fontSize: ['28px', '34px'],
fontWeight: 600,
lineHeight: 1.2,
color: '#111',
span: [4, 6],
margin: '0 0 0.75rem 0',
},
Low: {
fontSize: ['22px', '26px'],
fontWeight: 500,
lineHeight: 1.3,
color: '#222',
span: [2, 4],
margin: '0 0 0.5rem 0',
},
},
Subhead: {
High: {
fontSize: ['20px', '24px'],
fontWeight: 600,
lineHeight: 1.25,
color: '#222',
span: [2, 3],
margin: '0 0 0.5rem 0',
},
Medium: {
fontSize: ['16px', '18px'],
fontWeight: 500,
lineHeight: 1.3,
color: '#333',
span: [1, 2],
margin: '0 0 0.25rem 0',
},
},
BodyText: {
High: {
fontSize: '16px',
fontWeight: 400,
lineHeight: 1.5,
color: '#333',
span: 1,
margin: '0 0 1rem 0',
},
Medium: {
fontSize: ['14px', '15px'],
fontWeight: 400,
lineHeight: 1.5,
color: '#444',
span: 1,
margin: '0 0 0.75rem 0',
},
Low: {
fontSize: ['12px', '14px'],
fontWeight: 400,
lineHeight: 1.4,
color: '#555',
span: 1,
margin: '0 0 0.5rem 0',
},
},
Quote: {
High: {
fontSize: ['20px', '24px'],
fontWeight: 500,
lineHeight: 1.4,
color: '#222',
span: 2,
margin: '0 0 0.75rem 0',
},
Medium: {
fontSize: ['16px', '18px'],
fontWeight: 400,
lineHeight: 1.4,
color: '#333',
span: 1,
margin: '0 0 0.5rem 0',
},
},
PullQuote: {
High: {
fontSize: ['24px', '28px'],
fontWeight: 600,
lineHeight: 1.2,
color: '#111',
span: [2, 3],
margin: '0 0 0.5rem 0',
},
Medium: {
fontSize: ['18px', '20px'],
fontWeight: 500,
lineHeight: 1.25,
color: '#222',
span: [1, 2],
margin: '0 0 0.25rem 0',
},
},
Byline: {
Standard: {
fontSize: ['12px', '14px'],
fontWeight: 400,
lineHeight: 1.3,
color: '#555',
span: 1,
margin: '0 0 0.25rem 0',
},
},
Caption: {
Standard: {
fontSize: ['12px', '14px'],
fontWeight: 400,
lineHeight: 1.3,
color: '#555',
span: 1,
margin: '0.25rem 0',
},
},
};
+8
View File
@@ -0,0 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src"]
}
+22
View File
@@ -0,0 +1,22 @@
import { defineConfig } from 'vite';
import { resolve } from 'path';
import dts from 'vite-plugin-dts';
export default defineConfig({
plugins: [
dts({
insertTypesEntry: true,
}),
],
build: {
lib: {
entry: resolve(__dirname, 'src/index.ts'),
name: 'NewspaperUITheme',
formats: ['es', 'cjs'],
fileName: (format) => `index.${format === 'es' ? 'js' : 'cjs'}`,
},
rollupOptions: {
external: [],
},
},
});