Code block

Code blocks use a monospace font on a muted background, with a line-number gutter. Highlighting is done by Shiki and follows your light or dark theme.

Installation

This pattern is built from files in @intentui/editor. Install the editor, then copy the code above into a component of your own.

npx shadcn@latest add @intentui/editor

What's included

PieceWhy it is here
RichTextExtensionLexical's rich text behavior. Every pattern needs it.
InitialStateExtensionApplies the seeded content immediately, so the server and the client render the same. Leave it out if your editor starts empty. See Seeding initial content.
CodeExtensionRegisters the code nodes, Shiki highlighting, Tab indentation and the light and dark theme sync.
ShortcutsExtensionProvides the Ctrl Alt C shortcut. Remove it and the block still works, but without that shortcut.
registerMarkdownShortcuts(editor, MULTILINE_ELEMENT_TRANSFORMERS)Turns three backticks into a code block. Without it only the button, slash menu and shortcut insert code blocks.
InsertCodeBlockPluginThe toolbar button.
CodePickerPluginThe "Insert code block" slash menu item.
ComponentPicker, BlockInsert, ToolbarContainers for the slash menu and the button.

Inserting a code block

MethodHow
ToolbarThe "Insert code block" button.
Slash menuType / and choose "Insert code block" (keywords: code, codeblock, javascript, python, js).
MarkdownType three backticks, optionally followed by a language such as js, then Space or Enter.
ShortcutCtrl Alt C (Cmd Option C on macOS).

With a collapsed cursor the current block becomes a code block. With selected text, the selection is replaced by a code block containing that text. Inserting inside an existing code block does nothing.

Behavior

  • Tab indents by 2 spaces.
  • Arrow keys let you leave the block when it is the first or last block in the document.
  • The theme is github-light or github-dark, chosen from whether <html> has the dark class. The extension watches the class and updates existing blocks when you switch themes.

For single words inside a sentence use inline code instead. See Text format.

Styling

theme.ts:

components/editor/theme.ts
code: "editor-code relative mb-3 block overflow-x-auto rounded-lg border border-border bg-muted ...",
codeHighlight: {
  inserted: "bg-success-subtle text-success-subtle-foreground",
  deleted: "bg-danger-subtle text-danger-subtle-foreground",
},

theme.css adds the .editor-code rules: the background is forced to var(--muted), and .editor-code::before draws the sticky line-number gutter from the data-gutter attribute. Edit that rule to restyle or hide the gutter.

To change the highlighter themes or tab size, edit LIGHT_CODE_THEME, DARK_CODE_THEME and tabSize in extensions/code-extension.tsx. Languages and tokenizing belong to Lexical, see lexical.dev.