Accessibility & Inclusive Design
Building Beep applications that are usable by everyone — keyboard-only users, screen readers, and users with visual, motor, or cognitive needs
Table of Contents
Overview
Beep Controls are designed with accessibility as a first-class concern. The framework provides built-in support for high-contrast mode, screen reader integration, keyboard navigation, and configurable focus indicators. This guide explains how to use these features and how to ensure your own custom controls meet the same bar.
Accessibility is not a bolt-on feature — it is woven into BaseControl so
that every control inherits it automatically. You need to opt in to enable the
full stack, but you should never need to opt out.
HighContrastMode
HighContrastMode is a global toggle that tells all Beep controls to use
system high-contrast colors instead of theme colors. When enabled, controls ignore the
active theme's palette and read from SystemColors, ensuring legibility
for users who have enabled Windows High Contrast.
static void Main()
{
ApplicationConfiguration.Initialize();
// Detect system high-contrast setting on startup
if (SystemInformation.HighContrast)
{
BeepThemesManager.EnableHighContrastMode();
}
// Or expose a toggle in your settings
SystemEvents.UserPreferenceChanged += (s, e) =>
{
if (e.Category == UserPreferenceCategory.Accessibility)
{
if (SystemInformation.HighContrast)
BeepThemesManager.EnableHighContrastMode();
else
BeepThemesManager.DisableHighContrastMode();
}
};
Application.Run(new MainForm());
}
When HighContrastMode is active, BaseControl.ApplyControlStyle() automatically
substitutes theme colors with high-contrast equivalents. No control-level code changes needed.
// Inside BaseControl.ApplyControlStyle():
if (BeepThemesManager.HighContrastMode)
{
BackColor = SystemColors.Window;
ForeColor = SystemColors.WindowText;
_borderPen = new Pen(SystemColors.WindowText, 2f); // Thicker borders
}
else
{
var theme = BeepThemesManager.ActiveTheme;
BackColor = theme.BackColor;
ForeColor = theme.ForeColor;
}
ScreenReaderSupport
ScreenReaderSupport automatically populates AccessibleName,
AccessibleDescription, and AccessibleRole on all Beep controls.
Enable it globally in Program.cs:
static void Main()
{
ApplicationConfiguration.Initialize();
BeepThemesManager.ApplyTheme("MaterialBlue");
ScreenReaderSupport.Enable(); // Activates accessibility properties globally
Application.Run(new MainForm());
}
With ScreenReaderSupport enabled, controls automatically derive their
accessible names from nearby labels, button text, or the Caption property:
// ScreenReaderSupport automatically pairs labels with inputs
var nameLabel = new BeepLabel { Text = "Full Name" };
var nameBox = new BeepTextBox();
// nameBox.AccessibleName is automatically set to "Full Name"
// For standalone controls, set explicitly:
myButton.Text = "Save";
myButton.AccessibleName = "Save Document"; // Override for more context
myButton.AccessibleDescription = "Saves the current document to disk";
Focus Indicators and Tab Order
BaseControl paints a visible focus rectangle whenever the control has keyboard
focus. You can customize the focus indicator thickness, color, and style:
// Per-control focus indicator customization
myButton.FocusIndicatorColor = Color.FromArgb(0, 120, 215);
myButton.FocusIndicatorWidth = 3;
myButton.FocusIndicatorStyle = FocusBorderStyle.Solid;
// Style options
// Solid — 2px-4px solid border in FocusIndicatorColor
// Dashed — standard Windows focus rectangle (dotted)
// Glow — soft glow around the control perimeter
Never disable focus indicators. Keyboard-only and low-vision users rely on them to know where they are on the form. If you customize, ensure high contrast against the control's background:
// Bad — invisible focus indicator on a dark control
darkPanel.FocusIndicatorColor = Color.DarkBlue;
// Good — visible indicator regardless of background
darkPanel.FocusIndicatorColor = Color.Cyan;
Caption Accessibility
Beep controls support a Caption property that serves as the accessible
label. When ScreenReaderSupport is enabled:
Caption→ populatesAccessibleNameautomaticallyCaptionDescription→ populatesAccessibleDescription- Contextual hints propagate to the Windows accessibility API
// Caption on a disabled control — screen reader reads "Date of Birth, disabled"
dobPicker.Caption = "Date of Birth";
dobPicker.CaptionDescription = "Select your birth date from the calendar";
dobPicker.Enabled = false;
// Validation errors + captions
emailBox.Caption = "Email Address";
emailBox.ValidationError = "Please enter a valid email";
// Screen reader announces: "Email Address, error: Please enter a valid email"
Region-Based Hit Testing
For controls with non-rectangular shapes (rounded corners, circular buttons, custom paths),
Beep supports region-based hit testing through HitTestRegion. This ensures
that clicks outside the visible region are not captured, which is important for users
with motor impairments who may click near the control's edge.
public class CircularButton : BaseControl
{
private Region _hitRegion;
public CircularButton()
{
Size = new Size(60, 60);
UpdateHitRegion();
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
UpdateHitRegion();
}
private void UpdateHitRegion()
{
_hitRegion?.Dispose();
using var path = new GraphicsPath();
path.AddEllipse(ClientRectangle);
_hitRegion = new Region(path);
HitTestRegion = _hitRegion;
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
using var path = new GraphicsPath();
path.AddEllipse(ClientRectangle);
e.Graphics.FillPath(_backBrush, path);
}
}
Set HitTestRegion on any BaseControl descendant to define a
custom clickable area. Clicks outside the region pass through to controls beneath.
ARIA Equivalent Properties
Beep controls map logical roles and states to the Windows accessibility API, providing the equivalent of ARIA attributes for desktop applications. Most are automatic; the table below shows the mapping for custom scenarios:
| Beep Property | Windows API | ARIA Equivalent | Automatically Set? |
|---|---|---|---|
Caption | AccessibleName | aria-label | Yes (via ScreenReaderSupport) |
CaptionDescription | AccessibleDescription | aria-description | Yes |
ControlRole | AccessibleRole | role | Yes (derived from control type) |
ValidationError | LiveRegion update | aria-invalid | Yes (announced on change) |
Enabled | State flag | aria-disabled | Yes |
IsChecked | State flag | aria-checked | Yes (checkboxes/toggles) |
// Manually set role for custom controls
public class RatingStars : BaseControl
{
public RatingStars()
{
ControlRole = AccessibleRole.Slider;
Caption = "Rating";
CaptionDescription = "Rate this item from 1 to 5 stars";
}
}
// Override for dynamic accessible descriptions
protected override AccessibleObject CreateAccessibilityInstance()
{
return new RatingAccessibleObject(this);
}
Designing Accessible Themes
When creating a custom IBeepTheme, validate these accessibility requirements:
- Contrast ratio ≥ 4.5:1 for normal text (WCAG 2.1 AA)
- Contrast ratio ≥ 3:1 for large text (≥ 18px or 14px bold)
- Non-color indicators — use icons, text labels, or patterns alongside color (e.g., error state = red border + icon)
- Minimum touch target 44 × 44px at native resolution
- Focus indicator visible against all background colors in the theme
- Disabled state clearly distinguishable — not just lighter color, but reduced opacity + different visual treatment
Accessibility Checklist
Use this checklist as a pre-release gate for any Beep-powered form:
-
ScreenReaderSupport.Enable()is called at startup - HighContrastMode detection and
UserPreferenceChangedhandler are wired up - All interactive controls are reachable by Tab / Shift+Tab
-
TabIndexfollows a logical reading order (left-to-right, top-to-bottom) - Every control without visible text has
Captionset - Focus indicators are visible against all background colors
- Color is never the sole differentiator of state (use icons, text, or patterns too)
- Modal dialogs and dropdowns close with Escape
- All text meets 4.5:1 contrast ratio in all themes
- Touch targets are ≥ 44 × 44px
- Forms degrade gracefully at 150% and 200% DPI
- Non-rectangular controls use
HitTestRegion