npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

paperplane-react

v0.1.1

Published

A React UI component library with a paper/tactile feel — no Tailwind required

Readme

paperplane-react

A React UI component library with a paper and ink aesthetic — tactile, warm, and classic. Built with zero Tailwind dependency, works in any React environment.

npm version


✦ Why paperplane-react?

  • No Tailwind required — styles are self-contained via CSS custom properties injected at runtime. No PostCSS config, no content glob, no purge issues.
  • Works everywhere — React 17+, Next.js (Pages & App Router), Remix, Vite, Create React App, etc.
  • SSR-safe — includes <PaperStyleTag /> for Server Components and PaperProvider for client-side injection.
  • Fully typed — TypeScript-first with complete prop types.
  • Tiny bundle — zero runtime dependencies besides React itself.

Installation

npm install paperplane-react
# or
yarn add paperplane-react
# or
pnpm add paperplane-react

That's it. No Tailwind config, no CSS imports, no PostCSS plugins.


Setup

React / Vite / CRA

Wrap your app with PaperProvider once:

// main.tsx or App.tsx
import { PaperProvider } from 'paperplane-react';

export default function App() {
  return (
    <PaperProvider>
      <YourApp />
    </PaperProvider>
  );
}

Next.js App Router (v13+)

Use PaperStyleTag in your root layout (Server Component) and PaperProvider for client-side interactivity:

// app/layout.tsx
import { PaperStyleTag, PaperProvider } from 'paperplane-react';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <PaperStyleTag />
      </head>
      <body>
        <PaperProvider>
          {children}
        </PaperProvider>
      </body>
    </html>
  );
}

Next.js Pages Router

// pages/_app.tsx
import { PaperProvider } from 'paperplane-react';
import type { AppProps } from 'next/app';

export default function MyApp({ Component, pageProps }: AppProps) {
  return (
    <PaperProvider>
      <Component {...pageProps} />
    </PaperProvider>
  );
}

Using Custom Fonts

PaperUI includes the Dareo custom font (available in both OTF and TTF formats). Use it to add a distinctive, handcrafted feel to your app.

Option 1: Direct CSS Import (Recommended)

// In your main app file or root layout
import 'paperplane-react/dist/fonts/fonts.css';

// Now use the font in any component
<Heading style={{ fontFamily: 'Dareo, serif' }}>Custom Heading</Heading>

// Or use the CSS variable
<Text style={{ fontFamily: 'var(--paper-font-dareo)' }}>Beautiful text</Text>

Option 2: Via PaperProvider

Pass the loadFonts prop to automatically inject font declarations:

<PaperProvider loadFonts={true}>
  <YourApp />
</PaperProvider>

// Then use in any component
<Heading>This uses Dareo if you set fontFamily</Heading>

Or set a custom font globally:

<PaperProvider fontFamily="Dareo, serif" loadFonts={true}>
  <YourApp />
</PaperProvider>

Option 3: Manual Function Call

import { injectPaperFonts } from 'paperplane-react';

// In useEffect or component
useEffect(() => {
  injectPaperFonts();
}, []);

Components

<Paper>

The base surface. Like a sheet of paper on a desk.

import { Paper } from 'paperplane-react';

<Paper elevation="md" padding="lg">
  Content on paper
</Paper>

<Paper elevation="lg" aged>
  An aged, yellowed sheet
</Paper>

<Paper elevation="sm" torn>
  With a torn bottom edge
</Paper>

Props:

| Prop | Type | Default | Description | |------|------|---------|-------------| | elevation | "flat" \| "sm" \| "md" \| "lg" | "sm" | Shadow depth | | padding | "none" \| "sm" \| "md" \| "lg" | "md" | Inner padding | | aged | boolean | false | Cream/yellowed background | | torn | boolean | false | Torn bottom edge effect | | as | React.ElementType | "div" | Render as any HTML element |


<Button>

Tactile buttons that feel like they're pressed into paper.

import { Button } from 'paperplane-react';

<Button>Default</Button>
<Button variant="solid" color="primary">Save Document</Button>
<Button variant="outline" color="danger">Delete</Button>
<Button variant="ghost">Cancel</Button>
<Button variant="ink" color="primary">Ink Stamp Style</Button>
<Button loading>Saving...</Button>
<Button size="lg" leftIcon={<PencilIcon />}>Write</Button>

Props:

| Prop | Type | Default | |------|------|---------| | variant | "solid" \| "outline" \| "ghost" \| "ink" | "solid" | | size | "sm" \| "md" \| "lg" | "md" | | color | "default" \| "primary" \| "danger" \| "warning" | "default" | | loading | boolean | false | | fullWidth | boolean | false | | leftIcon | ReactNode | — | | rightIcon | ReactNode | — |


