# react-paperboard-ui
**Repository Path**: wangkai000/react-paperboard-ui
## Basic Information
- **Project Name**: react-paperboard-ui
- **Description**: 一款面向React的纸皮风格UI库
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-07-03
- **Last Updated**: 2026-07-14
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 📦 Paperboard UI
**瓦楞纸板质感 React 组件库 · Corrugated Cardboard Textured React Component Library**
[English](#english) · [中文](#中文)
> 6 种纸主题 · 5 种边缘模式 · 65 个组件 · SSR 安全 · 运行时主题切换
---
## English
A React component library with authentic corrugated cardboard texture. Built on Radix UI headless primitives + SCSS-crafted textures + CSS custom properties. Runtime theme switching with zero FOUC, full TypeScript support, SSR-safe.
> **Distribution model**: shadcn/ui-style atomic CLI distribution. Components are copied as source code into your project — fully customizable, no black-box dist files.
### ✨ Features
- **Runtime multi-theme** — 6 paper themes via `data-theme` + CSS variables, no reload needed
- **Corrugation toggle** — `data-corrugated` controls flute texture visibility
- **5 edge modes** — clean / torn / scissor / rough / zigzag, seeded PRNG generates stable `clip-path`
- **65 components** — full coverage: primitives, forms, layouts, navigation, feedback, data display, paper-style decorations
- **Radix headless + SCSS** — interaction logic by Radix UI, visual texture by SCSS Modules
- **TypeScript friendly** — full type exports, every component uses `forwardRef` + `displayName`
- **Source-first distribution** — no dist package; components live in your `src/` as editable source
---
### 📦 Quick Start (CLI)
```bash
# 1. Initialize paperboard in your React project
npx react-paperboard-ui init
# 2. Add components you need
npx react-paperboard-ui add Button
npx react-paperboard-ui add Card
npx react-paperboard-ui add Select
# 3. Import and use
```
```tsx
import { Button } from '@/components/paperboard-ui/Button';
import { Card } from '@/components/paperboard-ui/Card';
```
> **How it works**: `init` copies shared dependencies (ThemeProvider, tokens, edge hooks). `add ` resolves component dependencies, copies source files into your project, and installs required npm peer deps. All code is yours to modify.
>
> **Path alias**: The import path `@/components/paperboard-ui/` depends on your `tsconfig.json` path aliases. Make sure `@/*` → `./src/*` (or equivalent) is configured in `compilerOptions.paths`.
---
### 🚀 Usage Example
```tsx
import React, { useState } from 'react';
import { ThemeProvider, useTheme } from '@/theme';
import { Button } from '@/components/paperboard-ui/Button';
import { Card } from '@/components/paperboard-ui/Card';
import { Input } from '@/components/paperboard-ui/Input';
import { Tag } from '@/components/paperboard-ui/Tag';
import { Surface } from '@/components/paperboard-ui/Surface';
function App() {
const [name, setName] = useState('');
const { theme, setTheme, corrugated, setCorrugated } = useTheme();
return (
setTheme('kraft')}>Kraft
setTheme('dark')}>Dark
setTheme('rice')}>Rice
setCorrugated(!corrugated)}>
Corrugation: {corrugated ? 'ON' : 'OFF'}
Shipping Label
setName(e.target.value)} />
Fragile
Handle with care
Tracking #: PB-{Date.now().toString().slice(-6)}
Ship
);
}
export default function Root() {
return (
);
}
```
---
### 🎨 Theme System
6 built-in paper themes, switchable at runtime via `data-theme`:
| Theme | `data-theme` | Description |
|-------|-------------|-------------|
| Kraft paper | `kraft` | Default, standard cardboard brown |
| White board | `white` | Warm white tone |
| Dark board | `dark` | True dark mode (`color-scheme: dark`) |
| Rice paper | `rice` | Off-white, cool tone |
| Parchment | `parchment` | Yellowish antique |
| Letter paper | `letter` | Light cream |
#### ThemeProvider
```tsx
import { ThemeProvider } from '@/theme';
```
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `theme` | `PaperTheme` | `'kraft'` | Paper theme key |
| `corrugated` | `boolean` | `false` | Corrugation texture toggle |
| `defaultEdgeMode` | `EdgeMode` | `'clean'` | Default edge mode (overridable per component) |
| `container` | `HTMLElement` | `document.documentElement` | Target element for `data-*` attributes |
| `tokens` | `Partial` | — | CSS variable overrides (`--pb-*`) |
> **Auto dark mode**: If no `theme` is set and the system prefers `prefers-color-scheme: dark`, it auto-switches to `dark`. Manual `setTheme()` disables auto-following.
#### useTheme Hook
```tsx
import { useTheme } from '@/theme';
function ThemeSwitcher() {
const { theme, setTheme, corrugated, setCorrugated, defaultEdgeMode, setDefaultEdgeMode } = useTheme();
return (
<>
setTheme('dark')}>Switch to dark
setCorrugated(true)}>Enable corrugation
>
);
}
```
#### CSS Variable Names
```
--pb-paper-base / light / dark / cream / darker
--pb-flute / flute-dark
--pb-tape
--pb-accent / accent-hover / accent-deep
--pb-ink / ink-faded
--pb-success / warning / error / info (+ -deep variants)
--pb-white / black / border-color / cardboard
```
---
### ✂️ Edge Modes
5 edge modes powered by seeded PRNG (`mulberry32`) generating stable `clip-path: polygon(...)` values:
| Mode | Key | Description |
|------|-----|-------------|
| Clean | `clean` | Neat rectangular edge |
| Torn | `torn` | Hand-torn paper edge, moderate jitter |
| Scissor | `scissor` | Scissor-cut, straight segments with slight offset |
| Rough | `rough` | Rough tear, large jitter |
| Zigzag | `zigzag` | Natural zigzag pattern |
```tsx
Hand-torn edge
Scissor cut with custom seed
Rough torn card
```
The `seed` prop controls PRNG output for deterministic edge shapes — same seed produces identical results across renders (SSR-safe via `useMemo`).
---
### 📋 Components (65)
#### Primitives
| Component | Description | Key Props |
|-----------|-------------|-----------|
| **Surface** | Base paper surface | `variant`, `edgeMode`, `corrugated`, `paper`, `seed`, `asChild` |
#### Basics
| Component | Description | Key Props |
|-----------|-------------|-----------|
| **Button** | Paper-style button | `size`, `variant`, `icon`, `loading`, `block`, `asChild` |
| **Input** | Text input with label/prefix/suffix | `inputSize`, `error`, `label`, `prefix`, `suffix`, `addonBefore`, `addonAfter` |
| **Tag** | Inline tag/label | `variant`, `size`, `removable`, `onRemove` |
| **Chip** | Selectable/removable chip | `variant`, `size`, `selected`, `selectable`, `removable`, `icon`, `avatar` |
#### Forms
| Component | Description | Key Props |
|-----------|-------------|-----------|
| **Checkbox** | Paper checkbox | `checked`, `disabled`, `label`, `onCheckedChange` |
| **Radio** | Radio button | `value`, `checked`, `disabled`, `label` |
| **Switch** | Toggle switch | `checked`, `disabled`, `label`, `onCheckedChange` |
| **Select** | Dropdown (multi/search) | `value`, `multiple`, `options`, `searchable`, `size` |
| **Slider** | Range slider | `min`, `max`, `step`, `value`, `onChange`, `disabled` |
| **Form** | Form field wrapper | `label`, `required`, `error`, `helperText`, `name` |
#### Layout
| Component | Description | Key Props |
|-----------|-------------|-----------|
| **Card** | Paper card container (+ sub-components) | `variant`, `size`, `interactive`, `edgeMode` |
| **Panel** | Collapsible panel | `title`, `defaultOpen`, `onOpenChange` |
| **Divider** | Divider line | `orientation`, `variant`, `label`, `align` |
| **Descriptions** | Key-value list | `items`, `column`, `bordered`, `title` |
#### Navigation
| Component | Description | Key Props |
|-----------|-------------|-----------|
| **Tabs** | Tab navigation (Radix) | `Tabs.List`, `Tabs.Trigger`, `Tabs.Content` |
| **Breadcrumb** | Breadcrumb trail | `separator`, `Breadcrumb.Item` |
| **Pagination** | Page navigation | `current`, `total`, `pageSize`, `onChange`, `size` |
| **Menu** | Vertical/horizontal menu | `items`, `selectedKey`, `onSelect`, `mode` |
| **Steps** | Step progress | `Steps.Step` (`title`, `description`) |
| **Segmented** | Segmented control | `options`, `value`, `onChange` |
#### Feedback
| Component | Description | Key Props |
|-----------|-------------|-----------|
| **Tooltip** | Hover tooltip (Radix) | `content`, `side`, `delayDuration` |
| **Popover** | Floating popover (Radix) | `open`, `defaultOpen`, `onOpenChange` |
| **Dropdown** | Dropdown menu (Radix) | `Dropdown.Item`, `Dropdown.Trigger` |
| **Progress** | Progress bar | `value`, `max`, `indicatorColor` |
| **Skeleton** | Loading skeleton | `width`, `height`, `variant` |
| **Spinner** | Loading spinner | `size`, `color` |
| **Alert** | Alert message | `variant`, `title`, `edgeMode` |
| **Badge** | Status badge / count | `variant`, `size`, `dot`, `count`, `overflowCount` |
| **Toast** | Toast notification (Radix) | `Toast.Provider`, `Toast.Viewport`, `useToast()` |
| **Message** | Inline message | `children`, `defaultDuration` |
| **Notification** | Notification stack | `children`, `defaultDuration` |
| **EmptyState** | Empty data placeholder | `icon`, `title`, `description`, `action` |
| **Result** | Result page | `status`, `icon`, `title`, `subTitle`, `extra` |
#### Data Display
| Component | Description | Key Props |
|-----------|-------------|-----------|
| **Avatar** | User avatar | `src`, `alt`, `size`, `shape`, `fallback`, `status` |
| **Table** | Data table (+ sub-components) | `bordered`, `striped`, `stickyHeader`, `size` |
| **List** | Data list | `items`, `bordered`, `size` |
| **Statistic** | Statistic display | `title`, `value`, `prefix`, `suffix`, `precision`, `trend` |
| **Accordion** | Collapsible accordion | `title`, `defaultOpen`, `disabled` |
#### Overlays
| Component | Description | Key Props |
|-----------|-------------|-----------|
| **Drawer** | Side drawer | `open`, `onOpenChange`, `title`, `side`, `size` |
| **Modal** | Modal dialog | `open`, `onOpenChange`, `title`, `description`, `size` |
#### Paper-Style (25 decorative)
| Component | Description | Key Props |
|-----------|-------------|-----------|
| **Stamp** | Rubber stamp imprint | `color`, `variant`, `edgeMode`, `size`, `rotate` |
| **WaxSeal** | Wax seal with embossed pattern | `color`, `size`, `rotate`, `seal`, `shape` |
| **Tape** | Adhesive tape piece | `position`, `color`, `width`, `edgeMode` |
| **Ribbon** | Decorative ribbon | `color`, `position`, `edgeMode` |
| **Envelope** | Openable letter envelope | `sender`, `recipient`, `edgeMode` |
| **StickyNote** | Sticky note paper | `color`, `rotate`, `as` |
| **PaperStack** | Stack of paper layers (draggable) | `layers`, `offset`, `maxVisible`, `sortable` |
| **Timeline** | Vertical timeline | `items`, `mode`, `edgeMode` |
| **BulletinBoard** | Bulletin board with pins | `title`, `backgroundColor` |
| **CarbonCopy** | Carbon copy paper | `copies`, `defaultValue` |
| **ClippingBoard** | Clipping board | `clips` |
| **DeskMat** | Desk mat with grid/ruler | `gridSize`, `showRuler` |
| **FileFolder** | File folder tab | `title`, `files`, `expanded` |
| **JournalPage** | Journal page layout | `date`, `title` |
| **LetterSet** | Complete letter set | `sender`, `recipient`, `content`, `stampType`, `waxColor` |
| **NotePad** | Note pad with tear-off pages | `pages`, `currentPage`, `onTear` |
| **PageTurn** | Flip page animation | `front`, `back`, `open`, `direction` |
| **PaperClip** | Paper clip decoration | `position`, `color`, `size` |
| **PaperConfetti** | Confetti paper pieces | `count`, `active` |
| **PaperCut** | Papercut layered reveal | `revealed`, `layers` |
| **PaperPlane** | Flying paper plane animation | `flying`, `onComplete` |
| **PushPin** | Push pin decoration | `position`, `color`, `size` |
| **StickyWall** | Sticky notes wall | `notes`, `backgroundColor` |
| **WritingPaper** | Lined writing paper | `lineType`, `lineColor` |
---
### 📝 Paper-Style Components In Detail
The paper-style components are what make Paperboard UI unique — they simulate real-world paper objects with authentic textures and interactions.
**Stamp** — Rubber stamp with 4 ink colors, 3 shapes, rotation. Edge mode for distressed edges.
```tsx
APPROVED
```
**WaxSeal** — Wax seal with embossed pattern, 6 colors, 4 sizes. Includes wax bleed, highlight, and crack textures.
```tsx
```
**Tape** — Adhesive tape in 8 positions, 3 colors. Edge mode for torn tape ends.
```tsx
FRAGILE
```
**Ribbon** — Decorative ribbon banner at top-left or top-right corner.
```tsx
Sale
```
**Envelope** — Letter envelope with sender/recipient, openable flap with torn edge.
```tsx
Dear Bob, ...
```
**StickyNote** — Classic sticky note in 5 colors, auto-rotation (seed-based for SSR stability).
```tsx
Don't forget to ship!
Urgent
```
**PaperStack** — Stack of paper layers with offset visualization, draggable sorting (via @dnd-kit).
```tsx
Top sheet
}]} offset={6} sortable />
```
**Timeline** — Vertical timeline with dot or stamp mode.
```tsx
```
**BulletinBoard** — Cork-board style container for pinning notes.
```tsx
Meeting at 3pm
```
**CarbonCopy** — Carbon copy paper effect with multiple copies.
```tsx
```
**ClippingBoard** — Clipping board with clipped items.
```tsx
```
**DeskMat** — Desk mat with optional grid lines, ruler, and crop guide.
```tsx
Content on the mat
```
**FileFolder** — File folder tab with expandable file list.
```tsx
```
**JournalPage** — Journal page layout with date and title header.
```tsx
It was a good day.
```
**LetterSet** — Complete letter set: sender, recipient, stamp, wax seal.
```tsx
Dear Bob...} stampType="vintage" waxColor="red" />
```
**NotePad** — Note pad with tear-off pages and page navigation.
```tsx
console.log('Torn:', id)} />
```
**PageTurn** — Flip page animation with front/back content.
```tsx
Front} back={Back
} open={isOpen} direction="right" />
```
**PaperClip** / **PaperConfetti** / **PaperCut** / **PaperPlane** / **PushPin** — Decorative paper elements with animations.
```tsx
Hidden content
console.log('Sent!')} />
```
**StickyWall** — Sticky notes wall with multiple notes and background color.
```tsx
```
**WritingPaper** — Lined writing paper with ruled/grid/blank line types.
```tsx
Handwritten content here...
```
---
### 🔧 Local Development
```bash
git clone https://gitee.com/wangkai000/react-paperboard-ui.git
cd react-paperboard-ui
npm install
npm run dev # start demo site (Vite)
npm run build # build CLI tool (tsup, output to dist/cli/)
npm run test # run tests (Vitest + React Testing Library)
npm run storybook # start Storybook (port 6006)
npm run build-storybook # build Storybook static site
npm run type-check # TypeScript type check
npm run lint # ESLint check
```
---
### 🛠️ Tech Stack
| Category | Technology |
|----------|-----------|
| Framework | React 18 / 19 |
| Headless interaction | Radix UI (12 packages) |
| Styling | SCSS Modules + CSS Custom Properties |
| Icons | lucide-react |
| Bundling | Vite (library mode) + tsup (CLI) |
| Type system | TypeScript ~5.6 |
| Testing | Vitest + React Testing Library + jsdom |
| Docs | Storybook 8 |
| Drag & drop | @dnd-kit/core + @dnd-kit/sortable |
---
### 📄 License
MIT © [wangkai000](https://gitee.com/wangkai000)
Repository: [https://gitee.com/wangkai000/react-paperboard-ui](https://gitee.com/wangkai000/react-paperboard-ui)
---
## 中文
瓦楞纸板质感 React 组件库。基于 Radix UI 无头原语 + SCSS 拟物质感 + CSS 自定义属性构建。运行时主题切换无 FOUC,完整 TypeScript 类型支持,SSR 安全。
> **分发模式**:shadcn/ui 风格原子化 CLI 源码分发。组件以源码形式复制到你的项目中 — 完全可定制,无黑盒 dist 产物。
### ✨ 特性
- **运行时多主题** — 6 种纸主题通过 `data-theme` + CSS 变量切换,无需重新加载
- **瓦楞质感切换** — `data-corrugated` 控制瓦楞波纹纹理显隐
- **5 种边缘模式** — 整齐 / 手撕 / 剪刀 / 粗撕 / 自然锯齿
- **65 个组件** — 全量覆盖:原语、表单、布局、导航、反馈、数据展示、纸风格装饰
- **Radix 无头 + SCSS 拟物** — 交互逻辑由 Radix UI 负责,视觉质感由 SCSS 叠上纸皮纹理
- **TypeScript 友好** — 全组件 `forwardRef` + `displayName` + 完整类型导出
- **源码级分发** — 非传统 npm 包,组件源码直接存在于你的 `src/` 目录,随时可修改
---
### 📦 快速开始(CLI)
```bash
# 1. 在 React 项目中初始化 paperboard
npx react-paperboard-ui init
# 2. 按需添加组件
npx react-paperboard-ui add Button
npx react-paperboard-ui add Card
npx react-paperboard-ui add Select
# 3. 导入使用
```
```tsx
import { Button } from '@/components/paperboard-ui/Button';
import { Card } from '@/components/paperboard-ui/Card';
```
> **原理**:`init` 复制共享依赖(ThemeProvider、tokens、edge hooks)。`add <组件名>` 自动解析组件依赖树、复制源码到项目中、安装所需 npm peer 依赖。所有代码归你所有,自由修改。
>
> **路径别名说明**:导入路径 `@/components/paperboard-ui/` 取决于你的 `tsconfig.json` 路径别名配置。请确保 `compilerOptions.paths` 中已配置 `@/*` → `./src/*`(或等效映射)。
---
### 🚀 使用示例
---
### 🎨 主题系统
6 套内置纸主题,运行时通过 `data-theme` 切换:
| 主题 | `data-theme` | 说明 |
|------|-------------|------|
| 牛皮纸 | `kraft` | 默认,标准纸板棕色 |
| 白纸板 | `white` | 暖白色调 |
| 黑纸板 | `dark` | 真暗色模式 |
| 宣纸 | `rice` | 米白偏冷 |
| 羊皮纸 | `parchment` | 黄色仿旧 |
| 信纸 | `letter` | 浅米色 |
#### ThemeProvider
```tsx
```
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `theme` | `PaperTheme` | `'kraft'` | 纸主题标识 |
| `corrugated` | `boolean` | `false` | 瓦楞纹理开关 |
| `defaultEdgeMode` | `EdgeMode` | `'clean'` | 默认边缘模式 |
| `container` | `HTMLElement` | `document.documentElement` | `data-*` 属性注入目标 |
| `tokens` | `Partial` | — | CSS 变量覆盖 |
> **自动暗色模式**:未显式设置 `theme` 且系统偏好暗色时,自动切换到 `dark` 主题。手动调用 `setTheme()` 后不再跟随系统。
#### useTheme Hook
```tsx
import { useTheme } from '@/theme';
function ThemeSwitcher() {
const { theme, setTheme, corrugated, setCorrugated } = useTheme();
return (
<>
setTheme('dark')}>切换到黑纸板
setCorrugated(true)}>开启瓦楞
>
);
}
```
#### CSS 变量命名
```
--pb-paper-base / light / dark / cream / darker
--pb-flute / flute-dark
--pb-tape
--pb-accent / accent-hover / accent-deep
--pb-ink / ink-faded
--pb-success / warning / error / info(+ -deep 变体)
--pb-white / black / border-color / cardboard
```
---
### ✂️ 边缘模式
5 种边缘模式,基于 seeded PRNG(`mulberry32`)生成稳定的 `clip-path`:
| 模式 | 标识 | 说明 |
|------|------|------|
| 整齐 | `clean` | 规则矩形边缘 |
| 手撕 | `torn` | 手撕纸边,中等抖动 |
| 剪刀 | `scissor` | 剪刀剪裁,直线段带轻微偏移 |
| 粗撕 | `rough` | 粗暴撕裂,大抖动 |
| 锯齿 | `zigzag` | 自然锯齿纹路 |
```tsx
手撕边缘
剪刀边缘
粗撕卡片
```
`seed` 属性控制 PRNG 输出,相同 seed 始终产生相同边缘形状,SSR 安全。
---
### 📋 组件列表(65 个)
#### 原语
| 组件 | 说明 | 关键 Props |
|------|------|-----------|
| **Surface** | 纸面基础原语 | `variant`, `edgeMode`, `corrugated`, `seed` |
#### 基础
| 组件 | 说明 | 关键 Props |
|------|------|-----------|
| **Button** | 纸风格按钮 | `size`, `variant`, `icon`, `loading`, `block`, `asChild` |
| **Input** | 文本输入框 | `inputSize`, `error`, `label`, `prefix`, `suffix` |
| **Tag** | 行内标签 | `variant`, `size`, `removable` |
| **Chip** | 可选/可删除芯片 | `variant`, `size`, `selected`, `selectable`, `removable` |
#### 表单
| 组件 | 说明 | 关键 Props |
|------|------|-----------|
| **Checkbox** | 纸风格复选框 | `checked`, `disabled`, `label` |
| **Radio** | 单选按钮 | `value`, `checked`, `disabled` |
| **Switch** | 开关切换 | `checked`, `disabled`, `label` |
| **Select** | 下拉选择器(多选/搜索) | `value`, `multiple`, `options`, `searchable` |
| **Slider** | 滑块 | `min`, `max`, `step`, `value` |
| **Form** | 表单字段包裹器 | `label`, `required`, `error` |
#### 布局
| 组件 | 说明 | 关键 Props |
|------|------|-----------|
| **Card** | 纸卡片容器(含子组件) | `variant`, `size`, `edgeMode` |
| **Panel** | 可折叠面板 | `title`, `defaultOpen` |
| **Divider** | 分割线 | `orientation`, `variant`, `label` |
| **Descriptions** | 键值对描述列表 | `items`, `column`, `bordered` |
#### 导航
| 组件 | 说明 | 关键 Props |
|------|------|-----------|
| **Tabs** | 标签页导航(Radix) | `Tabs.List`, `Tabs.Trigger`, `Tabs.Content` |
| **Breadcrumb** | 面包屑 | `separator`, `Breadcrumb.Item` |
| **Pagination** | 分页 | `current`, `total`, `pageSize`, `onChange` |
| **Menu** | 垂直/水平菜单 | `items`, `selectedKey`, `onSelect` |
| **Steps** | 步骤条 | `Steps.Step` (`title`, `description`) |
| **Segmented** | 分段控制器 | `options`, `value`, `onChange` |
#### 反馈
| 组件 | 说明 | 关键 Props |
|------|------|-----------|
| **Tooltip** | 悬浮提示(Radix) | `content`, `side`, `delayDuration` |
| **Popover** | 浮层弹出(Radix) | `open`, `defaultOpen` |
| **Dropdown** | 下拉菜单(Radix) | `Dropdown.Item`, `Dropdown.Trigger` |
| **Progress** | 进度条 | `value`, `max`, `indicatorColor` |
| **Skeleton** | 骨架屏 | `width`, `height`, `variant` |
| **Spinner** | 加载旋转 | `size`, `color` |
| **Alert** | 警告提示 | `variant`, `title`, `edgeMode` |
| **Badge** | 状态徽标/计数 | `variant`, `size`, `dot`, `count` |
| **Toast** | 轻提示(Radix) | `Toast.Provider`, `Toast.Viewport`, `useToast()` |
| **Message** | 行内消息 | `children`, `defaultDuration` |
| **Notification** | 通知堆叠 | `children`, `defaultDuration` |
| **EmptyState** | 空数据占位 | `icon`, `title`, `description` |
| **Result** | 结果页 | `status`, `icon`, `title`, `subTitle` |
#### 数据展示
| 组件 | 说明 | 关键 Props |
|------|------|-----------|
| **Avatar** | 用户头像 | `src`, `alt`, `size`, `shape`, `fallback` |
| **Table** | 数据表格(含子组件) | `bordered`, `striped`, `stickyHeader` |
| **List** | 数据列表 | `items`, `bordered`, `size` |
| **Statistic** | 统计数值 | `title`, `value`, `prefix`, `suffix` |
| **Accordion** | 折叠手风琴 | `title`, `defaultOpen` |
#### 弹层
| 组件 | 说明 | 关键 Props |
|------|------|-----------|
| **Drawer** | 侧边抽屉 | `open`, `onOpenChange`, `title`, `side` |
| **Modal** | 模态弹窗 | `open`, `onOpenChange`, `title`, `description` |
#### 纸风格装饰(25 个)
| 组件 | 说明 | 关键 Props |
|------|------|-----------|
| **Stamp** | 橡胶印章 | `color`, `variant`, `edgeMode`, `rotate` |
| **WaxSeal** | 蜡封印章 | `color`, `size`, `rotate`, `seal` |
| **Tape** | 胶带 | `position`, `color`, `edgeMode` |
| **Ribbon** | 装饰缎带 | `color`, `position` |
| **Envelope** | 信封(可翻开) | `sender`, `recipient` |
| **StickyNote** | 便利贴 | `color`, `rotate`, `as` |
| **PaperStack** | 纸层堆叠(可拖拽排序) | `layers`, `offset`, `sortable` |
| **Timeline** | 垂直时间线 | `items`, `mode` |
| **BulletinBoard** | 公告板 | `title`, `backgroundColor` |
| **CarbonCopy** | 复写纸 | `copies`, `defaultValue` |
| **ClippingBoard** | 剪报板 | `clips` |
| **DeskMat** | 桌垫(网格/标尺) | `gridSize`, `showRuler` |
| **FileFolder** | 文件夹标签 | `title`, `files`, `expanded` |
| **JournalPage** | 日记页面 | `date`, `title` |
| **LetterSet** | 完整信件套装 | `sender`, `recipient`, `content` |
| **NotePad** | 记事本(可撕页) | `pages`, `currentPage`, `onTear` |
| **PageTurn** | 翻页动画 | `front`, `back`, `open` |
| **PaperClip** | 回形针装饰 | `position`, `color`, `size` |
| **PaperConfetti** | 纸屑飞溅 | `count`, `active` |
| **PaperCut** | 剪纸分层揭示 | `revealed`, `layers` |
| **PaperPlane** | 飞翔纸飞机 | `flying`, `onComplete` |
| **PushPin** | 图钉装饰 | `position`, `color`, `size` |
| **StickyWall** | 便签墙 | `notes`, `backgroundColor` |
| **WritingPaper** | 横线信纸 | `lineType`, `lineColor` |
---
### 🔧 本地开发
```bash
git clone https://gitee.com/wangkai000/react-paperboard-ui.git
cd react-paperboard-ui
npm install
npm run dev # 启动 demo 站(Vite)
npm run build # 构建 CLI 工具(tsup,输出到 dist/cli/)
npm run test # 运行测试(Vitest)
npm run storybook # 启动 Storybook(端口 6006)
npm run type-check # TypeScript 类型检查
npm run lint # ESLint 检查
```
---
### 🛠️ 技术栈
| 类别 | 技术 |
|------|------|
| 框架 | React 18 / 19 |
| 无头交互 | Radix UI(12 个包) |
| 样式 | SCSS Modules + CSS 自定义属性 |
| 图标 | lucide-react |
| 打包 | Vite(库模式) |
| 类型 | TypeScript ~5.6 |
| 测试 | Vitest + React Testing Library |
| 文档 | Storybook 8 |
| 拖拽 | @dnd-kit/core + @dnd-kit/sortable |
---
### 📄 License
MIT © [wangkai000](https://gitee.com/wangkai000)
仓库地址:[https://gitee.com/wangkai000/react-paperboard-ui](https://gitee.com/wangkai000/react-paperboard-ui)