3 min read

Tabs Component

The documentation system includes a tabs component that allows you to show the same content in multiple languages or frameworks. This is perfect for API documentation,code examples,and multi-platform guides.

Basic Syntax#

Use :::tabs to create a tabbed interface. Each tab is defined with == Tab Name:

Markdown
:::tabs== JavaScript```javascriptconsole.log('Hello World');

== Python

Python
print('Hello World')

== Ruby

Ruby
puts 'Hello World'

:::

Plaintext
**Result:**:::tabs== JavaScript```javascriptconsole.log('Hello World');

== Python

Python
print('Hello World')

== Ruby

Ruby
puts 'Hello World'

:::

How It Works#

  1. Start with :::tabs on its own line
  2. Define tabs using == Tab Name (two equals signs followed by a space and the tab name)
  3. Add content for each tab (can include code blocks,text,lists,etc.)
  4. End with ::: on its own line

Code Examples in Multiple Languages#

Perfect for showing the same functionality across different programming languages:

Javascript
// Fetch user data from APIasyncfunctiongetUser(id){const response = awaitfetch(`/api/users/${id}`);return response.json();}const user = awaitgetUser(123);console.log(user.name);
Python
# Fetch user data from APIimport requestsdefget_user(id): response = requests.get(f'/api/users/{id}')return response.json()user = get_user(123)print(user['name'])
Go
// Fetch user data from APIpackage mainimport ("encoding/json""fmt""net/http")funcgetUser(id int) (map[string]interface{},error){ resp,err:= http.Get(fmt.Sprintf("/api/users/%d",id))if err != nil{returnnil,err}defer resp.Body.Close()var user map[string]interface{} json.NewDecoder(resp.Body).Decode(&user)return user,nil}funcmain(){ user,_:= getUser(123) fmt.Println(user["name"])}
Rust
// Fetch user data from APIuse serde_json::Value;asyncfnget_user(id:u32) ->Result<Value,reqwest::Error>{leturl = format!("/api/users/{}",id);letresponse = reqwest::get(&url).await?; response.json::<Value>().await}#[tokio::main]asyncfnmain(){letuser = get_user(123).await.unwrap();println!("{}",user["name"]);}

Framework-Specific Examples#

Show the same component in different frameworks:

Button.jsx
importReactfrom'react';functionButton({onClick,children}){return (<buttononClick={onClick}className="btn btn-primary" >{children}</button> );}exportdefaultButton;
Button.vue
<template> <button @click="onClick" class="btn btn-primary" > <slot></slot> </button></template><script>export default{ name:'Button', props:{ onClick:Function}}</script>
Button.svelte
<script> export let onClick;</script><button on:click={onClick} class="btn btn-primary"> <slot></slot></button>
button.component.ts
import{Component,Input,Output,EventEmitter}from'@angular/core';@Component({selector:'app-button',template:` <button (click)="onClick.emit()" class="btn btn-primary" > <ng-content></ng-content> </button> `})exportclassButtonComponent{@Output() onClick = newEventEmitter<void>();}

Installation Instructions#

Show installation steps for different package managers:

Bash
npm install my-package
Bash
yarn add my-package
Bash
pnpm add my-package
Bash
bun add my-package

Configuration Examples#

Different configuration formats:

config.json
{"name":"my-app","version":"1.0.0","scripts":{"dev":"vite","build":"vite build"},"dependencies":{"react":"^18.2.0"}}
config.yaml
name:my-appversion:1.0.0scripts:dev:vitebuild:vitebuilddependencies:react:^18.2.0
config.toml
name = "my-app"version = "1.0.0"[scripts]dev = "vite"build = "vite build"[dependencies]react = "^18.2.0"

Platform-Specific Instructions#

Bash
# Install using Homebrewbrew install my-tool# Verify installationmy-tool --version

Linux#

Bash
# Install using apt (Debian/Ubuntu)sudo apt updatesudo apt install my-tool# Verify installationmy-tool --version

Windows#

Powershell
# Install using Chocolateychoco install my-tool# Verify installationmy-tool--version

Mixed Content Types#

Tabs can contain any markdown content,not just code blocks:

This is the overview tab with regular markdown content.

You can include:

  • Lists
  • Bold text
  • Italic text
  • Links

