2

I'm building a static site with Astro and trying to create a custom code block component that allows users to switch between different programming languages.

Current Implementation

CodeBlock.jsx:

import React, { useState } from "react";
import "./CodeBlock.css";
import { Code } from 'astro:components';

const CodeBlock = ({ snippets = [] }) => {
  if (!snippets.length) return null;

  const [activeTab, setActiveTab] = useState(snippets[0].label);
  const [collapsed, setCollapsed] = useState(false);

  const activeSnippet = snippets.find((s) => s.label === activeTab) || snippets[0];

  return (
    <div className="code-block">
      <div className="code-block-header">
        <div className="tabs">
          {snippets.map((s) => (
            <button
              key={s.label}
              className={`tab ${activeTab === s.label ? "active" : ""}`}
              onClick={() => setActiveTab(s.label)}
            >
              {s.label}
            </button>
          ))}
        </div>
        <button
          className="collapse-btn"
          onClick={() => setCollapsed((prev) => !prev)}
        >
          {collapsed ? "Expand" : "Collapse"}
        </button>
      </div>

      {!collapsed && (
        <pre className="code-content">
          <code>{activeSnippet.code}</code>
        </pre>
      )}
    </div>
  );
};

export default CodeBlock;

Usage in MDX

import CodeBlock from "../../components/CodeBlock/CodeBlock.jsx"

<CodeBlock client:load
  snippets={[
    { label: "Python", code: "print('Hello World')" },
    { label: "Java", code: "System.out.println('Hello, world!');" },
    { label: "JavaScript", code: "console.log('Hello, world!');" }
  ]}
/>

I'm aware that Astro allows customization of how code blocks are rendered (via remark/rehype plugins or custom components), but my specific challenge is that my component needs to accept multiple code blocks simultaneously to enable the tab-switching functionality. This makes it difficult to leverage standard markdown code block syntax directly.

Is there a way to leverage markdown's native code block syntax (triple backticks) while still having the ability to switch between languages in the UI? For example, something like:

:::tabs
```python
   def hello():
       print("Hello World")
```
```javascript
   function hello() {
       console.log("Hello World");
   }
```
:::

What's the recommended approach in Astro for creating tabbed/switchable code blocks that work well with MDX content, especially when dealing with multiple code snippets that need to be passed together? Something like this:

Code snippet with python code

Code snippet with java code

Any guidance or best practices would be greatly appreciated! Thanks in advance.

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.