Code Block
beui/code-blockFreeComponent
A syntax-highlighted code surface with stable streaming updates, line numbers, focused lines, smooth following, and copy feedback.
Install it
npx shadcn@latest add https://beui.dev/r/code-block.jsonSource
1"use client";2// beui.dev/components/agents/code-block34import { Check, Copy, FileCode2, LoaderCircle } from "lucide-react";5import { motion, useReducedMotion } from "motion/react";6import {7 type ReactNode,8 useCallback,9 useEffect,10 useLayoutEffect,11 useMemo,12 useRef,13 useState,14} from "react";15import {16 type AgentCodeLanguage,17 AgentCodeLine,18 useAgentCodeTokens,19} from "@/components/agents/agent-code";20import { SPRING_PRESS } from "@/lib/ease";21import { cn } from "@/lib/utils";2223export type CodeBlockStatus = "streaming" | "complete";2425export interface CodeBlockProps {26 code: string;27 language?: AgentCodeLanguage;28 filename?: ReactNode;29 status?: CodeBlockStatus;30 showLineNumbers?: boolean;31 highlightLines?: number[];32 maxHeight?: number;33 wrap?: boolean;34 copyable?: boolean;35 onCopy?: () => void | Promise<void>;36 className?: string;37}3839export function CodeBlock({40 code,41 language = "typescript",42 filename,43 status = "complete",44 showLineNumbers = true,45 highlightLines = [],46 maxHeight = 280,47 wrap = false,48 copyable = true,49 onCopy,50 className,51}: CodeBlockProps) {52 const reduce = useReducedMotion() ?? false;53 const viewportRef = useRef<HTMLDivElement>(null);54 const copyTimer = useRef<number | undefined>(undefined);55 const [copied, setCopied] = useState(false);56 const streaming = status === "streaming";57 const tokens = useAgentCodeTokens(code, language);58 const highlighted = useMemo(59 () => new Set(highlightLines),60 [highlightLines],61 );62 let offset = 0;63 const lines = code.split("\n").map((content) => {64 const line = { content, offset };65 offset += content.length + 1;66 return line;67 });6869 useEffect(70 () => () => {71 if (copyTimer.current) window.clearTimeout(copyTimer.current);72 },73 [],74 );7576 useLayoutEffect(() => {77 const viewport = viewportRef.current;78 if (!viewport || !streaming) return;7980 const frame = requestAnimationFrame(() => {81 if (viewport.scrollHeight <= viewport.clientHeight) return;82 if (typeof viewport.scrollTo === "function") {83 viewport.scrollTo({84 top: viewport.scrollHeight,85 behavior: reduce ? "auto" : "smooth",86 });87 } else {88 viewport.scrollTop = viewport.scrollHeight;89 }90 });91 return () => cancelAnimationFrame(frame);92 });9394 const handleCopy = useCallback(async () => {95 if (onCopy) await onCopy();96 else await navigator.clipboard?.writeText(code);9798 setCopied(true);99// … truncated
What it pulls in
npm packages
Files it writes
More from beui
All 104 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Action Swap Bluraction-swap-blur | beui | Components | Free | 3 deps · 4 files | |
| Action Swap Cascadeaction-swap-cascade | beui | Components | Free | 3 deps · 4 files | |
| Action Swap Rollaction-swap-roll | beui | Components | Free | 3 deps · 4 files | |
| Agent Activityagent-activity | beui | Components | Free | 4 deps · 9 files | |
| Agent Loading States Agent Progressagent-progress | beui | Components | Free | 3 deps · 3 files | |
| AI Sidebarai-sidebar | beui | Components | Free | 4 deps · 5 files | |
| Animated Badgeanimated-badge | beui | Components | Free | 4 deps · 3 files | |
| Number Animation Animated Numberanimated-number | beui | Components | Free | 3 deps · 3 files |