And even paragraphs of text explaining concepts.

Javascript
// Here's the code implementationfunctionexample(){return'This tab has code';}

myFunction(param)#

Parameters:

  • param (string):Description of the parameter

Returns: Description of return value

Example:

Javascript
const result = myFunction('hello');

REST API Methods#

Bash
# Get a resourcecurl -X GET https://api.example.com/users/123 \ -H "Authorization:Bearer YOUR_TOKEN"

Response:

Json
{"id":123,"name":"John Doe","email":"john@example.com"}
Bash
# Create a resourcecurl -X POST https://api.example.com/users \ -H "Content-Type:application/json" \ -H "Authorization:Bearer YOUR_TOKEN" \ -d '{ "name":"Jane Smith", "email":"jane@example.com"}'

Response:

Json
{"id":124,"name":"Jane Smith","email":"jane@example.com"}
Bash
# Update a resourcecurl -X PUT https://api.example.com/users/123 \ -H "Content-Type:application/json" \ -H "Authorization:Bearer YOUR_TOKEN" \ -d '{ "name":"John Updated", "email":"john.new@example.com"}'
Bash
# Delete a resourcecurl -X DELETE https://api.example.com/users/123 \ -H "Authorization:Bearer YOUR_TOKEN"

Response:

Json
{"success":true,"message":"User deleted"}

Database Queries#

Sql
-- Select users with recent activitySELECT u.id,u.name,u.email,MAX(a.created_at) as last_activityFROM users uJOIN activities a ON u.id = a.user_idWHERE a.created_at > NOW() -INTERVAL30DAYGROUPBY u.id,u.name,u.emailORDERBY last_activity DESC;
Javascript
// Select users with recent activitydb.users.aggregate([{$lookup:{from:"activities",localField:"_id",foreignField:"user_id",as:"activities"}},{$match:{"activities.created_at":{$gte:newDate(Date.now() - 30 * 24 * 60 * 60 * 1000)}}},{$project:{name:1,email:1,last_activity:{$max:"$activities.created_at"}}},{$sort:{last_activity:-1}}]);
Sql
-- Select users with recent activitySELECT u.id,u.name,u.email,MAX(a.created_at) as last_activityFROM users uJOIN activities a ON u.id = a.user_idWHERE a.created_at >CURRENT_TIMESTAMP-INTERVAL'30 days'GROUPBY u.id,u.name,u.emailORDERBY last_activity DESC;

Combining with Enhanced Code Blocks#

You can use code block features (titles,line highlighting) inside tabs:

old-code.js
functionprocessData(data){// Old inefficient approachconst results = [];for (let i = 0;i <data.length;i++){ results.push(transform(data[i]));}return results;}
new-code.js
functionprocessData(data){// New efficient approach using mapreturn data.map(item =>transform(item));}

Best Practices#

  1. Use meaningful tab names - Tab names should clearly indicate what's in each tab
  2. Keep tabs consistent - Use the same tab order across similar examples
  3. Don't overload tabs - 2-6 tabs is ideal;more than that becomes hard to navigate
  4. Consider the first tab - The first tab is shown by default,so put the most popular/relevant option first
  5. Test on mobile - Tabs are horizontally scrollable on mobile devices

Tips#

  • Tab names can include spaces and special characters:== Node.js (v20+)
  • Content can be any valid markdown including headings,lists,code blocks,etc.
  • Nesting tabs inside tabs is not recommended and may not work correctly
  • Empty tabs are not recommended;each tab should have meaningful content

Syntax Reference#

Markdown
:::tabs== First Tab NameContent for first tab goes here.Can be multiple lines.== Second Tab NameContent for second tab.== Third Tab NameMore content here.:::

Rules:

  • Must start with :::tabs on its own line
  • Each tab starts with == Tab Name (two equals signs,space,then the name)
  • Content follows each tab declaration until the next == or :::
  • Must end with ::: on its own line

Browser Support#

The tabs component works in all modern browsers:

  • ✅ Chrome/Edge (latest)
  • ✅ Firefox (latest)
  • ✅ Safari (latest)
  • ✅ Mobile browsers

Features used:

  • CSS Flexbox for layout
  • CSS animations for smooth transitions
  • JavaScript ES6+ for interactivity
  • Touch scrolling for mobile tab navigation