Repository navigation
Phase 1b: Per-platform template keying + P0/P1 sizing sweep - #2
Merged
Merged
Conversation
…onentManager, and InitService to skip components without templates for the target platform
…r platform-specific content and enhance structure for better maintainability
…ts are requested for unsupported platforms
…d platform-specific content, improving organization and maintainability
…System v2 enhancements, including platform-specific content handling and form sizing contracts
… validate platform-specific content handling and support checks
Records the template-system-v2 branch state, the Input height fix, and the P0/P1 sweep that landed the primary-blue token unification, DropdownItem hit target, and RadioGroupItem checked-border fixes. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous `dotnet restore src/` treated `src/` as a project path (MSB1003). No .sln or .slnx lives in src/ — the solution ShellUI.Native.slnx is at repo root, and it includes examples/MAUI.Demo which needs the MAUI workload and is covered by the separate build-examples job in ci.yml. Mirror ci.yml's approach: restore + build the CLI project + tests project explicitly, keeping this job workload-free and fast. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Shewart
added a commit
that referenced
this pull request
Aug 29, 2026
Updates the roadmap and development plan to reflect the state post-PR #2: - Phase 1a + 1b now live on main (44 platform-keyed templates, sizing + token contracts locked). P0/P1/P2 marked done in COMPONENTS_ROADMAP.md. - Current Snapshot table now points at feat/p3-navigation-layout as the next active branch. - New Phase 1c section in DEVELOPMENT_PLAN.md scopes the P3 tier (tabs, accordion, collapsible, breadcrumb, scroll-area, skeleton), locks implementation order to build primitives before composites, and pins the branch to the sizing + token contracts. - Phase 2 (Avalonia) is unblocked but deliberately sequenced after Phase 1c to avoid doubling maintenance surface while MAUI is still growing. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes out Phase 1b of the ShellUI Native roadmap: the template layer becomes
platform-keyed so adding Avalonia (Phase 2) is a per-template dict entry rather
than a whole parallel registry. Also lands a P0/P1 correctness/consistency sweep
of the existing MAUI templates.
Prerequisite for Phase 2 (Avalonia implementation).
Phase 1b — Template System v2
Problem:
ComponentRegistry.GetComponentContent(name)returned a singleMAUI-flavored C# string per component. There was no platform dimension in the
lookup path — Avalonia would have needed either a duplicate registry or install-time
string-mangling of MAUI templates.
Design: per-template
Contentsdictionary owned by the template class; theregistry stores
(Metadata, Contents)bundles so lookup is one hop with noper-component switch arms to maintain as new platforms are added.
public static string Content =>topublic static IReadOnlyDictionary<NativePlatform, string> Contents { get; }ComponentRegistry.GetComponentContent(name, NativePlatform)— returnsnullfor known component + unsupported platform (distinguishable from unknowncomponent via new
SupportsPlatform/GetSupportedPlatforms)UnsupportedPlatformExceptioninCore.ModelswithComponentName,RequestedPlatform,SupportedPlatformsfor programmatic callersComponentInstaller/ComponentManager/InitServiceall threadconfig.TargetPlatformthrough and skip components that don't support it,with a clear error listing supported platforms
replaces it (silent when the platform IS supported)
P0/P1 sizing + token sweep
Full re-read of every P0 + P1 template looking for the class of drift the Input
component had. Three real bugs found and fixed; everything else surveyed
(Badge, Progress, Alert, Card family, Label, Separator, Switch, Checkbox, Shell,
Dialog/Drawer/Sheet/Popover content boxes) was sized and tokenized correctly.
1.
Inputheight drift —Borderhad noHeightRequestand usedPadding = (12, 8), so the composite grew to whatever platform-default heightEntrypicked (Windows ~44, Android ~48+ with material padding). Renderedvisibly taller than the pickers sitting next to it in the same form row. Now
HeightRequest = 40andPadding = (12, 0), matchingSelect/DatePicker/TimePicker.2. Primary-blue token drift —
InputTemplatefocus border andRadioGroupItemTemplatechecked indicator used#3B82F6(blue-500) whileButton/Checkbox/Switch/Progressall use#2563EB(blue-600) forthe same "primary" role. Standardized on
#2563EB.3.
DropdownItemhit target too small —Padding = (8, 10)with no minimumheight → ~34px rows, below iOS 44px / Android 48dp touch guidance. Now
Padding = (12, 12)+MinimumHeightRequest = 40.4.
RadioGroupItemchecked-border missing — only the fill flipped color whena radio became selected; the ring stayed grey.
Checkboxhad already handledthis. Fixed to match — both stroke and background flip to
#2563EBwhen checked.Docs
Contract section (per-control height/padding table + rules for future
controls, menu rows, and icon-shaped controls) and new Design Token
Contract section (every ARGB in use mapped to its role, so drifts like
the two blues can't sneak back in and Phase 2's Avalonia
ResourceDictionaryextraction is mechanical)
registry lookup and the
SupportsPlatform/GetSupportedPlatformscontractbranch strategy, phase status, and Phase 1b follow-ups
Test plan
dotnet build src/— 0 warnings, 0 errorsdotnet test— 199/199 passing (up from 147; 52 new/updated testscovering the platform-keyed registry,
UnsupportedPlatformException, andregression locks that will fail-loud when Phase 2 adds Avalonia content)
TemplateContentTestsparameterized over all 44 components onNativePlatform.MAUI— every existing MAUI template still compiles identicallyEvery_component_reports_MAUI_as_a_supported_platform— regression lockGetComponentContent_returns_null_for_known_component_but_unsupported_platform—verifies the null-return contract for the Avalonia case that will flip once
Phase 2 adds content
MAUI.Demoon Windows/Android/iOS heads to confirmInput / Select / DatePicker / TimePicker render at the same 40px height side by
side (not yet automated)
shellui-native init --yes && add button input card dialogagainsta fresh
dotnet new mauiproject — needs a workstation with the MAUI workloadinstalled
🤖 Generated with Claude Code