Installation
Add bydefaulthuman to your project in one command.
bydefaulthuman uses the shadcn CLI for distribution. Each component is a registry JSON file that resolves into copyable source in your project — no package to pin, no version drift.
Prerequisites
- React 18+
- Next.js 13+ App Router or any React setup with path aliases configured
- Tailwind CSS
- shadcn CLI initialised with
npx shadcn init
Install any component
npx shadcn add https://bydefaulthuman.fun/r/button.jsonThis copies button.tsx into your project and automatically installs roughjs plus shared files — use-rough.ts and rough.ts — through registryDependencies. Shared files are deduplicated automatically, so running the command for a second component won't overwrite them.
What lands in your project
rough.ts exports configureCrumble, all three theme option objects, and the CrumbleContext used internally. use-rough.ts exports useRough, the single hook every component calls to draw its SVG border.
Global theme
All components default to pencil. To change the default globally, call configureCrumble once — anywhere in your app before the first render, for example in a layout or providers file:
import { configureCrumble } from "@/lib/rough";
configureCrumble({ theme: "ink" });Available themes are "pencil", "ink", and "crayon". See Introduction for what each one looks like.
React Context alternative
If you prefer context over a module-level singleton — useful when different sections of your UI need different themes — wrap a subtree with CrumbleContext.Provider:
import { CrumbleContext } from "@/lib/rough";
export function SketchySection({ children }: { children: React.ReactNode }) {
return (
<CrumbleContext.Provider
value={{ theme: "crayon", animateOnMount: true, animateOnHover: true }}
>
{children}
</CrumbleContext.Provider>
);
}Per-component override
The theme prop on any component always wins over both the global config and any ancestor context:
<Button theme="crayon">This one is crayon</Button>
<Button>This one uses the global config</Button>Disable animation behaviour
configureCrumble({
animateOnMount: false, // skip the redraw on first render
animateOnHover: false, // borders stay static; no reseed on mouseenter
});Both flags can also be passed on the CrumbleContext.Provider value if you only want to disable animation in a specific section.
Custom colours
Every component accepts stroke, strokeMuted, and fill props. These map to --cr-stroke, --cr-stroke-muted, and --cr-fill:
<Button stroke="#e85d4a">Red border button</Button>
<Card stroke="oklch(0.55 0.18 260)" fill="oklch(0.97 0.02 260 / 40%)">
Blue tinted card
</Card>You can also set the CSS variables on a parent element to theme an entire section without repeating props on every component.
Updating a component
Components live in your project, so updates are opt-in. Re-run the add command to pull the latest version:
npx shadcn add https://bydefaulthuman.fun/r/button.json