@dendelion/paper-ui
Natural-material React component library — paper, ink, canvas, and watercolor.
Features
- Natural Materials — Textured paper backgrounds, ink borders, canvas weaves, watercolor washes
- 37 Components — Layout primitives, form controls, data display, navigation, feedback, and overlays (see Components)
- Tailwind CSS Preset —
paperPresetwith warm color tokens (paper, ink, canvas, watercolor) - 7 Paper Textures — SVG-generated grain: white, paper, speckle, parchment, canvas, kraft, chalkboard
- Ruled Overlays — Notebook lines and grid patterns in blue, brown, or black
- TypeScript — Full type support with strict checking
- SCSS Modules — Scoped component styles with shared mixins and tokens
- Self-Hosted Fonts — Luminari (display), Cormorant Garamond (body), Caveat (handwritten)
Installation
npm install @dendelion/paper-ui
# or
pnpm add @dendelion/paper-uiPeer Dependencies
npm install react react-dom tailwindcssQuick Start
1. Configure Tailwind CSS
// tailwind.config.ts
import { paperPreset } from '@dendelion/paper-ui/tailwind';
export default {
presets: [paperPreset],
content: ['./src/**/*.{js,jsx,ts,tsx}'],
};2. Import Global Styles
// In your app entry (e.g., main.tsx)
import '@dendelion/paper-ui/dist/index.css';This imports the bundled CSS including fonts, base styles, and Tailwind directives.
3. Use Components
import { Layout, Page, Button, Checkbox, IconButton } from '@dendelion/paper-ui';
function App() {
return (
<Layout
title="Dashboard"
subtitle="Welcome back"
navigationItems={[
{ id: 'home', label: 'Home', path: '/' },
{ id: 'plans', label: 'Plans', path: '/plans' },
]}
>
<Page>
<Button variant="primary" size="medium">
Create Plan
</Button>
<Checkbox label="Show completed" />
<IconButton icon={<SettingsIcon />} label="Settings" />
</Page>
</Layout>
);
}Components
The library exports 37 components. The core layout and form primitives are documented below; the full set is:
| Category | Components |
|---|---|
| Layout | Layout, Page, Card, Divider, Accordion |
| Navigation | Island, NavigationIsland, Tabs, Breadcrumb, Pagination |
| Forms | Button, IconButton, Checkbox, Radio, RadioGroup, Switch, Input, Select, Textarea |
| Data display | Table, ListItem, Stamp, Badge, Avatar, PropTable, Swatch, Icon |
| Feedback | Alert, ToastProvider, Progress, Spinner, Skeleton |
| Overlay | Modal, Tooltip, Menu |
| Code | CodeBlock, CopyButton |
All components are documented with live demos and prop tables in the built-in showcase (pnpm run dev).
All components are named exports with a matching {Component}Props type.
Components that support the dark "chalkboard" theme accept a surface prop ('paper' | 'chalkboard', default 'paper'), kept separate from each component's semantic variant:
<Button variant="primary" surface="chalkboard">Save</Button>
<Input label="Name" surface="chalkboard" />Layout
Page shell with configurable sidebar, header, footer, and content area.
<Layout
title="Page Title"
subtitle="Optional subtitle"
showHeader={true}
showSidebar={true}
showFooter={false}
showPage={true}
background="paper" // 'paper' | 'parchment' | 'kraft' | 'marble' | 'speckle' | 'canvas'
navigationItems={[...]}
headerActions={<><Button>Action</Button></>}
navigationIsland={<NavigationIsland items={[...]} />}
>
{children}
</Layout>Page
Content wrapper with paper texture background and optional watercolor accent.
<Page withAccent accentColor="green">
{children}
</Page>The texture prop is shared across textured components (Page, Card, Alert, Modal, Select, Table). It accepts a name, a config, or a boolean to toggle the default:
<Card texture="kraft" /> {/* named texture */}
<Card texture={{ texture: 'paper', ruledType: 'lines' }} /> {/* full config */}
<Page texture={false} /> {/* disable the default */}Button
Pressed paper button with ink stamp effect and watercolor wash on hover.
<Button variant="primary" size="medium" icon={<PlusIcon />}>
Click Me
</Button>Variants: primary | secondary | ghost | danger
Sizes: small | medium | large
Checkbox
Hand-drawn square with animated SVG ink checkmark.
<Checkbox label="Enable feature" labelPosition="right" />IconButton
Circular canvas patch button with watercolor glow ring on hover.
<IconButton icon={<SearchIcon />} variant="default" size="medium" label="Search" />NavigationIsland
Floating pill-style navigation bar with paper texture background.
<NavigationIsland
items={[
{ id: 'dash', label: 'Dashboard', icon: <HomeIcon /> },
{ id: 'plans', label: 'Plans', icon: <FolderIcon /> },
]}
activeId={activeId}
onSelect={setActiveId}
/>Design Tokens
Colors
| Token | Usage |
|---|---|
| paper | Backgrounds, surfaces (warm off-white scale) |
| ink | Text, borders, shadows (deep charcoal scale) |
| canvas | Buttons, patches, sidebar (cream weave scale) |
| watercolor | Accents, hover states, focus rings (blue, green, amber, rose, slate) |
Typography
| Role | Font | Usage |
|---|---|---|
| Display | Luminari | Titles, buttons, navigation, logo |
| Body | Cormorant Garamond | Paragraphs, descriptions, labels |
| Handwritten | Caveat | Tags, annotations, special labels |
| Mono | JetBrains Mono | Code, data, timestamps |
Textures
Available as Tailwind utilities:
bg-paper-texture— Subtle grain noisebg-speckle-texture— Coarse speckled noisebg-parchment-texture— Warm aged paperbg-canvas-weave— Desaturated woven grainbg-kraft-texture— Brown craft paperbg-marble-texture— Cool stone grain
Development
# Install dependencies
pnpm install
# Start showcase dev server
pnpm run dev
# Build library
pnpm run build
# Type check
pnpm run check-types
# Lint and format (Biome)
pnpm run lint
pnpm run lint:fixLicense
MIT