diff --git a/plugins/winui/skills/winui-design/SKILL.md b/plugins/winui/skills/winui-design/SKILL.md index ff4e081..9890d43 100644 --- a/plugins/winui/skills/winui-design/SKILL.md +++ b/plugins/winui/skills/winui-design/SKILL.md @@ -1,60 +1,59 @@ --- name: winui-design -description: "WinUI 3 UI design and XAML correctness — layout planning, control selection, Fluent Design, theming (Light/Dark/HighContrast), typography styles, spacing, brushes, accessibility, data binding review. Use when designing new pages, converting from WPF/Electron/web, reviewing XAML, fixing theme issues, or applying Fluent Design." +description: "Use when designing, reviewing, or fixing WinUI 3: layout planning, control choice, Fluent Design alignment, Light/Dark/High Contrast theming, typography, spacing, brushes, accessibility, and XAML data-binding design. Load before authoring new XAML, reviewing UI PRs, migrating desktop UI to WinUI, or choosing between WinUI controls/patterns." --- -### UI Planning -> **Before picking controls, search the catalogue.** This skill ships `winui-search.exe` alongside this `SKILL.md`. It indexes 100+ WinUI Gallery controls, every Windows Community Toolkit scenario, and a curated set of platform integration patterns (JumpList, Share, file pickers, drag-drop). Use it to ground every control choice in a real shipping sample **before writing any XAML** — this is the difference between guessing property names and copying canonical code. -> -> ```powershell -> .\winui-search.exe search "" "" ... # batch one focused query per feature -> .\winui-search.exe get ... # batch up to 3 IDs — full XAML + C# + pitfall notes -> .\winui-search.exe list # browse all patterns (heavy — prefer search) -> .\winui-search.exe update # force refresh now -> ``` -> -> **Workflow:** in **one** `search` call, list every feature you need for the current page (one focused query per feature, not a bag of keywords) → from each shortlist pick the best ID → grab full code with `get` (batch up to 3 IDs per call) → then write XAML using those samples as reference. **Do NOT interleave searching with coding** — front-load all lookups, then code. BM25 rewards focused per-query phrasing, so keep each query about one control or pattern. -#### Step 1: Identify App Type and Anchor Control -| App Type | Anchor Control | Reference App | -|----------|---------------|---------------| -| Settings / config tool | `NavigationView` Left + `SettingsCard` | Windows Settings | -| Document / session editor | `TabView` + full-width content | Windows Terminal, Notepad | -| Hierarchical browser | `TreeView` + `ListView` + `BreadcrumbBar` | File Explorer | -| Developer tool / dashboard | `NavigationView` + card layout | Dev Home | -| Single-purpose utility | Mode switcher + compact grid | Calculator | +## Search samples before writing XAML -#### Step 2: Map Requirements to Controls -**Navigation:** 2-7 sections → `NavigationView`; document tabs → `TabView`; breadcrumb trail → `BreadcrumbBar`; 2-3 modes → `SelectorBar`. +This skill ships `winui-search.exe` alongside this `SKILL.md` (≈100 WinUI Gallery controls, every Windows Community Toolkit scenario, curated platform-integration patterns; each result returns full XAML + C# + pitfall notes). **Front-load lookups, then code** — don't interleave. -**Data display:** Vertical list → `ListView`; tiles/grid → `GridView` or `ItemsRepeater` + `UniformGridLayout`; hierarchy → `TreeView`; tabular → `ListView` with Grid column headers; master-detail → `ListView` + detail `Grid`. +```powershell +.\winui-search.exe search "" "" ... # batch one focused query per feature (BM25 likes focused phrasing) +.\winui-search.exe get ... # batch up to 3 IDs — full XAML + C# + pitfall notes +.\winui-search.exe list # browse all patterns (heavy — prefer search) +.\winui-search.exe update # force cache refresh +``` + +Search covers controls **and** platform integration (file pickers, Share, JumpList, drag-drop, app lifecycle, dialogs) — front-load all lookups before writing XAML; **don't interleave** search with coding. + +## App-shape anchors + +Pick the closest shipping app silhouette before laying out a page: + +| App type | Anchor controls | Reference apps | +|----------|-----------------|----------------| +| Settings / config tool | `NavigationView` Left + `SettingsCard` / `SettingsExpander` | Windows Settings, Slack | +| Document / session editor | `TabView` + full-bleed content, light chrome | Windows Terminal, VS Code, Notepad | +| Hierarchical browser | `TreeView` + `ListView` + `BreadcrumbBar` | File Explorer, Outlook | +| Developer tool / dashboard | `NavigationView` + card layout | Dev Home, GitHub Desktop | +| Single-purpose utility | Mode switcher + compact grid | Calculator, Snipping Tool | +| Media / canvas / hero | `Grid` with hero surface, floating commands, **no** `NavigationView` | Photos, Spotify, Clipchamp | + +## Reach-for-this control map -**Input:** Text → `TextBox`; number → `NumberBox`; search → `AutoSuggestBox`; date → `CalendarDatePicker`; boolean → `ToggleSwitch`; pick one from 2-3 → `RadioButtons`; pick one from 4+ → `ComboBox`. +Before writing XAML, map the requirement to a platform control. These mappings exist to short-circuit cross-framework instincts (WPF `DataGrid`, web ``): -**Feedback:** Blocking decision → `ContentDialog`; contextual action → `Flyout`/`MenuFlyout`; onboarding → `TeachingTip`; inline status → `InfoBar`; system notification → `AppNotification`. +- **Navigation:** 2–7 sections → `NavigationView`; document/session tabs → `TabView`; breadcrumb trail → `BreadcrumbBar`; 2–3 modes → `SelectorBar`. +- **Data display:** Vertical list → `ListView`; tiles/grid → `GridView` or `ItemsRepeater` + `UniformGridLayout`; hierarchy → `TreeView`; **tabular → `ListView` with a `Grid`-based `ItemTemplate` and a header `Grid` above** (WinUI has no `DataGrid`; don't default to `CommunityToolkit.WinUI.Controls.DataGrid` — its columns can't use `x:Bind`); master-detail → `ListView` + detail `Grid`. +- **Input:** Text → `TextBox`; number → `NumberBox`; search → `AutoSuggestBox`; date → `CalendarDatePicker`; boolean → `ToggleSwitch`; pick one from 2–3 → `RadioButtons`; pick one from 4+ → `ComboBox`. +- **Feedback:** Blocking decision → `ContentDialog`; contextual action → `Flyout` / `MenuFlyout`; onboarding / hint → `TeachingTip`; inline status / async progress → `InfoBar`; system notification → `AppNotification`. -#### Step 3: Plan Layout -- **Content fills the window** — no floating cards on empty backgrounds -- `Grid` for structure, `StackPanel` only for simple stacking of few items -- Sidebar: fixed 300-360px width; main content: `Width="*"` with 24px padding -- Status bar: `Grid` row at bottom; toolbar: `CommandBar` or title bar buttons +If the mapping above doesn't fit, search `winui-search.exe` before improvising. -#### Step 4: Size the Window to the App +## Window sizing (WinUI 3 specifics) -> **WinUI 3 has no `SizeToContent`.** Without an explicit size, Windows defaults the main window to ~1024×768 — oversized for most utilities. **Size the window in `MainWindow`'s constructor; derive from the layout, not a generic.** +> **WinUI 3 has no `SizeToContent`.** Without an explicit size, Windows defaults the main window to ~1024×768 — oversized for most utilities. Size it in `MainWindow`'s constructor. -**Rubric.** Width = widest row + 48 padding (24 each side), rounded **up** to nearest 20. Height = 32 (titlebar) + Σ(row heights) + Σ(spacing) + 48 padding, rounded up to 20. Round up — clipped content is a worse failure than a slightly-wide window. +**Rubric.** Width = widest row + 48 padding, rounded up to nearest 20. Height = 32 (titlebar) + Σ(row heights) + Σ(spacing) + 48 padding, rounded up to 20. Round up — clipped content is a worse failure than a slightly-wide window. Sanity ranges (derive yours from the rubric): -**Sanity check** (ranges, not targets — derive yours from the rubric): - Single-purpose utility → ~440–560 wide - Form / single-page tool → ~600–800 wide, ~640–800 tall - Multi-pane (nav + content) → ~1100–1300 wide, ~720–840 tall - Document / canvas / media editor → 1280+ wide -If your derived number is well below its range, you missed a row — re-check. - -`AppWindow.Resize` takes **physical pixels**, not DIPs — multiply by the monitor's DPI scale: +`AppWindow.Resize` takes **physical pixels**, not DIPs — multiply by the monitor's DPI scale. `XamlRoot.RasterizationScale` is null in the constructor and stale after `AppWindow.Move`, so `[DllImport] GetDpiForWindow` is the cleanest path: ```csharp using Microsoft.UI; @@ -72,150 +71,104 @@ public sealed partial class MainWindow : Window InitializeComponent(); var hwnd = Win32Interop.GetWindowFromWindowId(AppWindow.Id); var scale = GetDpiForWindow(hwnd) / 96.0; - AppWindow.Resize(new SizeInt32((int)(460 * scale), (int)(860 * scale))); + // widthDip / heightDip come from the rubric above — derive, don't copy. + AppWindow.Resize(new SizeInt32((int)(widthDip * scale), (int)(heightDip * scale))); } } ``` -`XamlRoot.RasterizationScale` is null in the ctor and stale after `AppWindow.Move`, so `[DllImport]` is the cleanest path. Don't try to size the window by setting `Width`/`Height` on the root `Grid` — that clips content, not the window. - -If the user asks for UI validation, see `winui-ui-testing` Step 3.5 to verify the rubric against the visual checklist. - -#### Step 5: Design Anti-Patterns -| ❌ Don't | ✅ Do Instead | -|----------|--------------| -| Centered floating card on background | Content fills window with padding | -| Custom pill/segment tab switcher | `NavigationView` Top or `SelectorBar` | -| Equal-width 50/50 column split | Fixed sidebar (300-360px) + flexible main | -| Hardcoded colors (`#FF0000`) | `{ThemeResource}` brushes | -| `ScrollViewer` around `ListView` | ListView has built-in scrolling | -| Custom ControlTemplate for standard controls | Built-in controls with style overrides | +Don't size the window by setting `Width`/`Height` on the root `Grid` — that clips content, not the window. -### XAML Correctness +## XAML landmines (the things you'll otherwise ship broken) -#### Theming Rules -- **`{ThemeResource BrushName}`** at usage sites — updates on theme change -- **`{StaticResource}`** with `ResourceKey` redirects inside theme dictionaries — zero allocation -- **`ResourceKey` must end in `Brush`** (target the `SolidColorBrush`, not the `Color`) -- Always define all three variants: `x:Key="Light"`, `x:Key="Dark"`, `x:Key="HighContrast"` — never use `x:Key="Default"` -- Verify runtime theme switching: `{ThemeResource}` updates; `{StaticResource}` does not +### `x:Bind` defaults to `OneTime` ```xml - - - - - + + + + ``` -#### High Contrast -Only 8 system color brushes allowed in HC dictionaries: - -| Background | Foreground | Use Case | -|------------|------------|----------| -| `SystemColorWindowColorBrush` | `SystemColorWindowTextColorBrush` | General content | -| `SystemColorHighlightColorBrush` | `SystemColorHighlightTextColorBrush` | Selected/hover | -| `SystemColorButtonFaceColorBrush` | `SystemColorButtonTextColorBrush` | Buttons | -| `SystemColorWindowColorBrush` | `SystemColorHotlightColorBrush` | Hyperlinks | -| `SystemColorWindowColorBrush` | `SystemColorGrayTextColorBrush` | Disabled content | - -**HC prohibitions:** No hardcoded colors, no opacity, no accent colors, no regular WinUI brushes, no `SystemColor*` in Light/Dark dicts. Use empty HC dict when WinUI defaults suffice. Set `HighContrastAdjustment = None` at app level. - -#### Typography — Use Styles, Not Raw FontSize -| Style | Size | Weight | Use For | -|-------|------|--------|---------| -| `CaptionTextBlockStyle` | 12px | Regular | Small labels, timestamps | -| `BodyTextBlockStyle` | 14px | Regular | Body text (default — don't set explicitly) | -| `BodyStrongTextBlockStyle` | 14px | Semibold | Emphasized body text | -| `SubtitleTextBlockStyle` | 20px | Semibold | Section headers, card titles | -| `TitleTextBlockStyle` | 28px | Semibold | Page titles | -| `TitleLargeTextBlockStyle` | 40px | Semibold | Large feature titles | -| `DisplayTextBlockStyle` | 68px | Semibold | Hero text | - -Use `SemiBold`, never `Bold`. Minimum 12px. `BasedOn` styles must not re-declare inherited properties. - -#### Spacing and Layout -- **4px grid:** margins, padding, sizes must be multiples of 4 (4, 8, 12, 16, 24, 32, 48) -- `ControlCornerRadius` (4px) for controls, `OverlayCornerRadius` (8px) for overlays — never hardcode -- `RowSpacing`/`ColumnSpacing` instead of spacer elements -- `MinHeight`/`MinWidth` instead of fixed sizing -- No negative margins - -#### Remove Defaults -Don't set WinUI default values — blocks future updates: -- `BodyTextBlockStyle` on TextBlock, `TextFillColorPrimaryBrush` foreground, `TextWrapping="NoWrap"`, `Padding="0"`, `Margin="0"` - -#### Acrylic Pairings -| Surface | Background | Border | -|---------|-----------|--------| -| Flyouts, tooltips | `AcrylicBackgroundFillColorDefaultBrush` | `SurfaceStrokeColorFlyoutBrush` | -| UI surfaces | `AcrylicBackgroundFillColorBaseBrush` | `SurfaceStrokeColorDefaultBrush` | - -Use `BackgroundSizing="InnerBorderEdge"` on bordered acrylic. `ThemeShadow` requires `Translation="0,0,32"` and 12px parent padding. - -#### Data Binding -- `{x:Bind}` over `{Binding}`, explicit `Mode=OneWay`/`TwoWay`, `x:DataType` on `DataTemplate` -- **TextBox `x:Bind TwoWay` — always add `UpdateSourceTrigger=PropertyChanged`** so the ViewModel updates on each keystroke instead of waiting for `LostFocus`. Without it, UIA automation (`set-value`) and programmatic changes won't commit to the ViewModel. - ```xml - - ``` -- Commands over Click/Tapped handlers (MVVM) -- `VisualStateManager` for visual property changes, not code-behind -- No `IValueConverter` — prefer `x:Bind` with functions - -**Bool negation and Visibility functions** — define static methods in code-behind: -```csharp -// In code-behind (e.g., MainPage.xaml.cs) -public static Visibility BoolToVisibility(bool value) => - value ? Visibility.Visible : Visibility.Collapsed; -public static Visibility InvertBoolToVisibility(bool value) => - value ? Visibility.Collapsed : Visibility.Visible; -public static bool IsNotBusy(bool isLoading) => !isLoading; -``` +### `TextBox` two-way needs `UpdateSourceTrigger=PropertyChanged` + ```xml - -Visibility="{x:Bind local:MainPage.BoolToVisibility(ViewModel.IsLoading), Mode=OneWay}" -IsEnabled="{x:Bind local:MainPage.IsNotBusy(ViewModel.IsLoading), Mode=OneWay}" + ``` -❌ NEVER use `Converter={x:Null}` — it crashes at runtime. -#### Accessibility -- `AutomationProperties.Name` on icon-only controls -- `AutomationProperties.AutomationId` on all interactive controls -- Semantic controls (`Button`, `HyperlinkButton`) — not clickable `Border`/`TextBlock` -- `DividerStrokeColorDefaultBrush` for dividers +Default trigger resolves to `LostFocus` specifically for `TextBox.Text` (most other properties default to `PropertyChanged`). The VM is not updated per keystroke, and UIA keyboard-simulation tests (WinAppDriver `SendKeys`, etc.) that assert immediately after typing will see stale VM state until focus moves. + +### Attached properties from C# use static setters, not initializers -**Setting attached properties in code-behind** — WinUI attached properties use static methods, NOT object initializer syntax: ```csharp -using Microsoft.UI.Xaml.Automation; // required for AutomationProperties +using Microsoft.UI.Xaml.Automation; -// ❌ WRONG — object initializer doesn't work for attached properties +// ❌ WRONG — does not compile. CS0117: 'Button' does not contain a definition for 'AutomationProperties'. +// AutomationProperties is a static class of attached-property accessors, not an instance member. var btn = new Button { AutomationProperties = { AutomationId = "BtnSave" } }; -// ✅ CORRECT — static setter method +// ✅ CORRECT var btn = new Button { Content = "Save" }; AutomationProperties.SetAutomationId(btn, "BtnSave"); AutomationProperties.SetName(btn, "Save button"); Grid.SetRow(btn, 1); -Grid.SetColumn(btn, 0); ToolTipService.SetToolTip(btn, "Save the current document"); ``` -#### Formatting -- Self-closing tags for childless elements -- Styles referenced with `{StaticResource}` not `{ThemeResource}` -- No `px` suffix on numeric values, no commented-out XAML -- Consistent attribute order: x:Name, AutomationProperties, layout, content, style - -### References - -| File | Read when... | -|------|-------------| -| `references/approved-brushes.md` | Looking up correct WinUI brush names and usage rules | -| `references/theme-aware-resources.md` | Implementing ThemeResource/StaticResource, High Contrast, acrylic pairings | -| `references/code-review-checklist.md` | Reviewing XAML changes for correctness | -| `references/pr-review-patterns.md` | Applying concrete review fixes and patterns | -| `references/control-styles.md` | Customizing built-in control styles | -| `references/typography-and-spacing.md` | Detailed type ramp, spacing grid, and sizing examples | -| `references/colors-and-materials.md` | Theme brush catalog, Mica/Acrylic surface pairings, material usage | -| `references/iconography-and-motion.md` | Icon guidelines, animation patterns, connected animations | +### `Converter={x:Null}` crashes `x:Bind` at runtime + +`{x:Bind}` requires `Converter` to be a `{StaticResource}` lookup. `Converter={x:Null}` compiles but the generated code calls `LookupConverter("")`, which returns null, then dereferences it — you get `Resource Dictionary Key can only be String-typed` / `NullReferenceException` on first activation of the binding. If you don't want a converter, omit the property entirely. + +### Prefer `x:Bind` static functions over `IValueConverter` + +```csharp +// MainPage.xaml.cs +public static Visibility BoolToVisibility(bool v) => v ? Visibility.Visible : Visibility.Collapsed; +public static Visibility InvertBoolToVisibility(bool v) => v ? Visibility.Collapsed : Visibility.Visible; +public static bool Not(bool v) => !v; +``` +```xml + + +``` + +Don't rely on the glyph alone — screen readers won't announce "save icon" without `AutomationProperties.Name`. + +### Reusing an icon definition + +Define once in `App.xaml`, consume anywhere via `IconSourceElement`: + +```xml + + +``` +```xml + + + +``` + +### IconElement-bearing controls (cheat-sheet) + +Controls whose `Icon` property takes an `IconElement`: +- `AppBarButton`, `AppBarToggleButton` +- `MenuFlyoutItem`, `MenuFlyoutSubItem` +- `AutoSuggestBox.QueryIcon` +- `NavigationViewItem` +- `SelectorBarItem` + +Controls whose `IconSource` property takes an `IconSource`: +- `TabViewItem`, `SwipeItem` +- `InfoBar`, `InfoBadge` +- `TeachingTip` +- `XamlUICommand` +- `AnimatedIcon.FallbackIconSource`, `AnimatedIconSource.FallbackIconSource` + +If you find yourself wrapping a `FontIcon` in `IconSourceElement` repeatedly, you've picked the wrong slot — switch the parent's property to its `IconSource`-typed sibling if it exists. diff --git a/plugins/winui/skills/winui-design/references/code-review-checklist.md b/plugins/winui/skills/winui-design/references/code-review-checklist.md deleted file mode 100644 index 10c5a71..0000000 --- a/plugins/winui/skills/winui-design/references/code-review-checklist.md +++ /dev/null @@ -1,114 +0,0 @@ -# Code Review Checklist - -## Theme Support - -- [ ] Uses `{ThemeResource}` for colors/brushes at usage sites -- [ ] Uses `{StaticResource}` with `ResourceKey` redirects inside theme dictionaries -- [ ] Custom theme resources define `Light`, `Dark`, and `HighContrast` variants -- [ ] No `x:Key="Default"` — uses explicit `Light`/`Dark`/`HighContrast` -- [ ] `ResourceKey` values end in `Brush` (not the Color name) -- [ ] HC dictionary uses only the 8 system color brushes (no accent, no hardcoded, no WinUI brushes) -- [ ] No opacity on elements or brushes in HC dictionaries -- [ ] No HC resources (`SystemColor*`) used in Light/Dark dictionaries -- [ ] `StaticResource` redirects preferred over inline `SolidColorBrush` in theme dicts -- [ ] Theme dictionary `x:Key` order consistent across Light/Dark/HighContrast -- [ ] No partial theme updates — Light/Dark changes include matching HighContrast in same PR -- [ ] No ad-hoc themed literals (`White`/`Transparent` for themed surfaces) -- [ ] Acrylic surfaces use correct border/background pairings -- [ ] Light and Dark dicts reference the same semantic WinUI keys; differences are intentional -- [ ] Empty HC dict used when WinUI defaults suffice (``) -- [ ] `HighContrastAdjustment="None"` set at app level -- [ ] Accent colors use `SystemAccentColor*` resources (no hardcoded accent values) -- [ ] Verify runtime theme switching (ThemeResource updates; StaticResource does not) - -## Data Binding - -- [ ] Uses `{x:Bind}` over `{Binding}` where possible -- [ ] `Mode` explicitly set on `x:Bind` when values change (`OneWay`/`TwoWay`) -- [ ] `DataTemplate` has `x:DataType` specified -- [ ] No `IValueConverter` — uses `x:Bind` with functions -- [ ] Button text uses `Content` directly, not a nested `TextBlock` -- [ ] `IsEnabled` bound from ViewModel readiness state -- [ ] Commands used instead of Click/Tapped event handlers (MVVM) -- [ ] `VisualStateManager` used for visual property changes (not code-behind) -- [ ] ViewModel state mapped to named properties (bool/enum) instead of complex converter stacks -- [ ] Converters are only simple type conversions; business logic stays in ViewModel -- [ ] No code-behind for styles/colors/layout (exception: `HighContrastAdjustment` at app level) - -## Typography - -- [ ] Uses system text styles, not hardcoded font properties -- [ ] `FontWeight` is `SemiBold`, never `Bold` -- [ ] `BasedOn` styles do not re-declare inherited properties -- [ ] Default `TextFillColorPrimaryBrush` foreground not explicitly set -- [ ] No font sizes below 12px -- [ ] Icon TextBlocks set `IsTextScaleFactorEnabled="False"` -- [ ] Icon font uses `{ThemeResource SymbolThemeFontFamily}`, not hardcoded - -## Layout - -- [ ] Uses `ControlCornerRadius`/`OverlayCornerRadius` (not hardcoded) -- [ ] Selective corner rounding uses standard radii (e.g., `8,8,0,0`) -- [ ] Margins/padding use multiples of 4 -- [ ] Uses `MinHeight`/`MinWidth` instead of fixed sizing -- [ ] No fixed heights on text containers -- [ ] No fixed button widths (content-driven or `MinWidth`) -- [ ] `Border` for single-child containers (not nested Grids) -- [ ] `StackPanel` does not contain TextBlocks needing `TextTrimming` -- [ ] `RowSpacing`/`ColumnSpacing` used instead of spacer elements -- [ ] No negative margins -- [ ] `ThemeShadow` has `Translation="0,0,32"` and 12px parent padding -- [ ] Shadow receiver is behind the elevated element (z-order) -- [ ] `BackgroundSizing="InnerBorderEdge"` on bordered acrylic elements -- [ ] Mixed-control rows vertically centered - -## Styles - -- [ ] Styles referenced with `{StaticResource}` (not `{ThemeResource}`) -- [ ] Default WinUI property values not explicitly set (Padding, CornerRadius, etc.) -- [ ] Single-use styles inlined, named style deleted -- [ ] Existing WinUI styles checked before creating custom ones -- [ ] No no-op style churn -- [ ] App-specific resources stay in app or feature dictionaries -- [ ] `ThemeResource` used inside style setters for themed values -- [ ] VisualStateManager uses AdaptiveTrigger for responsive layout when needed -- [ ] Unused VisualState definitions removed - -## Resource Organization & Naming - -- [ ] Semantic resource keys used (avoid location-based names) -- [ ] Shared resources promoted only when reused across features -- [ ] One-off values remain local (no global resources for single-use) - -## Accessibility - -- [ ] `AutomationProperties.Name` on icon-only controls -- [ ] Light-dismiss targets are hit-test visible (`Background="Transparent"`) -- [ ] `DividerStrokeColorDefaultBrush` for dividers (not custom opacity brushes) - -## Performance - -- [ ] `x:Load` for conditional content -- [ ] `x:Phase` for list item incremental loading -- [ ] `OneTime` binding for static content -- [ ] Minimal container nesting - -## Formatting - -- [ ] Uniform indentation (spaces, no tabs) -- [ ] Self-closing tags for childless elements -- [ ] No `px` suffix on numeric values -- [ ] No commented-out XAML -- [ ] Unused VisualState definitions removed -- [ ] ThemeDictionaries before non-themed resources -- [ ] Namespace declarations ordered consistently (default, `x:`, platform, WinUI, local) -- [ ] Attribute order consistent across related files -- [ ] No checkpoint files checked in (use `_CP` locally and remove before commit) - -## Testing Reminders - -**If changing brushes:** Test in NightSky HC theme, hover on all interactive elements. Include Light/Dark/HC screenshot evidence. - -**If changing text/containers:** Test with text scaling at max and with long/localized strings. - -**If changing layout:** Test at 100%, 150%, 200%, 250% display scaling. Validate Figma at 100% scale. diff --git a/plugins/winui/skills/winui-design/references/colors-and-materials.md b/plugins/winui/skills/winui-design/references/colors-and-materials.md deleted file mode 100644 index caf424e..0000000 --- a/plugins/winui/skills/winui-design/references/colors-and-materials.md +++ /dev/null @@ -1,106 +0,0 @@ -# Colors and Materials Reference - -## Colors — Theme Resources - -**Never hardcode colors.** Always use `{ThemeResource}` brushes so your app works in Light, Dark, and High Contrast modes. - -### Text brushes - -| Resource | Use for | -|----------|---------| -| `TextFillColorPrimaryBrush` | Primary text (headings, body) | -| `TextFillColorSecondaryBrush` | Secondary / supporting text | -| `TextFillColorTertiaryBrush` | Pressed state text | -| `TextFillColorDisabledBrush` | Disabled text only | -| `TextOnAccentFillColorPrimaryBrush` | Text on accent-colored backgrounds | -| `AccentTextFillColorPrimaryBrush` | Hyperlinks and accent text | - -### Control fill brushes - -| Resource | Use for | -|----------|---------| -| `ControlFillColorDefaultBrush` | Control rest state | -| `ControlFillColorSecondaryBrush` | Control hover state | -| `ControlFillColorTertiaryBrush` | Control pressed state | -| `ControlFillColorDisabledBrush` | Disabled controls | -| `ControlFillColorInputActiveBrush` | Focused text input fields | - -### Background brushes - -| Resource | Use for | -|----------|---------| -| `CardBackgroundFillColorDefaultBrush` | Card backgrounds | -| `CardBackgroundFillColorSecondaryBrush` | Alternate card rows | -| `LayerFillColorDefaultBrush` | Layered surface backgrounds | -| `SolidBackgroundFillColorBaseBrush` | Opaque page backgrounds | -| `SmokeFillColorDefaultBrush` | Overlay dimming (behind dialogs) | -| `AcrylicBackgroundFillColorBaseBrush` | Acrylic material surfaces | - -### Accent fill (for primary action buttons) - -| Resource | Use for | -|----------|---------| -| `AccentFillColorDefaultBrush` | Primary button rest | -| `AccentFillColorSecondaryBrush` | Primary button hover | -| `AccentFillColorTertiaryBrush` | Primary button pressed | -| `AccentFillColorDisabledBrush` | Disabled primary button | - -### Stroke / border brushes - -| Resource | Use for | -|----------|---------| -| `CardStrokeColorDefaultBrush` | Card borders | -| `ControlStrokeColorDefaultBrush` | Control borders | -| `DividerStrokeColorDefaultBrush` | Separators and dividers | - -### Color code examples - -```xml - - - - - - - - - -``` - ---- - -## Materials — Mica & Acrylic - -**Mica** — use for the app's main window background. It samples the desktop wallpaper for a subtle tinted translucency. - -**Acrylic** — use for transient surfaces (flyouts, menus, sidebars) layered on top of the main window. - -```xml - - - - - - - - - - - - - - -``` - -| Material | Surface lifetime | Example | -|----------|-----------------|---------| -| **Mica** | Long-lived (app window) | Main window background | -| **Mica Base Alt** | Long-lived (alternate tint) | Secondary window background | -| **Acrylic** | Transient (overlays) | Flyouts, sidebars, command bars | - -Materials fall back to solid color on unsupported systems — no code needed. diff --git a/plugins/winui/skills/winui-design/references/control-styles.md b/plugins/winui/skills/winui-design/references/control-styles.md deleted file mode 100644 index cd3d6bf..0000000 --- a/plugins/winui/skills/winui-design/references/control-styles.md +++ /dev/null @@ -1,91 +0,0 @@ -# Control Styles - -Built-in WinUI 3 styles and patterns. Use `{StaticResource}` to reference, `BasedOn` to extend. - -## Button Styles - -| Style | Description | -|-------|-------------| -| `DefaultButtonStyle` | Standard button | -| `AccentButtonStyle` | Accent-colored primary action button | -| `NavigationBackButtonNormalStyle` | Back navigation (40x40) | -| `NavigationBackButtonSmallStyle` | Small back navigation (30x30) | - -```xml - -``` - -Empty HC dictionary lets WinUI defaults apply. Light and Dark usually have identical redirects. Border brush states should match background states. - -## Typography Styles - -| Style | Size | Weight | Use Case | -|-------|------|--------|----------| -| `CaptionTextBlockStyle` | 12px | Regular | Small labels, timestamps | -| `BodyTextBlockStyle` | 14px | Regular | Default body text (applied by default) | -| `BaseTextBlockStyle` | 14px | Semibold | Base body style (less common) | -| `BodyStrongTextBlockStyle` | 14px | Semibold | Emphasized body text | -| `BodyLargeTextBlockStyle` | 18px | Regular | Prominent body text | -| `SubtitleTextBlockStyle` | 20px | Semibold | Section headers, card titles | -| `TitleTextBlockStyle` | 28px | Semibold | Page titles | -| `TitleLargeTextBlockStyle` | 40px | Semibold | Large feature titles | -| `DisplayTextBlockStyle` | 68px | Semibold | Hero text | - -**Rules:** -- `BodyTextBlockStyle` is the default — do not explicitly apply it. -- `TextWrapping="NoWrap"` is the default — do not set it. -- Use `SemiBold`, never `Bold`. -- Minimum 12px for CJK legibility. -- `BasedOn` styles must not re-declare inherited properties (FontSize, FontFamily, FontWeight, LineHeight). - -## Style Hygiene - -- Reference styles with `{StaticResource}` (not `{ThemeResource}` — unnecessary overhead). -- Check for existing WinUI styles before creating custom ones. -- Single-use styles: inline the properties, delete the named style. -- Keep one-off values inline; promote to shared dictionary only when reused. -- Prefer setters/resource overrides for minor visual tweaks; avoid replacing `ControlTemplate` unless structurally required. -- Use `ThemeResource` inside style setters for theme-dependent values. -- Avoid no-op style churn. - -## Naming Conventions - -| Type | Convention | Example | -|------|------------|---------| -| Style | `{Purpose}Style` | `PrimaryButtonStyle` | -| Brush | `{Usage}{Property}Brush` | `HeaderBackgroundBrush` | -| DataTemplate | `{DataType}Template` | `UserItemTemplate` | -| Element `x:Name` | PascalCase + suffix | `SearchTextBox`, `SaveButton` | diff --git a/plugins/winui/skills/winui-design/references/iconography-and-motion.md b/plugins/winui/skills/winui-design/references/iconography-and-motion.md deleted file mode 100644 index 51d9e86..0000000 --- a/plugins/winui/skills/winui-design/references/iconography-and-motion.md +++ /dev/null @@ -1,103 +0,0 @@ -# Iconography and Motion Reference - -## Iconography - -Use **Segoe Fluent Icons** (Windows 11) via the `SymbolThemeFontFamily` resource, which falls back to **Segoe MDL2 Assets** on Windows 10 automatically. - -### Icon types in order of preference - -| Type | When to use | Example | -|------|-------------|---------| -| `SymbolIcon` | Standard named icons (simplest) | `` | -| `FontIcon` | Specific glyph codes from Segoe Fluent Icons | `` | -| `AnimatedIcon` | Interactive states (checkbox, nav, toggle) | Built-in with some controls | -| `ImageIcon` | Custom brand icons or images | `` | -| `PathIcon` | Custom vector shapes | `` | -| `BitmapIcon` | Legacy bitmap icons | Avoid — prefer `ImageIcon` | - -**Standard icon sizes:** 16px (inline/compact), 20px (default control size), 24px (emphasis), 32px (large), 48px (hero/feature). - -### Icon code examples - -```xml - - - - - - - - - - - - -``` - -Browse available icons in the **WinUI Gallery** app → Design guidance → Iconography, or search [Segoe Fluent Icons](https://learn.microsoft.com/windows/apps/design/style/segoe-fluent-icons-font). - ---- - -## Corner Radius - -Use the **built-in theme resources** — never hardcode `CornerRadius` values: - -| Resource | Value | Use for | -|----------|-------|---------| -| `ControlCornerRadius` | 4px | In-page controls (buttons, inputs, list items) | -| `OverlayCornerRadius` | 8px | Top-level containers (cards, dialogs, flyouts, app window) | -| 0px | — | Edges that intersect with other straight edges (no resource needed) | - -```xml - - - - - - - - - - - -``` - -### Connected animations - -Animate elements between pages (e.g., list item → detail page): - -```csharp -// Source page — prepare animation -var service = ConnectedAnimationService.GetForCurrentView(); -service.PrepareToAnimate("itemAnimation", sourceElement); -Frame.Navigate(typeof(DetailPage), item); - -// Destination page — play animation -var animation = ConnectedAnimationService.GetForCurrentView() - .GetAnimation("itemAnimation"); -animation?.TryStart(destinationElement); -``` diff --git a/plugins/winui/skills/winui-design/references/layout-review.md b/plugins/winui/skills/winui-design/references/layout-review.md new file mode 100644 index 0000000..2aad8be --- /dev/null +++ b/plugins/winui/skills/winui-design/references/layout-review.md @@ -0,0 +1,41 @@ +# WinUI layout and responsive review reference + +Load this when reviewing responsive behaviour, breakpoints, or state coverage on a data-driven page. SKILL.md already covers theming, control choice, and XAML landmines — don't duplicate. + +## Page planning template + +Fill these in before writing XAML or reviewing a page: + +- Primary user task: +- Secondary tasks: +- Content type / density: +- Navigation structure: flat / hierarchical / hybrid: +- App silhouette: shell (left/top nav) / document / canvas-hero / dense-grid / list-detail / single-task: +- Breakpoint behaviour at small (`<640`), medium (`641–1007`), large (`≥1008`) epx: +- Input modes covered: keyboard, mouse, touch, pen: + +## Responsive techniques (least to most disruptive) + +Pick the lightest change that preserves the task: + +| Technique | Use when | Example | +|---|---|---| +| **Reposition** | Same content fits better elsewhere | Side details move below main on narrow widths | +| **Resize** | Same content needs different space | Wider reading column at large widths | +| **Reflow** | Sequence can wrap or change columns | One column becomes two at `≥1008` epx | +| **Show/hide** | Secondary metadata is optional at small widths | Hide avatar/details, keep a route to full info | +| **Re-architect** | Width changes the task model | Single-pane list-detail becomes side-by-side | + +Breakpoints are **app-window effective pixels**, not physical screen pixels. The window can be `<640` epx on a 4K monitor. + +## State coverage for any data-driven page + +Every collection, fetch, or async-bound surface should explicitly handle: + +- **Loading** — progress text or skeleton; not just a spinner with no context +- **Empty** — what happened and what the user can do (call-to-action, not just "no items") +- **Error** — cause if known + a retry/repair affordance; never colour-only +- **Offline / permission denied** — separate from generic error if the recovery path differs +- **Selection** — including keyboard arrow-key behaviour and multi-select where relevant + +If any of these aren't represented in the view model, the page isn't done. diff --git a/plugins/winui/skills/winui-design/references/pr-review-patterns.md b/plugins/winui/skills/winui-design/references/pr-review-patterns.md deleted file mode 100644 index d1a9737..0000000 --- a/plugins/winui/skills/winui-design/references/pr-review-patterns.md +++ /dev/null @@ -1,186 +0,0 @@ -# Review Guidance Patterns - -Concrete guidance patterns for WinUI 3 XAML reviews. Use these as a checklist for common pitfalls and fixes. - -## 1. Brush References Must Target Brush Resources - -`ResourceKey` must reference the `SolidColorBrush` resource (suffix `Brush`), not the `Color` resource. - -```xml - - - - - -``` - -Applies to High Contrast as well: - -```xml - - - - - -``` - -## 2. Prefer StaticResource Redirects Over Inline SolidColorBrush - -Inline brushes allocate new objects. Redirect to existing WinUI brushes instead: - -```xml - - - - - -``` - -## 3. High Contrast Rules (Strict) - -- Only use the 8 system color brushes in HighContrast dictionaries. -- No hardcoded colors, no opacity, no accent colors, no regular WinUI brushes in HC. -- No gradient animations in HC. Use a single SystemColor brush. -- Use `{ThemeResource}` only for `SystemColor*` in HC; use `{StaticResource}` elsewhere. -- Use empty HC dictionary when WinUI defaults suffice: - `` -- Set `HighContrastAdjustment = ApplicationHighContrastAdjustment.None` once at app level. - -## 4. Remove Defaults and Redundant Properties - -Avoid setting WinUI default values; it blocks future updates. - -```xml - -