code-block
cult-ui/code-blockFreeComponent
A beautiful code block component with tabs, copy functionality, and smooth animations
Install it
npx shadcn@latest add https://raw.githubusercontent.com/nolly-studio/cult-ui/HEAD/apps/www/public/r/styles/default/code-block.jsonSource
1"use client"23import { useCallback, useLayoutEffect, useMemo, useRef, useState } from "react"4import { Check, Copy } from "lucide-react"5import { AnimatePresence, motion } from "motion/react"67import { cn } from "@/lib/utils"89interface CodeTab {10 label: string11 code: string12 language?: string13}1415interface CodeBlockProps {16 tabs?: CodeTab[]17 code?: string18 language?: string19 className?: string20}2122export function CodeBlock({23 tabs,24 code,25 language = "bash",26 className,27}: CodeBlockProps) {28 const [activeTab, setActiveTab] = useState(0)29 const [copied, setCopied] = useState(false)30 const [direction, setDirection] = useState(0)31 const preRef = useRef<HTMLPreElement>(null)32 const tabsContainerRef = useRef<HTMLDivElement>(null)33 const tabRefs = useRef<(HTMLButtonElement | null)[]>([])34 const [hasOverflow, setHasOverflow] = useState(false)35 const [indicator, setIndicator] = useState<{36 left: number37 width: number38 } | null>(null)3940 const measureIndicator = useCallback(() => {41 const container = tabsContainerRef.current42 const activeEl = tabRefs.current[activeTab]4344 if (!container || !activeEl) {45 return46 }4748 const containerRect = container.getBoundingClientRect()49 const tabRect = activeEl.getBoundingClientRect()5051 setIndicator({52 left: tabRect.left - containerRect.left,53 width: tabRect.width,54 })55 }, [activeTab])5657 const codeContent = useMemo(() => {58 if (tabs && tabs.length > 0) {59 return tabs60 }61 if (code) {62 return [{ label: language, code, language }]63 }64 return []65 }, [tabs, code, language])6667 const currentCode = codeContent[activeTab]?.code || ""6869 // Check overflow when tab changes or content updates70 // biome-ignore lint/correctness/useExhaustiveDependencies: activeTab is needed to recheck overflow when content changes71 useLayoutEffect(() => {72 const checkOverflow = () => {73 if (preRef.current) {74 const hasHorizontalOverflow =75 preRef.current.scrollWidth > preRef.current.clientWidth76 setHasOverflow(hasHorizontalOverflow)77 }78 }7980 checkOverflow()81 const resizeObserver = new ResizeObserver(checkOverflow)82 if (preRef.current) {83 resizeObserver.observe(preRef.current)84 }8586 return () => {87 resizeObserver.disconnect()88 }89 }, [activeTab])9091 useLayoutEffect(() => {92 measureIndicator()9394 const resizeObserver = new ResizeObserver(measureIndicator)95 const container = tabsContainerRef.current96// … truncated
What it pulls in
npm packages
Files it writes
More from cult/ui
All 157 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| ai-instructionsai-instructions | cult/ui | Components | Free | 2 deps | |
| ai-instructions-demoai-instructions-demo | cult/ui | Components | Free | no deps | |
| animated-numberanimated-number | cult/ui | Components | Free | 1 dep | |
| animated-number-demoanimated-number-demo | cult/ui | Components | Free | no deps | |
| bg-animate-buttonbg-animate-button | cult/ui | Components | Free | no deps | |
| bg-animate-button-demobg-animate-button-demo | cult/ui | Components | Free | no deps | |
| bg-animated-fractal-dot-gridbg-animated-fractal-dot-grid | cult/ui | Components | Free | 1 dep | |
| bg-animated-fractal-dot-grid-demobg-animated-fractal-dot-grid-demo | cult/ui | Components | Free | no deps |
