Skip to main content

Overview

The CodeGroup plugin allows you to create tabbed code blocks, perfect for showing the same code in different languages or displaying multiple related files. Each tab can have its own language and syntax highlighting.

Installation

npm install @yoopta/code

Basic Usage

import { CodeGroup } from '@yoopta/code';

const plugins = [
  CodeGroup,
  // ... other plugins
];

<YooptaEditor editor={editor} plugins={plugins} />;

Features

  • Multiple Tabs: Display code in multiple tabs
  • Syntax Highlighting: Powered by Shiki
  • Per-Tab Languages: Each tab can have different language
  • Active Tab State: Track which tab is active
  • Theme Support: Consistent theming across tabs

Structure

The CodeGroup plugin consists of nested elements:
code-group-container (props: activeTabId, theme)
├── code-group-list
│   └── code-group-item-heading (multiple tabs)
└── code-group-content (props: referenceId, language)

Configuration

import { CodeGroup } from '@yoopta/code';

const plugins = [
  CodeGroup.extend({
    options: {
      theme: 'dracula',
    },
  }),
];

Options

theme
string
default:"github-dark"
Shiki theme for all code blocks in the group
display
object

Element Props

code-group-container

activeTabId
string | null
ID of the currently active tab
theme
string
default:"github-dark"
Theme for all code blocks

code-group-content

referenceId
string | null
ID linking content to its tab heading
language
string
default:"typescript"
Programming language for this code block

Commands

addTabItem

Add a new tab to the code group.
import { CodeGroupCommands } from '@yoopta/code';

CodeGroupCommands.addTabItem(editor, blockId, { at: selection });

Keyboard Behavior

  • Enter on Tab Heading: Creates a new tab
  • Enter in Code Content: Inserts newline (not a new block)
  • Backspace: Prevents deletion at content start
  • Cmd/Ctrl+A: Selects entire code content

Initial Structure

When created, the plugin initializes with:
{
  'code-group-container': {
    activeTabId: 'generated-id',
    theme: 'github-dark',
  },
  tabs: [
    {
      heading: 'hello-world.ts',
      content: 'console.log("Hello World");',
      language: 'typescript',
    },
  ],
}

Custom Rendering

import { CodeGroup } from '@yoopta/code';

const CustomCodeGroup = CodeGroup.extend({
  elements: {
    'code-group-container': {
      render: (props) => {
        const { activeTabId, theme } = props.element.props;

        return (
          <div className="my-code-group" data-theme={theme}>
            {props.children}
          </div>
        );
      },
    },
    'code-group-list': {
      render: (props) => (
        <div className="tabs-header" {...props.attributes}>
          {props.children}
        </div>
      ),
    },
    'code-group-item-heading': {
      render: (props) => {
        const isActive = props.element.id === getActiveTabId();

        return (
          <button className={`tab ${isActive ? 'active' : ''}`} {...props.attributes}>
            {props.children}
          </button>
        );
      },
    },
    'code-group-content': {
      render: (props) => {
        const { language } = props.element.props;

        return (
          <pre data-language={language} {...props.attributes}>
            {props.children}
          </pre>
        );
      },
    },
  },
});

Use Cases

Multi-Language Examples

Show same code in JavaScript, Python, Go, etc.

Related Files

Display multiple files that work together

Before/After

Show code before and after refactoring

API Responses

Different response formats (JSON, XML, etc.)

Best Practices

Use descriptive names for tabs (e.g., “package.json”, “server.ts”)
Group related code in logical language combinations
Keep number of tabs reasonable (2-5) for better UX
Ensure code in different tabs is related or equivalent