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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.