Files
Terminal.Gui/docfx/docs/navigation.md
Copilot e7a4df492d Fixes #4050. Rename Command.Select and Selecting to Activate/Activating (#4470)
* Initial plan

* Rename Command.Select to Command.Activate and Selecting to Activating

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Add Activating event propagation to SuperView

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Update all comments and docs referencing Select to Activate

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Fix event log messages in examples to use Activating/Activate

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Revert automatic Activating event propagation that broke tests

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Update docfx documentation to use Activate/Activating terminology

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* renames

* Revert "Add Activating event propagation to SuperView"

This reverts commit 6d82bee9ad.

* added command diagrams

* mermaid

* updated level 3

* again

* Select->Activate in MouseTests.cs

* Update Terminal.Gui/Views/Selectors/FlagSelector.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Refactor: Rename Selecting to Activating in View APIs

Renamed the `Selecting` event and `OnSelecting` method to
`Activating` and `OnActivating` to better reflect their purpose.
Updated all related comments, test method names, variables,
and assertions in `View` and `ViewCommandTests` to align with
the new terminology.

Improved code clarity by using `_` for unused parameters in
lambda expressions. Renamed properties like `HandleSelecting`
to `HandleActivating` and adjusted naming conventions for
consistency (e.g., `OnactivatingCount` to `OnActivatingCount`).

These changes enhance readability, maintainability, and
terminology consistency across the codebase.

* Update Terminal.Gui/Views/Selectors/OptionSelector.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Typos

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tig <585482+tig@users.noreply.github.com>
Co-authored-by: Tig <tig@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-09 12:42:34 -07:00

571 lines
24 KiB
Markdown

