Code Block

A code block highlighted with Shiki that can type its code out, character by character.

"use client"

import { useTheme } from "next-themes"

import { CodeBlock } from "@/components/animate-ui/components/code-block"

const CODE = `'use client';

import * as React from 'react';

type MyComponentProps = {
  myProps: string;
} & React.ComponentProps<'div'>;

function MyComponent(props: MyComponentProps) {
  return (
    <div {...props}>
      <p>My Component</p>
    </div>
  );
}

export { MyComponent, type MyComponentProps };`

export default function CodeBlockDemo({
  delay = 0,
  duration = 10000,
  writing = true,
  cursor = true,
}: {
  delay?: number
  duration?: number
  writing?: boolean
  cursor?: boolean
}) {
  const { resolvedTheme } = useTheme()

  return (
    <CodeBlock
      key={`${delay}-${duration}-${writing}`}
      code={CODE}
      lang="tsx"
      theme={resolvedTheme === "dark" ? "dark" : "light"}
      writing={writing}
      delay={delay}
      duration={duration}
      cursor={cursor}
      className="w-[420px] max-w-full"
      scrollClassName="h-[372px] max-h-none"
    />
  )
}

Installation

npm install @animate-ui/react motion
pnpm add @animate-ui/react motion
yarn add @animate-ui/react motion
bun add @animate-ui/react motion

The code is highlighted with Shiki, a peer dependency of this primitive, loaded on demand:

npm install shiki
pnpm add shiki
yarn add shiki
bun add shiki

Usage

import { CodeBlock } from '@animate-ui/react/primitives/code-block';

export function Snippet() {
  return (
    <CodeBlock
      code="console.log('Hello, world!');"
      lang="javascript"
      writing
      duration={2000}
    />
  );
}

The block renders Shiki's <pre> inside a div. Style it through that div ([&_pre]:…, [&_.line]:…); data-writing and data-done let you show a cursor while it types.

Ready-made block

A styled block around the primitive, with a cursor while it types and a copy button, is a file you add to your project and own:

npx shadcn@latest add @animate-ui/components-code-block
pnpm dlx shadcn@latest add @animate-ui/components-code-block
yarn dlx shadcn@latest add @animate-ui/components-code-block
bun x shadcn@latest add @animate-ui/components-code-block
import { CodeBlock } from '@/components/animate-ui/components/code-block';

export function Snippet() {
  return (
    <CodeBlock
      code="console.log('Hello, world!');"
      lang="javascript"
      writing
      duration={2000}
    />
  );
}

It takes every prop of the primitive, plus:

PropTypeDefault
cursor?
booleantrue
copyButton?
booleantrue
scrollClassName?
string-

Animation

  • With writing, the code appears one character at a time, evenly over duration (after delay), and the block and scrollContainerRef (its parent element by default) scroll smoothly to follow the last line.
  • With inView, writing starts when the block scrolls into view.
  • Under reduced motion, the whole code is shown at once (onDone is still called).

API Reference

CodeBlock

PropTypeDefault
code
string-
lang
string-
theme?
"light" | "dark""light"
themes?
{ light: string; dark: string }{ light: "github-light", dark: "github-dark" }
writing?
booleanfalse
duration?
number5000
delay?
number0
onDone?
() => void-
onWrite?
(info: { index: number; length: number; done: boolean }) => void-
scrollContainerRef?
React.RefObject<HTMLElement | null>-
inView?
booleanfalse
inViewMargin?
string"0px"
inViewOnce?
booleantrue
...props?
React.ComponentProps<'div'>-

Built by Skyleen. The source code is available on GitHub.

Last updated: 10/18/2026

On this page