webdevpuneet.com

Multi-Tab Code Block with Syntax Highlighting — UI Snippet

Multi-Tab Code Block · Layouts · Plain HTML, CSS & JS · Live preview

CategoryLayouts

Copy & paste

Source Code

<div class="wrap">
  <div class="code-card">
    <div class="topbar">
      <div class="dots"><span></span><span></span><span></span></div>
      <div class="tabs" id="tabs">
        <button class="tab active" data-idx="0" onclick="switchTab(0)">index.js</button>
        <button class="tab" data-idx="1" onclick="switchTab(1)">styles.css</button>
        <button class="tab" data-idx="2" onclick="switchTab(2)">config.json</button>
      </div>
      <button class="copy-btn" id="copyBtn" onclick="copyCode()">Copy</button>
    </div>
    <div class="code-wrap">
      <div class="line-nums" id="lineNums"></div>
      <pre class="code" id="code"><code id="codeEl"></code></pre>
    </div>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Multi-file tabbed navigation with active underline indicator
Token-based syntax highlighting (kw, fn, str, num, prop, cm, pun)
Line number column with user-select: none
macOS traffic-light dots for the IDE aesthetic
Horizontal scroll for long lines with hidden scrollbar
Copy button reconstructing plain text from the token array
Iframe-safe copy with execCommand fallback
Dark theme designed for developer documentation

About this UI Snippet

Multi-Tab Code Block — File Tabs, Syntax Tokens, Line Numbers & Copy

Screenshot of the Multi-Tab Code Block snippet rendered live

A multi-tab code block is among the most-copied UI patterns in developer documentation, tutorials, and component libraries. Showing multiple related files side by side in a single card (JavaScript, CSS, config) gives readers the full context of a code example without cluttering the page — for a single-file version, see the code block. This snippet provides a complete, dark-themed code viewer with macOS-style traffic-light dots, file-name tabs, token-based syntax highlighting, line numbers, and a copy button — no external libraries required.

Token-based syntax highlighting

Rather than running a regex over the raw source string (which is fragile and order-dependent), each file's content is stored as an array of token objects: { t: 'kw', v: 'const' } for a keyword, { t: 'str', v: '"hello"' } for a string, and so on. The renderer maps over these tokens, wrapping each in a span with the appropriate CSS class. Token types include kw (keyword), fn (function), str (string), num (number), prop (property/selector), cm (comment), and pun (punctuation/operator). This approach is robust, predictable, and trivially extensible with new token types.

Line numbers

The line number column is rendered from the token array length and displayed in a separate container floated left of the code block. User-select: none prevents line numbers from being selected on code copy. The two elements share a horizontal scroll container so the numbers and code always scroll together.

File tabs and active state

switchTab() updates the active tab indicator, clears the copy button label, and calls render() with the new index. The tabs container uses overflow-x: auto with hidden scrollbar so long file lists are scrollable on mobile without overflowing the card.

Copy button

copyCode() reconstructs the plain-text content from the token array by joining all v values, then uses the Clipboard API with an execCommand fallback. The button briefly shows "Copied!" so the user knows the action succeeded.

The macOS aesthetic

The three traffic-light dots in the top-left corner are a widely recognised signal for "this is a code editor or terminal window." They set the visual register immediately, making the code block feel like a real IDE window rather than a styled textarea, which increases perceived code quality and authority in documentation contexts.

Step by step

How to Use

  1. 1
    Switch filesClick any tab to view a different file. The code, line numbers, and syntax highlighting all update instantly.
  2. 2
    Copy the codeClick Copy to copy the plain-text source of the active file to your clipboard. The button briefly confirms with "Copied!".
  3. 3
    Add your own filesAppend an object to the files array with name, lang, and content (an array of token arrays). Tokenise your code into kw, fn, str, num, prop, cm, and pun spans.
  4. 4
    Swap the contentReplace the sample files array with your own code snippets. Each row in content is one line, expressed as an array of token objects.
  5. 5
    Style your themeChange the colour variables in the CSS to match your documentation site's colour palette. The dark default matches most developer docs.
  6. 6
    Export for your frameworkClick "React" for a component accepting a files prop with tab state in useState. Click "Vue" for a Vue 3 SFC with reactive activeIdx.

Real-world uses

Common Use Cases

Component library and API documentation
Show the HTML, CSS, and JavaScript (or TSX, types, and test files) of every documented component in a single, tabbed code card. Users see the complete implementation without navigating away, and the copy button lets them grab any file with one click. The macOS chrome adds authority to your documentation site.
Tutorial and course code examples
Technical tutorials frequently need to show starter code, the completed version, and a config file simultaneously. The multi-tab block puts all three in one card, keeping the tutorial page clean while giving learners access to every file. Tab labels can be "Before" and "After" for refactoring examples.
Marketing and landing page code showcase
SaaS products that sell to developers use live, syntax-highlighted code samples in hero sections and feature breakdowns to demonstrate SDK simplicity. A multi-tab block showing initialise + configure + use in three files communicates the integration flow at a glance.
Code review or diff viewer UI
Extend the tab model to show original and modified versions of a file side by side, or add a diff indicator to lines that changed. The token model makes it easy to add a "changed" background highlight to specific lines by adding a class to that line's container.
AI coding assistant output display
AI code assistants often return multiple files (component, styles, test). Render the response in a tabbed code block so users can see all generated files in one place, switch between them, and copy each individually. This is the standard display used by tools like Claude Artifacts and ChatGPT code blocks.
Embedded in a no-code or CMS platform
Add the code block component to a rich-text or Markdown editor so content authors can insert styled, tabbed code examples without writing HTML. The tabs, syntax highlighting, and copy button work automatically once the author provides the file name and content.
Related: Gift Wrap Option Card
See the Gift Wrap Option Card for a related cards pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Regex-based highlighters apply patterns to a raw string in sequence, and the order matters — a string literal pattern can accidentally match inside a comment, and overlapping matches corrupt the output. Storing the code as a pre-tokenised array where each token has an explicit type gives deterministic output: the renderer just wraps each token in its class. Adding a new language is adding a new tokenisation function, not fighting regex order-of-operations.

copyCode() reconstructs the plain text by mapping over the token array and joining the v (value) fields of every token. This produces the exact source code without any span tags, so the clipboard gets clean, pasteable code. If your token model is different, join the text content of all spans in the code element using textContent instead.

Add a new entry to the files array with a name, a lang, and a content array. Tokenise the source manually (matching the existing token types) or write a small tokeniser function that walks the source string character by character, building token objects as it recognises keywords, strings, numbers, and comments for your target language. For languages not in the existing set, adding a custom token type with a new CSS colour class is trivial.

Accept a files prop (array of {name, content} objects). Keep activeIdx in useState. Render the tab bar from files.map(). The code area maps content[activeIdx] to JSX spans per token type. The copy handler reconstructs plain text from the active file's token array and calls navigator.clipboard.writeText. Use a key prop on the code container matching activeIdx to reset scroll on tab change. For the Tailwind version, click "Tailwind" to get the same markup with utility classes instead of a scoped stylesheet.