Ai Diff
smoothui-registry/ai-diffFreeComponent
Proposed code or data edit where added lines wipe in from the left and rejected lines collapse to nothing.
Install it
npx shadcn@latest add https://www.smoothui.dev/r/ai-diff.jsonSource
1"use client";23import { cn } from "@/lib/utils";4import { AnimatePresence, motion, useReducedMotion } from "motion/react";5import { useState } from "react";67const SPRING_DEFAULT = {8 bounce: 0.1,9 duration: 0.25,10 type: "spring" as const,11};12const EASE_OUT = [0.23, 1, 0.32, 1] as const;13const LINE_STAGGER = 0.02;14const WIPE_DURATION = 0.28;15const FLASH_DURATION = 0.35;16const SUCCESS_TINT = "oklch(72% 0.17 150 / 0.14)";17const DANGER_TINT = "oklch(63% 0.21 25 / 0.12)";1819export type AIDiffLineKind = "added" | "removed" | "context";2021export type AIDiffLine = {22 content: string;23 kind: AIDiffLineKind;24 /** Line number in the file. Omit for tabular data rather than code. */25 number?: number;26};2728export type AIDiffProps = {29 className?: string;30 lines: AIDiffLine[];31 onAccept?: () => void;32 onReject?: () => void;33 /** File path or a description of what is being changed. */34 title?: string;35};3637const PREFIX: Record<AIDiffLineKind, string> = {38 added: "+",39 context: " ",40 removed: "-",41};4243/**44 * A proposed edit awaiting a human yes or no.45 *46 * Added lines wipe in from the left with a clip path rather than fading: a wipe47 * has a direction, and direction is what tells you the change was *written*48 * rather than always having been there. Rejecting collapses the lines to zero49 * height so the space is reclaimed — a rejected edit should stop occupying the50 * page.51 */52const AIDiff = ({53 className,54 lines,55 onAccept,56 onReject,57 title,58}: AIDiffProps) => {59 const shouldReduceMotion = useReducedMotion();60 const [decision, setDecision] = useState<"accepted" | "rejected" | null>(61 null62 );6364 const accept = () => {65 setDecision("accepted");66 onAccept?.();67 };6869 const reject = () => {70 setDecision("rejected");71 onReject?.();72 };7374 const added = lines.filter((line) => line.kind === "added").length;75 const removed = lines.filter((line) => line.kind === "removed").length;7677 return (78 <motion.div79 // One flash on accept, then it settles. Anything more celebratory turns an80 // ordinary code review into an event.81 animate={82 decision && !shouldReduceMotion83 ? {84 backgroundColor: [85 decision === "accepted" ? SUCCESS_TINT : DANGER_TINT,86 "rgb(0 0 0 / 0)",87 ],88 }89 : undefined90 }91 className={cn(92 "w-full overflow-hidden rounded-xl border border-border bg-background",93 className94 )}95// … truncated
What it pulls in
npm packages
Files it writes
More from SmoothUI Registry
All 177 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Agent Avataragent-avatar | SmoothUI Registry | Components | Free | no deps | |
| Ai Approvalai-approval | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Artifactai-artifact | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Branchai-branch | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Citationai-citation | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Context Meterai-context-meter | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Conversationai-conversation | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Coreai-core | SmoothUI Registry | Components | Free | 1 dep |