# Navigation Deep Dive
This document covers Terminal.Gui's navigation system, which determines:
- What are the visual cues that help the user know which element of an application is receiving keyboard and mouse input (which one has focus)?
- How does the user change which element of an application has focus?
- What are the visual cues that help the user know what keystrokes will change the focus?
- What are the visual cues that help the user know what keystrokes will cause action in elements of the application that don't currently have focus?
- What is the order in which UI elements are traversed when using keyboard navigation?
- What are the default actions for standard key/mouse input (e.g. Hotkey, `Space`, `Enter`, or a mouse click)?
## See Also
* [Keyboard Deep Dive](keyboard.md)
* [Mouse Deep Dive](mouse.md)
* [Lexicon & Taxonomy](lexicon.md)
## Lexicon & Taxonomy
[!INCLUDE [Navigation Lexicon](~/includes/navigation-lexicon.md)]
## Tenets for Terminal.Gui UI Navigation (Unless you know better ones...)
See the [Keyboard Tenets](keyboard.md) as they apply as well.
Tenets higher in the list have precedence over tenets lower in the list.
* **One Focus Per App** - It should not be possible to have two views be the "most focused" view in an application. There is always exactly one view that is the target of keyboard input.
* **There's Always a Way With The Keyboard** - The framework strives to ensure users wanting to use the keyboard can't get into a situation where some element of the application is not accessible via the keyboard. For example, we have unit tests that ensure built-in Views will all have at least one navigation key that advances focus. Another example: As long as a View with a HotKey is visible and enabled, regardless of view-hierarchy, if the user presses that hotkey, the action defined by the hotkey will happen (and, by default the View that defines it will be focused).
* **Flexible Overrides** - The framework makes it easy for navigation changes to be made from code and enables changing of behavior to be done in flexible ways. For example a view can be prevented from getting focus by setting `CanFocus` to `false` or overriding `OnHasFocusChanging` and returning `true` to cancel.
* **Decouple Concepts** - In v1 `CanFocus` is tightly coupled with `HasFocus`, `TabIndex`, `TabIndexes`, and `TabStop` and vice-versa. There was a bunch of "magic" logic that automatically attempted to keep these concepts aligned. This resulted in a poorly specified, hard-to-test, and fragile API. In v2 we strive to keep the related navigation concepts decoupled. For example, `CanFocus` and `TabStop` are decoupled. A view with `CanFocus == true` can have `TabStop == NoStop` and still be focusable with the mouse.
## Answering the Key Navigation Questions
### Visual Cues for Focus
**Current Focus Indicator:**
- Views with focus are rendered using their `ColorScheme.Focus` attribute
- The focused view may display a cursor (for text input views)
- Views in the focus chain (SuperViews of the focused view) also use focused styling
**Navigation Cues:**
- HotKeys are indicated by underlined characters in Labels, Buttons, and MenuItems
- Tab order is generally left-to-right, top-to-bottom within containers
- Focus indicators (such as highlight rectangles) show which view will receive input
### Changing Focus
**Keyboard Methods:**
- `Tab` / `Shift+Tab` - Navigate between TabStop views
- `F6` / `Shift+F6` - Navigate between TabGroup containers
- Arrow keys - Navigate within containers or between adjacent views
- HotKeys - Direct navigation to specific views (Alt+letter combinations)
- `Enter` / `Space` - Activate the focused view
**Mouse Methods:**
- Click on any focusable view to give it focus
- Focus behavior depends on whether the view was previously focused (RestoreFocus vs AdvanceFocus)
### Navigation Order
Views are traversed based on their `TabStop` behavior and position in the view hierarchy:
1. **TabStop Views** - Navigated with Tab/Shift+Tab in layout order
2. **TabGroup Views** - Containers navigated with F6/Shift+F6
3. **NoStop Views** - Skipped during keyboard navigation but can receive mouse focus
## Keyboard Navigation
The majority of the Terminal.Gui Navigation system is dedicated to enabling the keyboard to be used to navigate Views.
Terminal.Gui defines these keys for keyboard navigation:
- `Application.NextTabStopKey` (`Key.Tab`) - Navigates to the next subview that is a `TabStop` (see below). If there is no next, the first subview that is a `TabStop` will gain focus.
- `Application.PrevTabStopKey` (`Key.Tab.WithShift`) - Opposite of `Application.NextTabStopKey`.
- `Key.CursorRight` - Operates identically to `Application.NextTabStopKey`.
- `Key.CursorDown` - Operates identically to `Application.NextTabStopKey`.
- `Key.CursorLeft` - Operates identically to `Application.PrevTabStopKey`.
- `Key.CursorUp` - Operates identically to `Application.PrevTabStopKey`.
- `Application.NextTabGroupKey` (`Key.F6`) - Navigates to the next view in the view-hierarchy that is a `TabGroup` (see below). If there is no next, the first view that is a `TabGroup` will gain focus.
- `Application.PrevTabGroupKey` (`Key.F6.WithShift`) - Opposite of `Application.NextTabGroupKey`.
`F6` was chosen to match [Windows](https://learn.microsoft.com/en-us/windows/apps/design/input/keyboard-accelerators#common-keyboard-accelerators) conventions.
These keys are all registered as `KeyBindingScope.Application` key bindings by `Application`. Because application-scoped key bindings have the lowest priority, Views can override the behaviors of these keys (e.g. `TextView` overrides `Key.Tab` by default, enabling the user to enter `\t` into text). The `AllViews_AtLeastOneNavKey_Leaves` unit test ensures all built-in Views have at least one of the above keys that can advance focus.
### Navigation Examples
```csharp
// Basic focus management
var button = new Button() { Text = "Click Me", CanFocus = true, TabStop = TabBehavior.TabStop };
var textField = new TextField() { Text = "", CanFocus = true, TabStop = TabBehavior.TabStop };
// Container with group navigation
var frameView = new FrameView()
{
Title = "Options",
CanFocus = true,
TabStop = TabBehavior.TabGroup
};
// Programmatic focus control
button.SetFocus(); // Give focus to specific view
Application.Navigation.AdvanceFocus(NavigationDirection.Forward, TabBehavior.TabStop);
```
### HotKeys
See also [Keyboard](keyboard.md) where HotKey is covered more deeply...
`HotKeys` can be used to navigate across the entire application view-hierarchy. They work independently of `Focus`. This enables a user to navigate across a complex UI of nested subviews if needed (even in overlapped scenarios). An example use case is the `AllViewsTester` Scenario.
HotKeys are defined using the `HotKey` property and are activated using `Alt+` the specified key:
```csharp
var saveButton = new Button() { Text = "_Save", HotKey = Key.S };
var exitButton = new Button() { Text = "E_xit", HotKey = Key.X };
// Alt+S will activate save, Alt+X will activate exit, regardless of current focus
```
Additionally, multiple Views in an application (even within the same SuperView) can have the same HotKey.
## Mouse Navigation
Mouse-based navigation is straightforward in comparison to keyboard: If a view is focusable and the user clicks on it, it gains focus. There are some nuances, though:
- If a View is focusable, and it has focusable sub-views, what happens when a user clicks on the `Border` of the View? Which sub-view (if any) will also get focus?
- If a View is focusable, and it has focusable sub-views, what happens when a user clicks on the `ContentArea` of the View? Which sub-view (if any) will also get focus?
The answer to both questions is:
If the View was previously focused, the system keeps a record of the SubView that was previously most-focused and restores focus to that SubView (`RestoreFocus()`).
If the View was not previously focused, `AdvanceFocus()` is called to find the next appropriate focus target.
For this to work properly, there must be logic that removes the focus-cache used by `RestoreFocus()` if something changes that makes the previously-focusable view not focusable (e.g. if Visible has changed).
### Mouse Focus Examples
```csharp
// Mouse click behavior
view.MouseEvent += (sender, e) =>
{
if (e.Flags.HasFlag(MouseFlags.Button1Clicked) && view.CanFocus)
{
view.SetFocus();
e.Handled = true;
}
};
// Focus on mouse enter (optional behavior)
view.MouseEnter += (sender, e) =>
{
if (view.CanFocus && focusOnHover)
{
view.SetFocus();
}
};
```
## Application Level Navigation
At the application level, navigation is encapsulated within the @Terminal.Gui.ApplicationNavigation helper class which is publicly exposed via the @Terminal.Gui.App.Application.Navigation property.
@Terminal.Gui.App.ApplicationNavigation.GetFocused gets the most-focused View in the application. Will return `null` if there is no view with focus (an extremely rare situation). This replaces `View.MostFocused` in v1.
The @Terminal.Gui.App.ApplicationNavigation.FocusedChanged and @Terminal.Gui.App.ApplicationNavigation.FocusedChanging events are raised when the most-focused View in the application is changing or has changed. `FocusedChanged` is useful for apps that want to do something with the most-focused view (e.g. see `AdornmentsEditor`). `FocusChanging` is useful for apps that want to override what view can be focused across an entire app.
The @Terminal.Gui.App.ApplicationNavigation.AdvanceFocus method causes the focus to advance (forward or backwards) to the next View in the application view-hierarchy, using `behavior` as a filter.
The implementation is simple:
```cs
return app.Current?.AdvanceFocus (direction, behavior);
```
This method is called from the `Command` handlers bound to the application-scoped keybindings created during `app.Init()`. It is `public` as a convenience.
**Note:** When accessing from within a View, use `App?.Current` instead of `Application.TopRunnable` (which is obsolete).
This method replaces about a dozen functions in v1 (scattered across `Application` and `Runnable`).
### Application Navigation Examples
```csharp
var app = Application.Create();
app.Init();
// Listen for global focus changes
app.Navigation.FocusedChanged += (sender, e) =>
{
var focused = app.Navigation.GetFocused();
StatusBar.Text = $"Focused: {focused?.GetType().Name ?? "None"}";
};
// Prevent certain views from getting focus
app.Navigation.FocusedChanging += (sender, e) =>
{
if (e.NewView is SomeRestrictedView)
{
e.Cancel = true; // Prevent focus change
}
};
// Programmatic navigation
Application.Navigation.AdvanceFocus(NavigationDirection.Forward, TabBehavior.TabStop);
Application.Navigation.AdvanceFocus(NavigationDirection.Backward, TabBehavior.TabGroup);
```
## View Level Navigation
@Terminal.Gui.ViewBase.View.AdvanceFocus is the primary method for developers to cause a view to gain or lose focus.
Various events are raised when a View's focus is changing. For example, @Terminal.Gui.ViewBase.View.HasFocusChanging and @Terminal.Gui.ViewBase.View.HasFocusChanged.
### View Focus Management
```csharp
// Basic focus control
public class CustomView : View
{
protected override void OnHasFocusChanging(CancelEventArgs<bool> e)
{
if (SomeCondition)
{
e.Cancel = true; // Prevent focus change
return;
}
base.OnHasFocusChanging(e);
}
protected override void OnHasFocusChanged(EventArgs<bool> e)
{
if (e.CurrentValue)
{
// View gained focus
UpdateAppearance();
}
base.OnHasFocusChanged(e);
}
}
```
## What makes a View focusable?
First, only Views that are visible and enabled can gain focus. Both `Visible` and `Enabled` must be `true` for a view to be focusable.
For visible and enabled Views, the `CanFocus` property is then used to determine whether the `View` is focusable. `CanFocus` must be `true` for a View to gain focus. However, even if `CanFocus` is `true`, other factors can prevent the view from gaining focus...
A visible, enabled, and `CanFocus == true` view can be focused if the user uses the mouse to clicks on it or if code explicitly calls `View.SetFocus()`. Of course, the view itself or some other code can cancel the focus (e.g. by overriding `OnHasFocusChanging`).
For keyboard navigation, the `TabStop` property is a filter for which views are focusable from the current most-focused. `TabStop` has no impact on mouse navigation. `TabStop` is of type `TabBehavior`.
### TabBehavior Values
* `null` - This View is still being initialized; acts as a signal to `set_CanFocus` to set `TabStop` to `TabBehavior.TabStop` as convenience for the most common use-case. Equivalent to `TabBehavior.NoStop` when determining if a view is focusable by the keyboard or not.
* `TabBehavior.NoStop` - Prevents the user from using keyboard navigation to cause view (and by definition its subviews) to gain focus. Note: The view can still be focused using code or the mouse.
* `TabBehavior.TabStop` - Indicates a View is a focusable view with no focusable subviews. `Application.Next/PrevTabStopKey` will advance ONLY through the peer-Views (`SuperView.SubViews`).
* `TabBehavior.TabGroup` - Indicates a View is a focusable container for other focusable views and enables keyboard navigation across these containers. This applies to both tiled and overlapped views. For example, `FrameView` is a simple view designed to be a visible container of other views in tiled scenarios. It has `TabStop` set to `TabBehavior.TabGroup` (and `Arrangement` set to `ViewArrangement.Fixed`). Likewise, `Window` is a simple view designed to be a visible container of other views in overlapped scenarios. It has `TabStop` set to `TabBehavior.TabGroup` (and `Arrangement` set to `ViewArrangement.Movable | ViewArrangement.Resizable | ViewArrangement.Overlapped`). `Application.Next/PrevGroupStopKey` will advance across all `TabGroup` views in the application (unless blocked by a `NoStop` SuperView).
### Focus Requirements Summary
For a view to be focusable:
1. **Visible** = `true`
2. **Enabled** = `true`
3. **CanFocus** = `true`
4. **TabStop** != `TabBehavior.NoStop` (for keyboard navigation only)
```csharp
// Example: Make a view focusable
var view = new Label()
{
Text = "Focusable Label",
Visible = true, // Must be visible
Enabled = true, // Must be enabled
CanFocus = true, // Must be able to focus
TabStop = TabBehavior.TabStop // Keyboard navigable
};
```
## How To Tell if a View has focus? And which view is the most-focused?
`View.HasFocus` indicates whether the `View` is focused or not. It is the definitive signal. If the view has no focusable SubViews then this property also indicates the view is the most-focused view in the application.
Setting this property to `true` has the same effect as calling `View.SetFocus ()`, which also means the focus may not change as a result.
If `v.HasFocus == true` then:
- All views up `v`'s superview-hierarchy must be focusable.
- All views up `v`'s superview-hierarchy will also have `HasFocus == true`.
- The deepest-subview of `v` that is focusable will also have `HasFocus == true`
In other words, `v.HasFocus == true` does not necessarily mean `v` is the most-focused view, receiving input. If it has focusable sub-views, one of those (or a further subview) will be the most-focused (`Application.Navigation.GetFocused()`).
The `private bool _hasFocus` field backs `HasFocus` and is the ultimate source of truth whether a View has focus or not.
### Focus Chain Example
```csharp
// In a hierarchy: Window -> Dialog -> Button
// If Button has focus, then:
window.HasFocus == true // Part of focus chain
dialog.HasFocus == true // Part of focus chain
button.HasFocus == true // Actually focused
// Application.Navigation.GetFocused() returns button
var mostFocused = Application.Navigation.GetFocused(); // Returns button
```
### How does a user tell?
In short: `ColorScheme.Focus` - Views in the focus chain render with focused colors.
Views use their `ColorScheme.Focus` attribute when they are part of the focus chain. This provides visual feedback about which part of the application is active.
```csharp
// Custom focus styling
protected override void OnDrawContent(Rectangle viewport)
{
var attribute = HasFocus ? GetFocusColor() : GetNormalColor();
Driver.SetAttribute(attribute);
// ... draw content
}
```
## How to make a View become focused?
The primary `public` method for developers to cause a view to get focus is `View.SetFocus()`.
Unlike v1, in v2, this method can return `false` if the focus change doesn't happen (e.g. because the view wasn't focusable, or the focus change was cancelled).
```csharp
// Programmatic focus control
if (myButton.SetFocus())
{
Console.WriteLine("Button now has focus");
}
else
{
Console.WriteLine("Could not focus button");
}
// Alternative: Set HasFocus property (same effect)
myButton.HasFocus = true;
```
## How to make a View become NOT focused?
The typical method to make a view lose focus is to have another View gain focus.
```csharp
// Focus another view to remove focus from current
otherView.SetFocus();
// Or advance focus programmatically
Application.Navigation.AdvanceFocus(NavigationDirection.Forward, TabBehavior.TabStop);
// Focus can also be lost when views become non-focusable
myView.CanFocus = false; // Will lose focus if it had it
myView.Visible = false; // Will lose focus if it had it
myView.Enabled = false; // Will lose focus if it had it
```
## Determining the Most Focused SubView
In v1 `View` had `MostFocused` property that traversed up the view-hierarchy returning the last view found with `HasFocus == true`. In v2, `Application.Navigation.GetFocused()` provides the same functionality with less overhead.
```csharp
// v2 way to get the most focused view
var focused = Application.Navigation.GetFocused();
// This replaces the v1 pattern:
// var focused = Application.TopRunnable.MostFocused;
```
## How Does `View.Add/Remove` Work?
In v1, calling `super.Add (view)` where `view.CanFocus == true` caused all views up the hierarchy (all SuperViews) to get `CanFocus` set to `true` as well.
Also, in v1, if `view.CanFocus == true`, `Add` would automatically set `TabStop`.
In v2, developers need to explicitly set `CanFocus` for any view in the view-hierarchy where focus is desired. This simplifies the implementation significantly and removes confusing behavior.
In v2, the automatic setting of `TabStop` in `Add` is retained because it is not overly complex to do so and is a nice convenience for developers to not have to set both `TabStop` and `CanFocus`. Note we do NOT automatically change `CanFocus` if `TabStop` is changed.
```csharp
// v2 explicit focus setup
var container = new FrameView()
{
Title = "Container",
CanFocus = true, // Must be explicitly set
TabStop = TabBehavior.TabGroup
};
var button = new Button()
{
Text = "Click Me",
CanFocus = true, // Must be explicitly set
TabStop = TabBehavior.TabStop // Set automatically by Add(), but can override
};
container.Add(button); // Does not automatically set CanFocus on container
```
## Knowing When a View's Focus is Changing
@Terminal.Gui.ViewBase.View.HasFocusChanging and @Terminal.Gui.ViewBase.View.HasFocusChanged are raised when a View's focus is changing.
```csharp
// Monitor focus changes
view.HasFocusChanging += (sender, e) =>
{
if (e.NewValue && !ValidateCanFocus())
{
e.Cancel = true; // Prevent gaining focus
}
};
view.HasFocusChanged += (sender, e) =>
{
if (e.CurrentValue)
{
OnViewGainedFocus();
}
else
{
OnViewLostFocus();
}
};
```
## Built-In Views Interactivity
The following table summarizes how built-in views respond to various input methods:
| View | States | Static | Default | HotKeys | Activate Cmd | Accept Cmd | HotKey Cmd | Click Focus | DblClick | RightClick | GrabMouse |
|------|--------|--------|---------|---------|------------|------------|------------|-------------|----------|------------|-----------|
| **View** | 1 | Yes | No | 1 | OnSelect | OnAccept | Focus | Focus | - | - | No |
| **Label** | 1 | Yes | No | 1 | OnSelect | OnAccept | FocusNext | Focus | - | FocusNext | No |
| **Button** | 1 | No | Yes | 1 | OnSelect | Focus+OnAccept | Focus+OnAccept | HotKey | - | Select | No |
| **CheckBox** | 3 | No | No | 1 | OnSelect+Advance | OnAccept | OnAccept | Select | - | Select | No |
| **OptionSelector** | >1 | No | No | 2+ | Advance | SetValue+OnAccept | Focus+SetValue | SetFocus+SetCursor | - | SetFocus+SetCursor | No |
| **Slider** | >1 | No | No | 1 | SetFocusedOption | SetFocusedOption+OnAccept | Focus | SetFocus+SetOption | - | SetFocus+SetOption | Yes |
| **ListView** | >1 | No | No | 1 | MarkUnMarkRow | OpenSelected+OnAccept | OnAccept | SetMark+OnSelectedChanged | OpenSelected+OnAccept | - | No |
| **TextField** | 1 | No | No | 1 | - | OnAccept | Focus | Focus | SelectAll | ContextMenu | No |
| **TextView** | 1 | No | No | 1 | - | OnAccept | Focus | Focus | - | ContextMenu | Yes |
### Table Legend
- **States**: Number of visual/functional states the view can have
- **Static**: Whether the view is primarily for display (non-interactive)
- **Default**: Whether the view can be a default button (activated by Enter)
- **HotKeys**: Number of hotkeys the view typically supports
- **Activate Cmd**: What happens when Command.Activate is invoked
- **Accept Cmd**: What happens when Command.Accept is invoked
- **HotKey Cmd**: What happens when the view's hotkey is pressed
- **Click Focus**: Behavior when clicked (if CanFocus=true)
- **DblClick**: Behavior on double-click
- **RightClick**: Behavior on right-click
- **GrabMouse**: Whether the view captures mouse for drag operations
## Common Navigation Patterns
### Dialog Navigation
```csharp
var dialog = new Dialog()
{
Title = "Settings",
CanFocus = true,
TabStop = TabBehavior.TabGroup
};
var okButton = new Button() { Text = "OK", IsDefault = true };
var cancelButton = new Button() { Text = "Cancel" };
// Tab navigates between buttons, Enter activates default
dialog.Add(okButton, cancelButton);
```
### Container Navigation
```csharp
var leftPanel = new FrameView()
{
Title = "Options",
TabStop = TabBehavior.TabGroup,
X = 0,
Width = Dim.Percent(50)
};
var rightPanel = new FrameView()
{
Title = "Preview",
TabStop = TabBehavior.TabGroup,
X = Pos.Right(leftPanel),
Width = Dim.Fill()
};
// F6 navigates between panels, Tab navigates within panels
```
### List Navigation
```csharp
var listView = new ListView()
{
CanFocus = true,
TabStop = TabBehavior.TabStop
};
// Arrow keys navigate items, Enter selects, Space toggles
listView.KeyBindings.Add(Key.CursorUp, Command.Up);
listView.KeyBindings.Add(Key.CursorDown, Command.Down);
listView.KeyBindings.Add(Key.Enter, Command.Accept);
```
## Accessibility Considerations
Terminal.Gui's navigation system is designed with accessibility in mind:
### Keyboard Accessibility
- All functionality must be accessible via keyboard
- Tab order should be logical and predictable
- HotKeys provide direct access to important functions
- Arrow keys provide fine-grained navigation within controls
### Visual Accessibility
- Focus indicators must be clearly visible
- Color is not the only indicator of focus state
- Text and background contrast meets accessibility standards
- HotKeys are visually indicated (underlined characters)
### Screen Reader Support
- Focus changes are announced through system events
- View titles and labels provide context
- Status information is available programmatically
### Best Practices for Accessible Navigation
```csharp
// Provide meaningful labels
var button = new Button() { Text = "_Save Document", HotKey = Key.S };
// Set logical tab order
container.TabStop = TabBehavior.TabGroup;
foreach (var view in container.Subviews)
{
view.TabStop = TabBehavior.TabStop;
}
// Provide keyboard alternatives to mouse actions
view.KeyBindings.Add(Key.F10, Command.Context); // Right-click equivalent
view.KeyBindings.Add(Key.Space, Command.Activate); // Click equivalent
```
For more information on accessibility standards, see:
- [Web Content Accessibility Guidelines (WCAG)](https://www.w3.org/WAI/WCAG21/quickref/)
- [Microsoft Accessibility Guidelines](https://learn.microsoft.com/en-us/windows/apps/design/accessibility/)
- [.NET Accessibility Documentation](https://learn.microsoft.com/en-us/dotnet/desktop/winforms/advanced/walkthrough-creating-an-accessible-windows-based-application)