Skip to content

Commit 73f07b6

Browse files
committed
docs(ui): add Status Bar documentation
Add comprehensive documentation for status bar integration: - Quick start with Community Toolkit - Displaying text messages - Progress indicators (determinate and indeterminate) - Animations and animation constants reference - Mode indicators (INS/OVR, line/column) - Complete examples (file processing, search) - Reusable StatusBarService class - Handling frozen status bar state - Best practices and comparison with other UI Closes #42
1 parent f8a0433 commit 73f07b6

1 file changed

Lines changed: 361 additions & 0 deletions

File tree

src/content/docs/status-bar.mdx

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
---
2+
title: Status Bar
3+
description: Learn how to display messages, progress, and animations in the Visual Studio status bar.
4+
category: fundamentals
5+
order: 12
6+
---
7+
8+
import Callout from '@components/Callout.astro';
9+
10+
The status bar at the bottom of Visual Studio displays quick feedback to users: text messages, progress indicators, and animated icons. It's ideal for brief, transient information.
11+
12+
## Quick Start with Community Toolkit
13+
14+
```csharp
15+
// Show a message
16+
await VS.StatusBar.ShowMessageAsync("Ready");
17+
18+
// Show progress
19+
await VS.StatusBar.ShowProgressAsync("Processing...", 1, 10);
20+
21+
// Clear the status bar
22+
await VS.StatusBar.ClearAsync();
23+
```
24+
25+
## Displaying Text
26+
27+
### Simple Messages
28+
29+
```csharp
30+
// Show a message
31+
await VS.StatusBar.ShowMessageAsync("Build succeeded");
32+
33+
// Clear after a delay
34+
await VS.StatusBar.ShowMessageAsync("File saved");
35+
await Task.Delay(3000);
36+
await VS.StatusBar.ClearAsync();
37+
```
38+
39+
### Traditional Approach
40+
41+
```csharp
42+
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
43+
44+
var statusBar = (IVsStatusbar)await VS.Services.GetStatusBarAsync();
45+
46+
// Check if status bar is frozen (owned by another component)
47+
statusBar.IsFrozen(out int frozen);
48+
if (frozen == 0)
49+
{
50+
statusBar.SetText("My message");
51+
}
52+
53+
// Clear
54+
statusBar.Clear();
55+
```
56+
57+
## Progress Indicator
58+
59+
### Determinate Progress
60+
61+
Show progress with known total:
62+
63+
```csharp
64+
// With Toolkit
65+
for (int i = 1; i <= 10; i++)
66+
{
67+
await VS.StatusBar.ShowProgressAsync($"Processing file {i}...", i, 10);
68+
await Task.Delay(200);
69+
}
70+
await VS.StatusBar.ClearAsync();
71+
72+
// Traditional
73+
uint cookie = 0;
74+
statusBar.Progress(ref cookie, 1, "Processing...", 5, 10); // 5 of 10
75+
statusBar.Progress(ref cookie, 0, "", 0, 0); // Clear
76+
```
77+
78+
### Indeterminate Progress
79+
80+
For unknown duration operations:
81+
82+
```csharp
83+
// Start animation
84+
await VS.StatusBar.StartAnimationAsync(StatusAnimation.Build);
85+
86+
// Do work...
87+
await DoWorkAsync();
88+
89+
// Stop animation
90+
await VS.StatusBar.EndAnimationAsync(StatusAnimation.Build);
91+
```
92+
93+
## Animations
94+
95+
Visual Studio provides several built-in animations:
96+
97+
```csharp
98+
// Available animations
99+
StatusAnimation.General // Generic pulsing
100+
StatusAnimation.Build // Build in progress
101+
StatusAnimation.Save // Save operation
102+
StatusAnimation.Deploy // Deployment
103+
StatusAnimation.Sync // Synchronization
104+
StatusAnimation.Find // Search operation
105+
StatusAnimation.Print // Print operation
106+
```
107+
108+
### Traditional Animation Control
109+
110+
```csharp
111+
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
112+
113+
var statusBar = (IVsStatusbar)await VS.Services.GetStatusBarAsync();
114+
115+
// Get animation object
116+
object icon = (short)Constants.SBAI_Build; // Build animation
117+
118+
// Start
119+
statusBar.Animation(1, ref icon);
120+
121+
// Stop
122+
statusBar.Animation(0, ref icon);
123+
```
124+
125+
### Animation Constants
126+
127+
| Constant | Value | Description |
128+
|----------|-------|-------------|
129+
| `SBAI_General` | 0 | General animation |
130+
| `SBAI_Build` | 2 | Building |
131+
| `SBAI_Save` | 3 | Saving |
132+
| `SBAI_Deploy` | 4 | Deploying |
133+
| `SBAI_Sync` | 5 | Syncing |
134+
| `SBAI_Find` | 6 | Finding |
135+
| `SBAI_Print` | 7 | Printing |
136+
137+
## Designer/Mode Indicator
138+
139+
Show the current mode in the status bar:
140+
141+
```csharp
142+
var statusBar = (IVsStatusbar)await VS.Services.GetStatusBarAsync();
143+
144+
// Set mode text (appears on the right side)
145+
statusBar.SetInsMode("OVR"); // Overwrite mode indicator
146+
statusBar.SetLineColChar(10, 25, 500); // Line 10, Col 25, Char 500
147+
```
148+
149+
## Feedback Region
150+
151+
The status bar has a feedback region that can host custom UI:
152+
153+
```csharp
154+
// This is rarely used - most extensions use text/progress only
155+
statusBar.GetFeedbackRegion(out var feedbackRegion);
156+
```
157+
158+
## Complete Examples
159+
160+
### File Processing with Progress
161+
162+
```csharp
163+
public async Task ProcessFilesAsync(IEnumerable<string> files)
164+
{
165+
var fileList = files.ToList();
166+
if (!fileList.Any()) return;
167+
168+
try
169+
{
170+
await VS.StatusBar.StartAnimationAsync(StatusAnimation.General);
171+
172+
for (int i = 0; i < fileList.Count; i++)
173+
{
174+
var fileName = Path.GetFileName(fileList[i]);
175+
await VS.StatusBar.ShowProgressAsync(
176+
$"Processing {fileName}...",
177+
i + 1,
178+
fileList.Count);
179+
180+
await ProcessFileAsync(fileList[i]);
181+
}
182+
183+
await VS.StatusBar.ShowMessageAsync($"Processed {fileList.Count} files successfully");
184+
}
185+
catch (Exception ex)
186+
{
187+
await VS.StatusBar.ShowMessageAsync($"Error: {ex.Message}");
188+
}
189+
finally
190+
{
191+
await VS.StatusBar.EndAnimationAsync(StatusAnimation.General);
192+
193+
// Clear after delay
194+
await Task.Delay(5000);
195+
await VS.StatusBar.ClearAsync();
196+
}
197+
}
198+
```
199+
200+
### Search Operation
201+
202+
```csharp
203+
public async Task<List<string>> SearchAsync(string query, CancellationToken ct)
204+
{
205+
var results = new List<string>();
206+
207+
try
208+
{
209+
await VS.StatusBar.StartAnimationAsync(StatusAnimation.Find);
210+
await VS.StatusBar.ShowMessageAsync($"Searching for '{query}'...");
211+
212+
results = await PerformSearchAsync(query, ct);
213+
214+
await VS.StatusBar.ShowMessageAsync($"Found {results.Count} results");
215+
}
216+
catch (OperationCanceledException)
217+
{
218+
await VS.StatusBar.ShowMessageAsync("Search canceled");
219+
}
220+
finally
221+
{
222+
await VS.StatusBar.EndAnimationAsync(StatusAnimation.Find);
223+
224+
await Task.Delay(3000);
225+
await VS.StatusBar.ClearAsync();
226+
}
227+
228+
return results;
229+
}
230+
```
231+
232+
### Status Bar Service Class
233+
234+
A reusable wrapper for status bar operations:
235+
236+
```csharp
237+
public class StatusBarService : IDisposable
238+
{
239+
private bool _animating;
240+
private StatusAnimation _currentAnimation;
241+
private CancellationTokenSource _clearCts;
242+
243+
public async Task ShowMessageAsync(string message, int clearAfterMs = 0)
244+
{
245+
_clearCts?.Cancel();
246+
await VS.StatusBar.ShowMessageAsync(message);
247+
248+
if (clearAfterMs > 0)
249+
{
250+
_clearCts = new CancellationTokenSource();
251+
_ = ClearAfterDelayAsync(clearAfterMs, _clearCts.Token);
252+
}
253+
}
254+
255+
public async Task ShowProgressAsync(string message, int current, int total)
256+
{
257+
_clearCts?.Cancel();
258+
await VS.StatusBar.ShowProgressAsync(message, current, total);
259+
}
260+
261+
public async Task StartAnimationAsync(StatusAnimation animation)
262+
{
263+
if (_animating)
264+
{
265+
await VS.StatusBar.EndAnimationAsync(_currentAnimation);
266+
}
267+
268+
_currentAnimation = animation;
269+
_animating = true;
270+
await VS.StatusBar.StartAnimationAsync(animation);
271+
}
272+
273+
public async Task StopAnimationAsync()
274+
{
275+
if (_animating)
276+
{
277+
await VS.StatusBar.EndAnimationAsync(_currentAnimation);
278+
_animating = false;
279+
}
280+
}
281+
282+
public async Task ClearAsync()
283+
{
284+
_clearCts?.Cancel();
285+
await StopAnimationAsync();
286+
await VS.StatusBar.ClearAsync();
287+
}
288+
289+
private async Task ClearAfterDelayAsync(int delayMs, CancellationToken ct)
290+
{
291+
try
292+
{
293+
await Task.Delay(delayMs, ct);
294+
await VS.StatusBar.ClearAsync();
295+
}
296+
catch (OperationCanceledException)
297+
{
298+
// Ignore - clear was canceled
299+
}
300+
}
301+
302+
public void Dispose()
303+
{
304+
_clearCts?.Cancel();
305+
_clearCts?.Dispose();
306+
}
307+
}
308+
```
309+
310+
## Frozen Status Bar
311+
312+
Other VS components can "freeze" the status bar to prevent changes:
313+
314+
```csharp
315+
var statusBar = (IVsStatusbar)await VS.Services.GetStatusBarAsync();
316+
317+
statusBar.IsFrozen(out int frozen);
318+
if (frozen != 0)
319+
{
320+
// Status bar is frozen by another component
321+
// Your message won't be displayed
322+
return;
323+
}
324+
325+
// Safe to update
326+
statusBar.SetText("My message");
327+
```
328+
329+
<Callout type="tip">
330+
The Community Toolkit methods handle frozen state automatically. Use the traditional approach only when you need fine-grained control.
331+
</Callout>
332+
333+
## Best Practices
334+
335+
1. **Keep messages brief** - Status bar space is limited
336+
2. **Clear after a delay** - Don't leave stale messages
337+
3. **Use appropriate animations** - Match the operation type
338+
4. **Don't overwrite important messages** - Check if frozen
339+
5. **Provide progress for long operations** - Users should know something is happening
340+
6. **Use consistent formatting** - "Verb + object" pattern works well
341+
342+
<Callout type="warning">
343+
The status bar is shared across all extensions and VS features. Don't assume your message will persist - it may be overwritten at any time.
344+
</Callout>
345+
346+
## Status Bar vs Other UI
347+
348+
| Information Type | Recommended UI |
349+
|------------------|----------------|
350+
| Quick feedback (2-5 seconds) | Status bar message |
351+
| Operation progress | Status bar progress |
352+
| Important notification | InfoBar |
353+
| Errors needing action | Error List |
354+
| Detailed logs | Output Window |
355+
| Blocking operation | Wait Dialog |
356+
357+
## See Also
358+
359+
- [Progress Indication](progress-indication) - Detailed progress feedback
360+
- [InfoBars](infobars) - Non-modal notifications
361+
- [Output Window](output-window) - Detailed logging

0 commit comments

Comments
 (0)