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:
:::tabs== JavaScript```javascriptconsole.log('Hello World');== Python
print('Hello World')== Ruby
puts 'Hello World':::
**Result:**:::tabs== JavaScript```javascriptconsole.log('Hello World');== Python
print('Hello World')== Ruby
puts 'Hello World':::
How It Works#
- Start with
:::tabson its own line - Define tabs using
== Tab Name(two equals signs followed by a space and the tab name) - Add content for each tab (can include code blocks,text,lists,etc.)
- End with
:::on its own line
Code Examples in Multiple Languages#
Perfect for showing the same functionality across different programming languages:
// Fetch user data from APIasyncfunctiongetUser(id){const response = awaitfetch(`/api/users/${id}`);return response.json();}const user = awaitgetUser(123);console.log(user.name);# 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'])// 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"])}// 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:
importReactfrom'react';functionButton({onClick,children}){return (<buttononClick={onClick}className="btn btn-primary" >{children}</button> );}exportdefaultButton;<template> <button @click="onClick" class="btn btn-primary" > <slot></slot> </button></template><script>export default{ name:'Button', props:{ onClick:Function}}</script><script> export let onClick;</script><button on:click={onClick} class="btn btn-primary"> <slot></slot></button>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:
npm install my-packageyarn add my-packagepnpm add my-packagebun add my-packageConfiguration Examples#
Different configuration formats:
{"name":"my-app","version":"1.0.0","scripts":{"dev":"vite","build":"vite build"},"dependencies":{"react":"^18.2.0"}}name:my-appversion:1.0.0scripts:dev:vitebuild:vitebuilddependencies:react:^18.2.0name = "my-app"version = "1.0.0"[scripts]dev = "vite"build = "vite build"[dependencies]react = "^18.2.0"Platform-Specific Instructions#
# Install using Homebrewbrew install my-tool# Verify installationmy-tool --versionLinux#
# Install using apt (Debian/Ubuntu)sudo apt updatesudo apt install my-tool# Verify installationmy-tool --versionWindows#
# Install using Chocolateychoco install my-tool# Verify installationmy-tool--versionMixed 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.
// 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:
const result = myFunction('hello');REST API Methods#
# Get a resourcecurl -X GET https://api.example.com/users/123 \ -H "Authorization:Bearer YOUR_TOKEN"Response:
{"id":123,"name":"John Doe","email":"john@example.com"}# 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:
{"id":124,"name":"Jane Smith","email":"jane@example.com"}# 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"}'# Delete a resourcecurl -X DELETE https://api.example.com/users/123 \ -H "Authorization:Bearer YOUR_TOKEN"Response:
{"success":true,"message":"User deleted"}Database Queries#
-- 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;// 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}}]);-- 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:
functionprocessData(data){// Old inefficient approachconst results = [];for (let i = 0;i <data.length;i++){ results.push(transform(data[i]));}return results;}functionprocessData(data){// New efficient approach using mapreturn data.map(item =>transform(item));}Best Practices#
- Use meaningful tab names - Tab names should clearly indicate what's in each tab
- Keep tabs consistent - Use the same tab order across similar examples
- Don't overload tabs - 2-6 tabs is ideal;more than that becomes hard to navigate
- Consider the first tab - The first tab is shown by default,so put the most popular/relevant option first
- 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#
:::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
:::tabson 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