microsoft / microsoft/microsoft-ui-reactor
REACTOR_A11Y_003 doesn't accept fluent .Header(...) as a label, and doesn't cover ComboBox/ToggleSwitch
- Dominant language
- C#
- Stars
- 646
- Forks
- 54
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 84
Description
## Context
Found while fixing #981, where four ReactorGallery cards shipped a bare `ComboBox` / `ToggleSwitch` and UIA reported `Name: (null)`. The interesting question isn't the samples — it's why nothing caught them.
`FormFieldLabelAnalyzer` (`REACTOR_A11Y_003`, `src/Reactor.Analyzers/AccessibilityAnalyzers.cs` ~L222-236) exists precisely to catch unlabelled form fields, and it was running on those files. It stayed silent for two independent reasons.
## Gap 1 — control coverage
The rule covers `TextBox`, `NumberBox`, `PasswordBox`, `AutoSuggestBox`. It does not cover `ComboBox` or `ToggleSwitch`, both of which are form fields that need an accessible name just as much.
## Gap 2 — the fluent `.Header(...)` modifier isn't recognised as a label
This one is worth fixing regardless of Gap 1, because it produces **false positives on correct code**. The analyzer accepts:
- the `header:` named argument
- `.AutomationName(...)`
- `.LabeledBy(...)`
but **not** the fluent `.Header("...")` modifier — even though it is the idiomatic Reactor spelling and demonstrably drives the UIA Name. Verified live in #981 via `HeaderAutomationNameFixtures`:
```
# HAN ComboBox: bare=<> headed= headedPlaceholder= headedEditable=
# HAN ToggleSwitch: bare=<> header=
```
So today `TextBox(...).Header("Name")` is correctly labelled but still diagnosed, while `TextBox(..., header: "Name")` is not. Two spellings of the same thing, one flagged.
## Why this wasn't fixed inline with #981
Deliberately deferred rather than smuggled into an a11y samples PR — the blast radius is real and deserves its own review:
- `samples/Directory.Build.props` wires the analyzer into **every** sample project.
- The repo root `Directory.Build.props` sets `TreatWarningsAsErrors` in **Release**.
So widening control coverage turns roughly 30 existing bare `ComboBox(...)` / `ToggleSwitch(...)` call sites across `samples/` into **Release build errors** in one step. And a good number are **false positives**: `SamplePageHost.OptionPanel` already derives `.AutomationName(...)` from a preceding caption `TextBlock` at runtime, which a syntactic analyzer cannot see. Those call sites are genuinely accessible today; flagging them would train contributors to suppress the rule, which is worse than not having it.
## Suggested sequencing
1. **Fix Gap 2 first, on its own.** Accept `.Header(...)` as a satisfying label for the controls already covered. Pure false-positive reduction, no new diagnostics, safe to land immediately.
2. **Then Gap 1**, with the sample fallout handled in the same PR — either label the real cases or find a way for the analyzer not to fire on `OptionPanel`-hosted children (an opt-out marker, or recognising the host pattern).
3. Add a row to `src/Reactor.Analyzers/AnalyzerReleases.Unshipped.md` if the id's behaviour changes materially, and note that `src/Reactor.Analyzers` targets `netstandard2.0` and cannot reference `src/Reactor.Cli` — any shared logic needs copying plus parity tests.
## Acceptance
- `TextBox(...).Header("Name")` no longer reports `REACTOR_A11Y_003`.
- A bare `ComboBox(...)` / `ToggleSwitch(...)` with no label does report it.
- `OptionPanel`-hosted children in `samples/` do not report it.
- `dotnet build -c Release` stays green across the solution.
Contributor guide
Research direction
Start in src/Reactor.Analyzers/AccessibilityAnalyzers.cs around FormFieldLabelAnalyzer and inspect the HeaderAutomationNameFixtures evidence, then review the sample call sites and Directory.Build.props files for Release warning behavior. Update the analyzer and its tests so fluent Header is accepted, bare ComboBox and ToggleSwitch controls are covered without flagging OptionPanel-hosted children, and dotnet build -c Release stays green.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- accessibility, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100