Installation
Every component assumes a Next.js app with Tailwind, shadcn/ui and Framer Motion. Set that up once, then copy any component in.
- 1
Create a Next.js app
npx create-next-app@latest my-app --typescript --tailwind --app - 2
Add shadcn/ui
npx shadcn@latest init - 3
Add Framer Motion
npm install motionFramer Motion is published as motion now. Import it from motion/react.
- 4
Add the shared helpers
The pieces every component builds on: the class merger, the shared springs, the button, the scroll helpers. Save them at these paths once.
src/components/ui/button.tsx
import * as React from "react"; import { Slot } from "@radix-ui/react-slot"; import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "@/lib/utils"; // Deliver's button (deliverwebsite.com .btn): hover sweeps a light across the face, // press pushes it 2px down onto its edge. const DELIVER_BUTTON = "group relative isolate gap-1.5 overflow-hidden rounded-lg font-semibold transition-all duration-200 active:translate-y-0.5 active:duration-75 before:absolute before:inset-0 before:-z-10 before:-translate-x-full before:bg-linear-105 before:from-transparent before:from-35% before:to-transparent before:to-65% before:transition-transform before:duration-1400 hover:before:translate-x-full"; // shadcn/ui button, plus Deliver's brand and line buttons and the "ink" pill the navbar demos use. const buttonVariants = cva( "inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-full text-sm font-medium transition-colors outline-none focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0", { variants: { variant: { default: "bg-primary text-primary-foreground hover:bg-primary/90", brand: cn(DELIVER_BUTTON, "bg-key text-white shadow-brand before:via-white/25 hover:bg-key-hover active:shadow-brand-pressed"), line: cn(DELIVER_BUTTON, "bg-line-face text-foreground shadow-line before:via-foreground/15 hover:bg-line-face-hover active:shadow-line-pressed"), ink: "bg-ink text-white hover:bg-primary", inverse: "bg-white text-ink hover:bg-white/85", outline: "border bg-background hover:bg-muted", ghost: "hover:bg-muted", }, size: { default: "h-10 px-5", sm: "h-8 px-3.5 text-xs", lg: "h-12 px-6 text-base", icon: "size-10", }, }, defaultVariants: { variant: "default", size: "default" }, }, ); type ButtonProps = React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & { asChild?: boolean }; export function Button({ className, variant, size, asChild = false, ...props }: ButtonProps) { const Component = asChild ? Slot : "button"; return <Component data-slot="button" className={cn(buttonVariants({ variant, size, className }))} {...props} />; } export { buttonVariants }; - 5
Copy a component
Open any component, switch to Code, and copy each file to the same path in your project.