Stepper
Render an ordered sequence of steps with one step at a time + Prev/Next paging. Best for tutorials / setup wizards / cooking recipes / algorithm walkthroughs — explicitly tells the reader "follow this path, in order."
When to use
- ✅ Tutorials (install → configure → first use)
- ✅ Multi-stage flows (multi-step forms / onboarding wizards / deploy checklists)
- ✅ Algorithm walkthroughs (one step at a time, see state changes)
- ✅ Cooking / experiment steps (ingredients → prep → cook → plate)
- ❌ Pick one of several views (not a sequence — parallel choices) → use Tabs
- ❌ Time-ordered events (history / roadmap with dates) → use Timeline
- ❌ Order doesn't matter (steps in any order) → use Layout or a plain list
Basic syntax
\```stepper
:::step title="Install Rho"
\```bash
brew install rho
\```
:::
:::step title="Open a .md file"
File → Open → pick your `.md`
:::
:::step title="Start writing"
Write markdown / Rho format directly in the editor.
:::
\```
Renders: a top progress bar showing "Step 1 of 3", below it one step at a time; bottom Prev / Next buttons to page through.
All options
Block-level: ```stepper
| Option | Type | Default | Purpose |
|---|---|---|---|
default |
int | 0 (first step) |
Which step to enter on |
linear |
bool | false |
When true, must complete in order to advance (good for wizards) |
progress |
enum | top |
Progress bar position (top / none) |
Step-level: :::step
| Option | Type | Default | Purpose |
|---|---|---|---|
title |
string | (required) | Step title (shown on the progress bar) |
optional |
bool | false |
Skippable (still allows skip when linear=true) |
disabled |
bool | false |
Greyed and inaccessible (placeholder for "future steps") |
Quote
titleif it has spaces:title="Install Rho".
Examples
Example 1: 3-step tutorial
\```stepper
:::step title="Step 1: Install"
Open a terminal:
\```bash
brew install rho # macOS
sudo apt install rho # Ubuntu/Debian
\```
:::
:::step title="Step 2: Create your first file"
\```bash
echo "# Hello Rho" > demo.md
rho demo.md
\```
The app opens a window showing the rendered output.
:::
:::step title="Step 3: Write your first interact block"
Add this to `demo.md`:
\```\```interact
slider x 0 10 5 1
template stl:
[Selected] -> [{x}]
\```\```
Reload — you'll see a slider.
:::
\```
Renders: top "Step 1 of 3" → "Step 2 of 3" → "Step 3 of 3" progress bar; click Next to advance. Each step holds rich markdown (code blocks, nested fences).
Example 2: linear wizard (onboarding)
\```stepper linear=true
:::step title="Welcome"
🎉 Welcome to Rho! This wizard takes 5 minutes to set up the basics.
Click **Next** to continue.
:::
:::step title="Account"
Enter your email (used for cloud.rho.md sync):
\```interact
input email "[email protected]"
template stl:
[Email] -> [{email}]
\```
:::
:::step title="Theme preference"
\```interact
select theme "dark" "light" "system"
template stl:
[Theme] -> [{theme}]
\```
:::
:::step title="Done"
✅ All set. Click **Done** to enter the main UI.
:::
\```
Renders: 4-step strict linear wizard; can't skip ahead until the previous step is done. Pairs with interact controls for lightweight forms (note: state isn't actually submitted to a backend — pure client-side, just a UI demo).
Example 3: algorithm walkthrough (with state)
\```stepper
:::step title="Initial array"
Original array: `[5, 2, 8, 1, 9, 3]`
We'll bubble-sort: compare adjacent pairs, larger sinks.
:::
:::step title="Pass 1"
Compare:
- (5,2) → swap → `[2, 5, 8, 1, 9, 3]`
- (5,8) → no change
- (8,1) → swap → `[2, 5, 1, 8, 9, 3]`
- (8,9) → no change
- (9,3) → swap → `[2, 5, 1, 8, 3, 9]`
The maximum 9 has "sunk" to the end.
:::
:::step title="Pass 2"
Repeat over the first 5 elements ...
:::
:::step title="Done"
Sorted: `[1, 2, 3, 5, 8, 9]`
:::
\```
Renders: algorithm step-through showing intermediate state per pass. Much clearer than one block of static prose.
Example 4: with optional + disabled steps
\```stepper
:::step title="Required: base config"
Configure base config...
:::
:::step title="Optional: advanced config" optional=true
Items advanced users can tune...
(Click Skip to skip)
:::
:::step title="Required: save"
Click **Save** to persist.
:::
:::step title="Future step" disabled=true
🚧 Coming in v0.7
:::
\```
Renders: step 2 has a "Skip" button; step 4 is greyed out and inaccessible.
Plain-text fallback behavior
:::step is a markdown directive container. In readers without support:
:::step title="Step 1: Install"
content
:::
→ :::step title=... shows as a literal; step content renders normally. All steps expand inline as a long page — readers see every step, only losing the "one step at a time + paging" interactivity.
Per-reader breakdown:
| Reader | Render |
|---|---|
| Rho | Full stepper (progress bar + Prev/Next + one step at a time) |
| GitHub web | :::step ... literal + steps inlined |
| Obsidian | Same |
| VS Code default preview | Same |
| cat / less | Plain text |
Readers always see all steps — that's the point of plain-text fallback.
Common pitfalls
1. Steps out of order
\```stepper
:::step title="Step 3"
:::
:::step title="Step 1"
:::
:::step title="Step 2"
:::
\```
→ Rho renders in document order (no auto-sort). Order them before you write.
2. Too many steps
| Step count | UX |
|---|---|
| 3-5 | Best |
| 6-8 | OK, but readers click Next many times — attention drifts |
| 9-12 | Fatigue; consider splitting into two steppers |
| > 12 | Anti-pattern — switch to Timeline or document-level chapters |
3. Wildly uneven step content
\```stepper
:::step title="Step 1"
(10 paragraphs of dense prose)
:::
:::step title="Step 2"
Click Next.
:::
:::step title="Step 3"
(8 more paragraphs)
:::
\```
→ Progress bar lies — 5 steps look even, but the actual workload is wildly different. Keep each step roughly equal effort (< 3 min reading / 1-2 actions).
4. Missing ::: close
\```stepper
:::step title="A"
A content
← ❌ Missing :::
:::step title="B"
B content
:::
\```
→ The whole stepper fails to parse. Every :::step needs a paired :::.
5. linear=true but user has no Skip path
\```stepper linear=true
:::step title="Required email"
\```interact
input email "" ← ⚠️ No default; user didn't fill in but can't skip → stuck
template stl:
[Email] -> [{email}]
\```
:::
\```
→ In linear mode the user can't advance without filling email, but Rho doesn't auto-validate input. Linear steps must:
- Give every control a sensible default value, or
- Mark the step
optional=true, or - Don't use linear mode
6. stepper inside stepper
\```stepper
:::step title="Outer"
\```stepper ← ⚠️ stepper in stepper; UI gets confusing fast
\```
:::
\```
→ Technically supported by Nested DSL, but two progress bars compete visually. Improvement: use Tabs inside, or replace with a plain ordered list.
7. Step 1 is "intro," not an action
\```stepper
:::step title="Intro"
This is a Rho onboarding tutorial......(200 words of intro)
:::
:::step title="Step 1: Install"
...
:::
\```
→ Users land on step 1 expecting an "action," see a wall of prose, get confused. Improvement: put the intro before the stepper as a regular paragraph; step 1 is the first action.
Stepper vs Tabs vs Timeline — how to choose
| Scenario | Use |
|---|---|
| Strict step sequence (walk through with Prev/Next) | Stepper |
| Pick one of several views (any order) | Tabs |
| Time-ordered events (with dates, all visible) | Timeline |
| Peer comparison (must see all together) | Layout grid |
See also
- Tabs — Multi-view, same space (unordered)
- Modal — Hidden content, on-demand
- Timeline — Time sequence (not a tutorial)
- Interact controls — Embedding input/select in steps for light forms
- Nested DSL
- Plain-text fallback principle