Skip to content
Back to skills

Fieldworks Avalonia Ui

ASecurity

Build, review, or fix Avalonia UI code in FieldWorks: XAML, MVVM, view models, owned controls, headless tests, preview host, accessibility identity, and product-vs-preview wiring. Use for any change under Src/Common/FwAvalonia/, Src/Common/FwAvaloniaPreviewHost/, or Src/**/*.Avalonia/, and for net48/net8 Avalonia test changes — even if the request only mentions a control, a binding, a style, or a flaky UI test. For whole-surface migration planning use fieldworks-winforms-to-avalonia-migration...

  • 111 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
designgoc#testinggitapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned September 20, 2026

npx -y skills add sillsdev/FieldWorks --skill fieldworks-avalonia-ui --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Fieldworks Avalonia Ui?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Fieldworks Avalonia Ui
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/sillsdev-fieldworks-avalonia-ui/badge)](https://www.skillsdirectory.com/skills/sillsdev-fieldworks-avalonia-ui)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: fieldworks-avalonia-ui
description: "Build, review, or fix Avalonia UI code in FieldWorks: XAML, MVVM, view models, owned controls, headless tests, preview host, accessibility identity, and product-vs-preview wiring. Use for any change under Src/Common/FwAvalonia/, Src/Common/FwAvaloniaPreviewHost/, or Src/**/*.Avalonia/, and for net48/net8 Avalonia test changes — even if the request only mentions a control, a binding, a style, or a flaky UI test. For whole-surface migration planning use fieldworks-winforms-to-avalonia-migration first."
---

# FieldWorks Avalonia UI

## Use This For

- Avalonia XAML, view models, commands, lifetimes, dispatching, and
  resource/style changes.
- New or changed projects under `Src/**/**/*.Avalonia/`,
  `Src/Common/FwAvalonia/`, and `Src/Common/FwAvaloniaPreviewHost/`.
- Preview Host module registration, sample data providers, and UI
  diagnostics (see `.github/instructions/avalonia.instructions.md` for
  build/preview commands and project layout rules).
- UI host wiring that selects between Avalonia and legacy UI — apply
  `fieldworks-ui-wiring-review` alongside this skill.

## Start From the Established Patterns

Do not design controls or seams from scratch. The migration hub skill
(`fieldworks-winforms-to-avalonia-migration`) documents the decided
architecture; its
`../fieldworks-winforms-to-avalonia-migration/references/architecture-patterns.md`
covers owned controls, writing-system text fields, dialogs/flyouts,
validation, and lifetime. Canonical code to imitate:

- Owned field controls: `Src/Common/FwAvalonia/Detail/FwFieldControls.cs`,
  `FwOptionChooser.cs`, `DetailMenuFlyout.cs`, `HoverReveal.cs`
- Detail view + focus memory: `DataTree.cs`,
  `DetailFocusMemory.cs`
- Seams (scheduler, lifetime, clipboard, edit sessions):
  `Src/Common/FwAvalonia/Seams/`
- Headless test setup: `Src/Common/FwAvalonia/FwAvaloniaTests/TestAppBuilder.cs`;
  examples in `DetailEditingTests.cs`, `VisualParityAndDensityTests.cs`
- Density constants: `Src/Common/FwAvalonia/FwAvaloniaDensity.cs`
- **Dialog stack (XAML + CommunityToolkit.Mvvm + compiled bindings):**
  `Src/Common/FwAvaloniaDialogs/` — `LexOptionsDlgView.axaml`/`.axaml.cs` +
  `LexOptionsDlgViewModel.cs`; headless tests in `FwAvaloniaDialogsTests/`.
  This is the verified template for hand-authored dialogs — see
  "Converting a WinForms dialog (MVVM dialog stack)" below.

**Re-implementing a Phase-1 deferred screen (JIRA tickets).** The full recipe (per-screen
`Docs/migration/<screen>.md` on the never-merged `phase1-docs` branch, stub recovery from git
history, which canonical screen to copy, `UIMode=New` re-wiring) is canonical in the migration
hub skill — `.claude/skills/fieldworks-winforms-to-avalonia-migration/SKILL.md`; start there.

## Converting a WinForms dialog (MVVM dialog stack)

Hand-authored dialogs/wizards use **XAML + CommunityToolkit.Mvvm + compiled
bindings** — NOT the region/IR pattern (that is only for XML-view-definition
views). Full step-by-step, the working template, and the decision
history/rationale pointer: `references/dialog-conversion.md`. The shape, per
dialog:

1. **View** `XyzDialogView.axaml` (+ `.axaml.cs`): a `UserControl` (not a
   `Window` — see modality below), `x:DataType` set to the view-model,
   compiled `{Binding}`s, and a stable `AutomationProperties.AutomationId`
   on every interactive control. Reuse owned controls (`FwMultiWsTextField`,
   `FwOptionChooser`) for writing-system fields and list pickers.
2. **View-model** `XyzDialogViewModel.cs`: `ObservableObject` with
   `[ObservableProperty]` state and `[RelayCommand]` actions; expose the
   result (e.g. `Accepted`). Keep it LCModel-free for the view; bind real
   settings/domain through the app-settings/edit-session seams.
3. **Tests** `XyzDialogTests.cs` (headless `[AvaloniaTest]`): assert the
   compiled bindings propagate both directions and the commands fire, plus
   the per-stage PNG captures and subjective checks under "Dialog spacing"
   below — together, the per-dialog definition of done.

### Style system (density + borders, per view)

The font/density tokens and the field-border rule are a GLOBAL system, calibrated to WinForms density —
not the roomy Fluent defaults — and applied per-control-tree (the only mechanism that renders in BOTH the
runtime host and the headless tests). Full detail, the calibrated numbers, and the per-view intent:
**`references/style-system.md`**. Headlines: **dialog inputs are BOXED** (`Border.fwFieldHost`),
**detail/region values are FLAT** with subtle separators, **browse keeps its grid lines** — just denser
font everywhere; one source of truth per family (`DialogTheme.axaml` for dialogs, `FwSurfaceStyles` for
region/browse); anything that must render headlessly uses a **CONCRETE value, never a Fluent
`DynamicResource`**.

### Dialog spacing

All dialog spacing/borders come from the shared tokens in
`Src/Common/FwAvaloniaDialogs/DialogTheme.axaml` (applied to each dialog body by
`DialogThemeBootstrap.Apply(this)`, called from every dialog view ctor). See `style-system.md`'s "Dialog
spacing tokens" table for the current calibrated values — that table is the single source of truth; don't
copy the numbers here too. Headlines (full rules + rationale:
`references/dialog-conversion.md` §2a-bis):

- Every dialog root carries `Classes="fwDialogRoot"` (window padding); no root `Margin` literal.
- No text-bearing or `PART_*Host` control with 0 padding — host borders carry `Classes="fwFieldHost"`.
- OK/Cancel use the standard button-strip gap tokens.
- Never hardcode a margin/spacing literal — use a token; add new tokens to `DialogTheme.axaml`.
- The headless `DialogLayoutAssert.AssertNoCrowding(view)` tripwire gates this in every dialog's
  realized-view test.
- **Capture a PNG at EACH interaction stage via `DialogSnapshot.Capture(view, "<Prefix>-<NN>-<stage>")`
  (→ flat gitignored folder `Output/Snapshots/<Prefix>-<NN>-<stage>.png`), then Read each PNG and answer
  the six subjective-quality questions — a hard rule and part of the per-dialog definition of done,
  for detail/browse views too.** The canonical checklist, the six questions, and the
  capture → run → Read → judge → fix → re-capture loop: `references/visual-snapshot-testing.md`.

Rules specific to dialogs:

- **It lives in `Src/Common/FwAvaloniaDialogs/`** (the dedicated XAML project),
  never in the pure-C# `FwAvalonia` foundation. Avalonia projects — including
  the XAML-compiled ones — are ordinary members of the `FieldWorks.proj`
  traversal (the `Src` glob); a new dialog project just needs adding to
  `FieldWorks.sln` (restore + VS). Exclude any nested test folder from the
  library's compile glob (`<Compile Remove="XxxTests/**/*.cs"/>`).
- **Modality during coexistence:** no Avalonia `Window.ShowDialog` — show the
  dialog `UserControl` via **`AvaloniaDialogHost.ShowModal`**; the view-model
  implements **`IDialogViewModel`** and raises `CloseRequested(bool)` from
  OK/Cancel. Mechanics + code: `references/dialog-conversion.md` §2.
- **Coexistence sync with the WinForms twin:** while both implementations
  ship, they are edited together — the apply-order mirroring, divergence
  register, and paired-edit rules live in the `dialog-update` skill.
- **Scope:** simple/confirmation/settings dialogs are good junior+AI work;
  Views-engine-coupled dialogs (Find/Replace, Styles host `IVwRootSite`)
  belong with the document engine (Stage 9), NOT this stack.

## Required Checks

- Use current Avalonia docs for uncertain APIs; do not guess dispatcher,
  headless, automation, or binding behavior.
- Keep field labels on the StringTable strategy. Product-facing
  FieldWorks-owned strings go in the project `.resx` and are consumed via
  the string accessor (`FwAvaloniaStrings`/`FwAvaloniaDialogsStrings`),
  never hardcoded; the neutral resx is the English source of truth.
  Prototype hardcoded strings must be called out as gaps.
- Stamp stable, nonlocalized `AutomationProperties.AutomationId` (derived
  from IR `StableId` where applicable) and localized
  `AutomationProperties.Name` on user-facing controls.
- UI logic stays in bindings/view models where practical; avoid
  logic-heavy code-behind.
- For any Avalonia "select from a list" control, prefer the shared
  `FwOptionChooser` pattern in `Src/Common/FwAvalonia/Detail/FwOptionChooser.cs`
  (AutoCompleteBox-based, keyboard-safe, search-capable, compact density)
  over ad hoc `ListBox` popups or one-off editable selectors. Reach for a raw
  `ComboBox` only when the UX explicitly needs an always-visible inline combo
  rather than the shared flyout selector.
- Do not fix Avalonia keyboard, focus, filtering, selection, popup, or
  rendering bugs by patching `System.Windows.Forms` hosts, WinForms
  interop message handling, or other legacy host-only routes unless the
  task explicitly targets interop behavior. Default to fixing the issue
  inside the Avalonia control tree or Avalonia-owned seams.
- Marshal to the UI thread through `IUiScheduler` (or Avalonia dispatcher
  in non-region code); no hidden `Task.Run`, no sync-over-async.
- Keep preview data lightweight unless the change explicitly opts into
  LCModel/project data; product-facing paths use real edit-session/domain
  contracts — detached DTO-only models remain preview-only.
- Headless tests: simulate input on `Window`, flush with
  `Dispatcher.UIThread.RunJobs()`, and capture visual regression frames
  with Skia (`UseHeadlessDrawing=false` + `CaptureRenderedFrame()`).
- Resx satellite assemblies need no runtime bootstrap; only tests that
  exercise genuine Chorus-supplied UI need an L10NSharp
  LocalizationManager.
- Evidence runs through `./build.ps1` and `./test.ps1` via the normal repo
  graph, not branch-only build paths.

## Review Red Flags

- A Common project directly references a feature module without an
  explicit architecture decision.
- Preview-only code launched from product UI without a feature gate.
- Tests manually call `OnPropertyChanged(...)`, `ShowRecord()`, or similar
  instead of proving the real broadcast/wiring path.
- The active Avalonia path drives hidden legacy rendering/menu
  infrastructure (see the hub skill's hard rules).
- Sleep-based or timing-sensitive UI tests.
- Claims of accessibility, localization, IME, or keyboard parity without
  executable evidence (see the hub skill's
  `../fieldworks-winforms-to-avalonia-migration/references/parity-evidence.md`
  §"Evidence language").

## Evidence for a PR or a ticket

Avalonia is the surface where capture is automated, so a visible change ships
with a picture. Do not leave it to the reviewer to imagine the before and
after.

1. Capture both states from a permanent headless test, not a throwaway
   fixture, so the evidence regenerates. `references/visual-snapshot-testing.md`
   has the harness.
2. Assert the behaviour deterministically in that same test. **The test is the
   evidence; the screenshot is the courtesy.** Keep PNGs as subjective
   evidence rather than pixel-golden tests.
3. Trim, caption and label before publishing, then upload by the routes in
   `.claude/references/evidence.md`.

Label every capture **control-level headless**, never "screenshot of FLEx",
unless the product actually drives the code path. When an operation exists but
nothing writes it at runtime yet, say so beside the image; a reader who
assumes otherwise believes a feature has shipped.

Captures belong in `Output/ManualEvidence/<TICKET>/`, which is gitignored.
Do not commit files from `Output`.

## Handoff

Report Avalonia docs consulted, tests run, remaining prototype gaps,
whether the change is product-facing or preview-only, and how the live
wiring path was validated for each affected host. For parity work, say
whether visual evidence is control-level headless capture or live desktop
capture, and which automation identities were assigned.

## Keep This Skill Current

When a control pattern, headless-test technique, or Avalonia API gotcha
proves out (or a pointer above goes stale), update this skill in the same
PR — and route durable architecture lessons through the protocol in
`../fieldworks-winforms-to-avalonia-migration/references/lessons-learned.md`.

Files in this skill

  • SKILL.md11 KB
  • references/dialog-conversion.md19.5 KB
  • references/style-system.md11.5 KB
  • references/visual-snapshot-testing.md10.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…