Contributing
Edit on GitHubOpen an issue or a pull request on GitHub to add a block or report a bug.
PrequelUI is open source and built in the open. Issues, pull requests and new blocks are welcome on GitHub.
Reporting a bug
Open an issue and tell us what you were doing, what you expected and what happened. A small reproduction — even a link to a sandbox — helps the most.
Adding a block
A block is one file, one component, one idea. Build it like this:
Write the component
Create
registry/prequel/<name>/<name>.tsxwith"use client"at the top. Export the component as a named export in PascalCase and asexport default."use client"; import { motion, useInView, useReducedMotion } from "motion/react"; import { cn } from "@/lib/utils"; export type MyBlockProps = { className?: string; // optional props with sensible demo defaults }; export function MyBlock({ className }: MyBlockProps) { return ( <div className={cn("rounded-xl border border-border bg-card p-6", className)}> {/* draw your chart in SVG, animate transform / opacity / pathLength */} </div> ); } export default MyBlock;"use client"; import { motion, useInView, useReducedMotion } from "motion/react"; import { cn } from "@/lib/utils"; export type MyBlockProps = { className?: string; // optional props with sensible demo defaults }; export function MyBlock({ className }: MyBlockProps) { return ( <div className={cn("rounded-xl border border-border bg-card p-6", className)}> {/* draw your chart in SVG, animate transform / opacity / pathLength */} </div> ); } export default MyBlock;Follow the code rules
Every block follows the same conventions:
- Imports only
react,motion/react,lucide-reactand@/lib/utils. No charting libraries — draw charts in SVG. - Props are typed and exported, every one optional, with deterministic demo data.
- No
Math.random()orDate.now()during render — hydration must match. Timers live insideuseEffectand are cleaned up. - Charts use a
viewBoxand scale to the container width. - Accessible: charts get
role="img"and anaria-label; controls are real buttons with a focus ring.
- Imports only
Register the block
Add an import and an entry in
registry/index.ts, then a matching item inregistry.jsonwithtype: "registry:block"and the dependencies the block actually uses.Open a pull request
Keep it small, describe what the block does, and reference any issue it closes.
Code style
- Clean, strict TypeScript — no
any, no unused variables. - Motion is calm: entrance once, soft ease-out, small staggers, no bounce.
- Honour
useReducedMotion()everywhere. - Use only shadcn tokens — no hard-coded colours — so blocks work in light and dark mode.