<Card> / <CardHeader> / <CardBody> / <CardFooter>

Structured paper cards with optional accent lines.

import { Card, CardHeader, CardBody, CardFooter, Button } from 'paperplane-react';

<Card elevation="md" accent="primary" hoverable>
  <CardHeader>
    <h3>Letter of Intent</h3>
  </CardHeader>
  <CardBody>
    Content of the card...
  </CardBody>
  <CardFooter>
    <Button size="sm">Sign</Button>
    <Button size="sm" variant="ghost">Decline</Button>
  </CardFooter>
</Card>

Card Props:

| Prop | Type | Default | |------|------|---------| | elevation | "flat" \| "sm" \| "md" \| "lg" | "sm" | | accent | "none" \| "primary" \| "danger" \| "warning" \| "info" \| "brown" | "none" | | aged | boolean | false | | hoverable | boolean | false |


<Input>

import { Input } from 'paperplane-react';

<Input label="Full Name" placeholder="John Doe" fullWidth />
<Input label="Email" type="email" error="Invalid email address" />
<Input label="Amount" leftAddon="$" rightAddon="USD" />
<Input underline placeholder="Underline style..." />

<Textarea>

import { Textarea } from 'paperplane-react';

<Textarea label="Your Letter" rows={6} fullWidth showCount maxLength={500} />
<Textarea lined placeholder="Lined paper style..." rows={5} />

<Select>

import { Select } from 'paperplane-react';

<Select label="Category" fullWidth>
  <option value="">Choose one…</option>
  <option value="a">Option A</option>
  <option value="b">Option B</option>
</Select>

<Badge>

import { Badge } from 'paperplane-react';

<Badge>Draft</Badge>
<Badge color="primary">Published</Badge>
<Badge variant="stamp" color="danger">Rejected</Badge>
<Badge variant="outline" color="warning">Pending</Badge>

<Alert>

import { Alert } from 'paperplane-react';

<Alert title="Note" color="info" dismissible>
  Your document has been saved automatically.
</Alert>

<Alert color="danger" title="Error" icon={<WarningIcon />}>
  Something went wrong. Please try again.
</Alert>

<Checkbox>

import { Checkbox } from 'paperplane-react';

<Checkbox label="I agree to the terms" />
<Checkbox label="Remember me" defaultChecked />
<Checkbox indeterminate label="Select all" />

<Spinner>

import { Spinner } from 'paperplane-react';

<Spinner />
<Spinner size="lg" color="primary" />

Typography: <Heading>, <Text>, <Divider>

import { Heading, Text, Divider } from 'paperplane-react';

<Heading as="h1" size="3xl">The Grand Chronicle</Heading>
<Heading as="h2" size="xl">Chapter One</Heading>

<Text>Body text in a warm serif typeface.</Text>
<Text size="sm" muted>A quiet footnote.</Text>
<Text italic>An italicized phrase.</Text>
<Text mono>monospace_text()</Text>

<Divider />
<Divider label="or" />
<Divider ornament />  {/* renders ✦ */}

Theming & Customization

PaperUI exposes all design decisions as CSS custom properties. Override any of them in your own CSS:

:root {
  /* Change primary color from forest green to navy */
  --paper-primary: #1a3a5c;
  --paper-primary-light: #2a5a8c;
  --paper-primary-dark: #0f2240;
  --paper-primary-bg: #f0f4f8;

  /* Use a different serif font */
  --paper-font-serif: 'Lora', Georgia, serif;

  /* Adjust paper base color */
  --paper-white: #fffdf8;
  --paper-cream: #f8f3e8;
}

Or via PaperProvider:

<PaperProvider fontFamily="'Lora', Georgia, serif">
  <App />
</PaperProvider>

Full list of CSS variables

See PAPER_CSS_VARS export for the complete token list, or inspect data-paperui="tokens" style tag in DevTools.


No-Tailwind Guarantee

PaperUI uses only:

  • CSS custom properties (:root { --paper-... }) injected once into <head>
  • Inline styles on components via React's style prop
  • A minimal <style> tag per component for keyframe animations

There is no dependency on Tailwind CSS, PostCSS, or any CSS framework. It will never conflict with or require Tailwind configuration. If you're using Tailwind in your project, PaperUI sits alongside it without any issues.


Browser Support

All modern browsers. CSS custom properties are supported in Chrome 49+, Firefox 31+, Safari 9.1+, Edge 15+.


License

MIT