react-e-ink
v0.0.1
Published
React component library that simulates a realistic e-ink display with WebGL shaders, content ghosting, stepped scrolling, and refresh cycles.
Downloads
148
Maintainers
Readme
react-e-ink
A React component library that simulates a realistic e-ink display. Wraps any React app with grayscale rendering, content ghosting, stepped scrolling, WebGL surface textures, and a full/partial refresh cycle.
Install
pnpm add react-e-inkPeer dependencies: react >= 19, react-dom >= 19, motion >= 12.
Quick start
import { EInkProvider, EInkDisplay } from "react-e-ink";
import "react-e-ink/styles.css";
function EInkShell({ children }: { children: React.ReactNode }) {
const pathname = usePathname(); // or useLocation(), etc.
return (
<EInkProvider pathname={pathname}>
<EInkDisplay pathname={pathname}>{children}</EInkDisplay>
</EInkProvider>
);
}The engine is framework-agnostic — pass pathname from whatever router you use (Next.js, React Router, TanStack Router, etc.).
The package ships TypeScript source (no build step). Configure your bundler to transpile it:
// next.config.ts
export default {
transpilePackages: ["react-e-ink"],
};Components
<EInkProvider>
Context provider that manages the refresh cycle and ghost state.
| Prop | Type | Description |
| ---------- | -------- | -------------------------------------- |
| pathname | string | Current route path from your router |
| children | node | App content |
<EInkDisplay>
The main visual wrapper. Renders the e-ink rendering pipeline around your content.
| Prop | Type | Description |
| --------------- | ------------ | -------------------------------------------------------------- |
| pathname | string | Must match the value passed to provider |
| children | node | Page content |
| renderOverlay | () => node | Optional. Render custom UI (status bar, decorations) inside the fixed overlay layer |
<EInkDisplay
pathname={pathname}
renderOverlay={() => (
<>
<MyStatusBar />
<MyDecorations />
</>
)}
>
{children}
</EInkDisplay>Hook: useEInk()
Access the engine state from any component inside the provider. Use this to build custom UI like status bars, refresh buttons, or debug overlays.
const {
refreshMode, // "idle" | "partial" | "full"
ghostIntensity, // 0–1, increases with partial refreshes
isInitialLoad, // true during the boot settle animation
refreshProgress, // 0–1, continuous progress toward next full refresh
forceRefresh, // () => void — trigger a full refresh immediately
addProgress, // (amount: number) => void — add to refresh progress
} = useEInk();Refresh cycle
- Partial refresh on each navigation — fast, but accumulates ghosting.
- Full refresh when progress reaches 1.0 — clears all ghosts and artifacts.
- Navigation adds ~14% progress per page change (~7 navigations per full refresh).
- Scrolling adds small increments of progress per step.
- Call
forceRefresh()to trigger a full refresh at any time.
Dark mode
Add the eink-dark class to <html> to invert all colors. The CSS variables flip automatically.
Customization
Fonts
:root {
--eink-font-body: "Literata", Georgia, serif;
--eink-font-mono: "JetBrains Mono", "Courier New", monospace;
}Colors
:root {
--eink-paper: #f2ecdb;
--eink-black: #1a1610;
--eink-dark: #332d24;
--eink-mid: #74694f;
--eink-light: #a89b7a;
--eink-ghost: #d1c9ae;
}Accessibility
- Animations respect
prefers-reduced-motion. - External links automatically get
target="_blank"andrel="noopener noreferrer".
License
MIT
