MDX + React Features Demo 🚀
Welcome to the advanced MDX demonstration page! This showcases the power of combining Markdown with React components.
✨ MDX = Markdown + JSX ✨
Interactive Components
Custom React Components
You can create and use custom React components directly in your MDX files:
Interactive Counter
The counter above is a fully functional React component embedded in Markdown!
Custom Styled Elements
Red highlight and teal highlight using custom components.
Tabs Component
- React
- Vue
- Angular
function WelcomeMessage() { const [name, setName] = React.useState('World'); return ( <div style={{padding: '20px', textAlign: 'center'}}> <input type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="Enter your name" style={{ padding: '8px', marginRight: '10px', borderRadius: '4px', border: '1px solid #ccc' }} /> <h2>Hello, {name}! 👋</h2> </div> ); }
<template>
<div class="welcome">
<input v-model="name" placeholder="Enter your name" />
<h2>Hello, {{ name }}! 👋</h2>
</div>
</template>
<script>
export default {
data() {
return {
name: 'World'
}
}
}
</script>
import { Component } from '@angular/core';
@Component({
selector: 'app-welcome',
template: `
<div>
<input [(ngModel)]="name" placeholder="Enter your name">
<h2>Hello, {{name}}! 👋</h2>
</div>
`
})
export class WelcomeComponent {
name = 'World';
}
Synced Tabs
- Windows
- macOS
- Linux
Windows Installation:
# Using Chocolatey
choco install nodejs
# Using Winget
winget install OpenJS.NodeJS
macOS Installation:
# Using Homebrew
brew install node
# Using MacPorts
sudo port install nodejs18
Linux Installation:
# Ubuntu/Debian
sudo apt install nodejs npm
# CentOS/RHEL
sudo yum install nodejs npm
# Arch Linux
sudo pacman -S nodejs npm
Choose your OS above, and the selection will sync across all tab groups with the same groupId!
- Windows
- macOS
- Linux
Windows Development:
- Use PowerShell or Command Prompt
- Consider Windows Subsystem for Linux (WSL)
- Visual Studio Code with Windows-specific extensions
macOS Development:
- Terminal.app or iTerm2
- Xcode Command Line Tools
- Native Unix-like environment
Linux Development:
- Native terminal environment
- Package managers for easy installation
- Vast community support
Advanced Code Examples
Live Code Editor (JavaScript/React Only)
Docusaurus Live Code Editor only supports JavaScript/React. Python requires additional tools like Pyodide or external sandboxes.
React Live Code Example:
function ColorPicker() { const [color, setColor] = React.useState('#667eea'); const colors = ['#667eea', '#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4', '#feca57']; return ( <div style={{textAlign: 'center', padding: '20px'}}> <div style={{ width: '100px', height: '100px', backgroundColor: color, margin: '0 auto 20px', borderRadius: '50%', border: '3px solid #333', transition: 'all 0.3s ease' }} /> <div style={{display: 'flex', justifyContent: 'center', gap: '10px'}}> {colors.map(c => ( <button key={c} onClick={() => setColor(c)} style={{ width: '30px', height: '30px', backgroundColor: c, border: color === c ? '3px solid #333' : '1px solid #ccc', borderRadius: '50%', cursor: 'pointer' }} /> ))} </div> <p style={{marginTop: '15px', fontFamily: 'monospace'}}> Selected: {color} </p> </div> ); }
JavaScript Calculator Example:
function Calculator() { const [display, setDisplay] = React.useState('0'); const [prevValue, setPrevValue] = React.useState(null); const [operation, setOperation] = React.useState(null); const [waitingForOperand, setWaitingForOperand] = React.useState(false); const inputNumber = (num) => { if (waitingForOperand) { setDisplay(String(num)); setWaitingForOperand(false); } else { setDisplay(display === '0' ? String(num) : display + num); } }; const calculate = () => { const prev = parseFloat(prevValue); const current = parseFloat(display); if (prev && operation) { const result = { '+': prev + current, '-': prev - current, '*': prev * current, '/': prev / current, }[operation]; setDisplay(String(result)); setPrevValue(null); setOperation(null); setWaitingForOperand(true); } }; const performOperation = (nextOperation) => { if (prevValue === null) { setPrevValue(display); } else if (operation) { calculate(); } setWaitingForOperand(true); setOperation(nextOperation); }; const clear = () => { setDisplay('0'); setPrevValue(null); setOperation(null); setWaitingForOperand(false); }; return ( <div style={{ maxWidth: '300px', margin: '0 auto', padding: '20px', border: '2px solid #667eea', borderRadius: '12px', backgroundColor: '#f8f9fa' }}> <div style={{ backgroundColor: '#333', color: 'white', padding: '15px', textAlign: 'right', fontSize: '24px', marginBottom: '15px', borderRadius: '6px', fontFamily: 'monospace' }}> {display} </div> <div style={{display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '10px'}}> <button onClick={clear} style={{gridColumn: 'span 2', padding: '15px', fontSize: '16px', backgroundColor: '#ff6b6b', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer'}}>Clear</button> <button onClick={() => performOperation('/')} style={{padding: '15px', fontSize: '16px', backgroundColor: '#667eea', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer'}}>÷</button> <button onClick={() => performOperation('*')} style={{padding: '15px', fontSize: '16px', backgroundColor: '#667eea', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer'}}>×</button> {[7,8,9].map(num => ( <button key={num} onClick={() => inputNumber(num)} style={{padding: '15px', fontSize: '16px', backgroundColor: 'white', border: '1px solid #ddd', borderRadius: '6px', cursor: 'pointer'}}>{num}</button> ))} <button onClick={() => performOperation('-')} style={{padding: '15px', fontSize: '16px', backgroundColor: '#667eea', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer'}}>-</button> {[4,5,6].map(num => ( <button key={num} onClick={() => inputNumber(num)} style={{padding: '15px', fontSize: '16px', backgroundColor: 'white', border: '1px solid #ddd', borderRadius: '6px', cursor: 'pointer'}}>{num}</button> ))} <button onClick={() => performOperation('+')} style={{padding: '15px', fontSize: '16px', backgroundColor: '#667eea', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer'}}>+</button> {[1,2,3].map(num => ( <button key={num} onClick={() => inputNumber(num)} style={{padding: '15px', fontSize: '16px', backgroundColor: 'white', border: '1px solid #ddd', borderRadius: '6px', cursor: 'pointer'}}>{num}</button> ))} <button onClick={calculate} style={{gridRow: 'span 2', padding: '15px', fontSize: '16px', backgroundColor: '#25c2a0', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer'}}>=</button> <button onClick={() => inputNumber(0)} style={{gridColumn: 'span 2', padding: '15px', fontSize: '16px', backgroundColor: 'white', border: '1px solid #ddd', borderRadius: '6px', cursor: 'pointer'}}>0</button> <button onClick={() => inputNumber('.')} style={{padding: '15px', fontSize: '16px', backgroundColor: 'white', border: '1px solid #ddd', borderRadius: '6px', cursor: 'pointer'}}>.</button> </div> </div> ); }
Python Code Support 🐍
Docusaurus does not support Python live code by default. Only static syntax highlighting is available for Python.
Static Python Code Example:
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
# Generate sample data
X = np.random.rand(1000, 5)
y = (X[:, 0] + X[:, 1] > 1).astype(int)
# Split the data
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# Train the model
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
# Evaluate
accuracy = model.score(X_test, y_test)
print(f"Model accuracy: {accuracy:.2%}")
Alternatives for Python Live Code:
🛠️ Python Interactive Solutions
- Pyodide Integration - Run Python in browser with WebAssembly
- CodePen/JSFiddle - Embed external Python sandboxes
- Trinket.io - Educational Python environment
- Repl.it embeds - Full-featured online IDE
- Jupyter Notebook integration - Via nbviewer or custom components
Example Integration:
<iframe src="https://trinket.io/embed/python/d4cb3e2f9b"
width="100%" height="300"></iframe>
Custom Alert Components
This is a success message with markdown support and a custom React component!
Be careful when using custom components. Make sure they're properly imported!
This shows what an error message looks like with our custom component.
This is an info alert without a title. You can use *markdown* and even links inside!
Progress Bars
Embedded HTML with Styling
Gradient Card
This is a custom styled card using inline CSS with gradient background.
Features:
- Custom styling
- Gradient background
- Markdown support inside HTML
- Responsive design
Mixed Content Example
Here's how you can mix regular markdown with React components seamlessly:
- Start with a numbered list
- Add some highlighted text
- Include interactive elements:
Interactive Counter
- Continue with more markdown content
- Add code examples:
// This is regular markdown code block
function mixedContent() {
return "Markdown + React = 🚀";
}
Advanced Mermaid with Styling
Math with Interactive Elements
Inline Math Examples
The quadratic formula:
Einstein's mass-energy equivalence:
Pythagorean theorem:
Block Math Examples
Gaussian Integral:
Euler's Identity:
Maxwell's Equations:
KaTeX math rendering is fully working in Docusaurus MDX files! Both inline $...$ and block $$...$$ equations are supported.
Complex Example: Todo List
function TodoList() { const [todos, setTodos] = React.useState([ { id: 1, text: 'Learn MDX', completed: true }, { id: 2, text: 'Build awesome docs', completed: false }, { id: 3, text: 'Share knowledge', completed: false } ]); const [newTodo, setNewTodo] = React.useState(''); const addTodo = () => { if (newTodo.trim()) { setTodos([...todos, { id: Date.now(), text: newTodo.trim(), completed: false }]); setNewTodo(''); } }; const toggleTodo = (id) => { setTodos(todos.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo )); }; const deleteTodo = (id) => { setTodos(todos.filter(todo => todo.id !== id)); }; return ( <div style={{ border: '2px solid #667eea', borderRadius: '12px', padding: '20px', backgroundColor: 'var(--ifm-background-surface-color)' }}> <h3 style={{marginTop: 0, color: '#667eea'}}>📝 Interactive Todo List</h3> <div style={{display: 'flex', gap: '10px', marginBottom: '20px'}}> <input type="text" value={newTodo} onChange={(e) => setNewTodo(e.target.value)} onKeyPress={(e) => e.key === 'Enter' && addTodo()} placeholder="Add new todo..." style={{ flex: 1, padding: '8px 12px', border: '1px solid #ddd', borderRadius: '6px', fontSize: '14px' }} /> <button onClick={addTodo} style={{ backgroundColor: '#667eea', color: 'white', border: 'none', padding: '8px 16px', borderRadius: '6px', cursor: 'pointer', fontSize: '14px' }} > Add </button> </div> <ul style={{listStyle: 'none', padding: 0}}> {todos.map(todo => ( <li key={todo.id} style={{ display: 'flex', alignItems: 'center', gap: '10px', padding: '8px 0', borderBottom: '1px solid #eee' }}> <input type="checkbox" checked={todo.completed} onChange={() => toggleTodo(todo.id)} style={{transform: 'scale(1.2)'}} /> <span style={{ flex: 1, textDecoration: todo.completed ? 'line-through' : 'none', color: todo.completed ? '#999' : '#333' }}> {todo.text} </span> <button onClick={() => deleteTodo(todo.id)} style={{ backgroundColor: '#ff6b6b', color: 'white', border: 'none', padding: '4px 8px', borderRadius: '4px', cursor: 'pointer', fontSize: '12px' }} > Delete </button> </li> ))} </ul> <div style={{marginTop: '15px', fontSize: '14px', color: '#666'}}> Total: {todos.length} | Completed: {todos.filter(t => t.completed).length} </div> </div> ); }
Conclusion
This page demonstrates the incredible power of MDX in Docusaurus:
- ✅ Standard Markdown - All basic features work perfectly
- ✅ React Components - Custom interactive components
- ✅ Live Code Editor - Editable JavaScript/React code blocks
- ✅ Math Support - Full KaTeX rendering for equations
- ✅ Tabs & Navigation - Enhanced user experience
- ✅ Custom Styling - Inline styles and CSS-in-JS
- ✅ Mixed Content - Seamless integration of markdown and JSX
- ✅ Complex Interactions - Full React functionality
- ⚠️ Python Limitation - Static code only, live code needs external tools
🎉 MDX + Docusaurus = Powerful Documentation! 🚀
MDX stands for Markdown + JSX - allowing you to write JSX (React components) directly in Markdown files, creating interactive and dynamic documentation.