uno
Beautiful themed components for Uno Platform in C#
Install / Use
npx skills add tobitege/Flowery.UnoInstalls into whichever agent you are using.
Cursor Rules
Cursor IDE rules (v2)
Quality Score
Category
Education & ResearchSupported Platforms
Skill content
View source on GitHubalwaysApply: true
Flowery.Uno MANDATORY Development Notes
This file captures learnings and patterns discovered during Flowery.Uno development for future reference.
🚨 READ THIS FIRST (top crash-prevention rules)
If you only read the first ~50 lines of this file, read this section. These rules prevent the most common Uno “mystery” runtime crashes:
- ContentControls that rebuild
Content: ALWAYS detach before re-parenting.- Pattern:
_userContent = Content; Content = null; BuildVisualTree(); _presenter.Content = _userContent; - See “UIElement can only have one parent” (search for
### 19).
- Pattern:
- Never bind a
ContentPresenterback tothis.Contentin a control that later setsContent = _rootGrid(creates self-parenting / re-parenting issues).- See the anti-pattern example under
### 19.
- See the anti-pattern example under
- Don’t use
PathIcondynamically in code-behind (Uno can throwArgumentException: Value does not fall within the expected range.).- Use
Microsoft.UI.Xaml.Shapes.PathorFlowery.Helpers.FloweryPathHelpersinstead (search for### 18).
- Use
- Use
DaisyControlExtensions.Iconfor button icons - This is the GOLD STANDARD (see section below). - Ambiguous type names:
Path,Color, etc. often need aliasing/qualification.- Example:
using Path = Microsoft.UI.Xaml.Shapes.Path;(search for### 12).
- Example:
- Do NOT merge
ms-appx:///uno.toolkit.*/Styles/Generic.xaml.Uno.Toolkit.*packages do not shipStyles/Generic.xaml. Adding that dictionary will fail to load resources and can crash at startup. ShadowContainer only needs the package reference.
Neumorphic Takeaways
For the distilled, field-tested fixes and integration notes from recent stability work, see llms-static/neumorphic.md → Field-Tested Integration Notes (Session Takeaways).
ThemeShadow + Elevation Learnings
- ThemeShadow requires explicit receivers: add the receiver to
ThemeShadow.Receivers(see Uno tests in!uno/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Media/ThemeShadowTests). - Translation.Z defines shadow depth: the casting element must have a
TranslationZ (e.g.,0,0,6). - CornerRadius is respected when ThemeShadow is applied directly to
BorderorRectanglewith radius properties (no custom masking required). - WASM/Skia elevation: for rounded shadows, apply
SetElevationto the template’sBorder(e.g.,ButtonBorder), not theButtoncontrol itself.
Pitfalls (Session)
These are compile-time issues that should be avoided up front:
- Do not use
??with different operand types (e.g.,Border ?? DaisyCard). Cast to a shared base likeFrameworkElementfirst. - Do not assign
UIElementtoFrameworkElementwithout an explicit cast and a null/type check. - Do not reference non-existent WinUI/Uno members like
FrameworkElement.IsVisibleChanged; use supported events orRegisterPropertyChangedCallback. - Do not access internal or private helpers (e.g.,
PlatformCompatibility) from outside their assembly. - Do not set
nullinto non-nullable reference types; update the type or use a nullable value. - Do not use
x:Bindpaths that are not real properties on the page (e.g.,Localization); ensure the property exists and follow the required localization binding pattern.
WASM/Browser (Skia) Heads-Up (Session)
These are the practical fixes and gotchas encountered when getting the Browser head running with Skia:
- Use
Microsoft.NET.Sdk.WebAssemblyfor the Browser head when usingUno.WinUI.Runtime.Skia.WebAssembly.Browser. Do NOT referenceUno.WinUI.Runtime.WebAssembly(triggersUNOB0017). - Target
net9.0withRuntimeIdentifier=browser-wasmand run viadotnet runon the project (not the output folder) to avoidhostpolicy.dllself-contained errors. - Use
HostBuilder.UseWebAssembly()directly; avoid reflection-based host builder hacks (inaccessible method errors). - Fix culture crashes by disabling invariant globalization and including ICU data:
<InvariantGlobalization>false</InvariantGlobalization><WasmIncludeFullIcuData>true</WasmIncludeFullIcuData>
- Keep SkiaSharp versions aligned across managed + native:
SkiaSharpandSkiaSharp.NativeAssets.WebAssemblyMUST match (e.g.,3.119.1) or you will hit undefined symbol errors.
- Static web assets duplicates (library layout + root assets) cause:
Two assets found targeting the same path with incompatible asset kinds- Fix by disabling root asset copies for
net9.0library projects and usingms-appx:///Flowery.Uno.Gallery/Assets/...paths. - Add a Browser-head build target that
RemoveDuplicateson@(UnoAllCopyToOutputItems)before_UnoAssetsGetCopyToPublishDirectoryItems.
- CSP warnings (workers,
unsafe-eval) andWEBGL_invalid_enummessages are expected in debug and are not fatal. - Keep Browser script ports aligned (5236) to avoid mismatched logs vs URL.
ms-appx:///is the correct scheme for Content assets in Uno (including WASM); it is supported byImage/BitmapImage.- Referencing assets in code can use
ms-appx:///Assets/...orms-appx:///AssemblyName/Assets/...and can be bound as a string. - Uno 4.7+ requires exact-case assembly names in
ms-appx:///AssemblyName/...(case-sensitive). - Library assets require
<GenerateLibraryLayout>true</GenerateLibraryLayout>in the library.csproj. - Library assets are referenced via
ms-appx:///[LibraryName]/[AssetPath]and viaStorageFile.GetFileFromApplicationUriAsync. - For non-WinAppSDK targets, library asset names should be lowercased in the
ms-appxURI. StorageFileHelper.ExistsInPackage("Assets/...")can be used to confirm asset presence at runtime.
Testing (Runtime Tests)
Problems, causes, and effective fixes
-
Windows runner COMExceptions / missing WinUI theme resources
- Symptom:
Cannot locate resource from 'ms-appx:///Microsoft.UI.Xaml/Themes/themeresources.xaml'and control construction COMExceptions. - Cause: Build command disabled PRI/resource generation and copy (
AppxGeneratePriEnabled=false,IncludeCopyLocalFilesOutputGroup=false). - Fix: Keep
EnableCoreMrtTooling=false, but remove those two properties in the Windows runner build args so WinUI resources load.
- Symptom:
-
Flowery theme resources missing in runtime tests
- Symptom:
ms-appx:///Flowery.Uno/Themes/Generic.xamlnot found; Daisy brushes missing. - Cause: Runtime test output only had
Themes/at app root, notFlowery.Uno/Themes/(library layout path). - Fix: In
Flowery.Uno.Gallery.Windows/App.xaml.cs, whenisRuntimeTests:- Copy
Themes→Flowery.Uno/ThemesunderAppContext.BaseDirectory. - Load
ms-appx:///Flowery.Uno/Themes/Generic.xaml. - Still add
XamlControlsResources(log if it fails). - Call
EnsureGalleryResources(isRuntimeTests)before the runtime-test early return so resources exist during tests.
- Copy
- Symptom:
-
Runtime tests not picking up
--runtime-testsargs- Symptom: Test app runs but no results produced / hangs.
- Cause: Args not reliably passed when running the Windows app via test host.
- Fix: Add env var fallback:
FLOWERY_RUNTIME_TESTS_PATH.RuntimeTestArgumentschecks env var first.- Both Windows/Skia runners set
FLOWERY_RUNTIME_TESTS_PATH.
-
Windows runner launching the wrong host
- Symptom: Running
dotnet <dll>bypassed Windows app packaging behavior. - Fix: Prefer the
.exe(Path.ChangeExtension(TargetPath, ".exe")) when it exists.
- Symptom: Running
Correct setup snapshot
Flowery.Uno.RuntimeTeststargets:net9.0;net9.0-windows10.0.19041.- Windows runner build args:
-p:EnableCoreMrtTooling=false(do not disable PRI or copy-local outputs). - Windows runner execution: run the app
.exewhen available; always setFLOWERY_RUNTIME_TESTS_PATH. App.xaml.csfor Windows: load runtime-test resources before the early return; copyThemesintoFlowery.Uno/Themesfor ms-appx resolution.
✅ CI / GitHub Actions (Uno + gh CLI)
Uno templates (CI generation)
Uno project templates can generate CI pipelines:
dotnet new unoapp -ci github
dotnet new unoapp -ci azure
dotnet new unoapp -ci none
GitHub CLI (workflow operations)
# List workflows
gh workflow list
# Trigger a workflow (requires on: workflow_dispatch)
gh workflow run .github/workflows/ci.yml
# Watch a run
gh run watch <run-id>
# View run details / logs
gh run view <run-id> --log-failed
⭐ GOLD STANDARD: Button Icons via Attached Property
This is the official Uno.Themes pattern for adding icons to buttons. It avoids all UIElement parentage issues.
Why This Pattern?
- UIElements can only have ONE parent. Passing
PathIconasContentoften causes silent failures. - Attached properties allow the button to build its own icon presenter, avoiding parentage issues.
- Supports icon + text on the same button (not mutually exclusive).
- Foreground inheritance is handled correctly for different button variants/states.
Using DaisyControlExtensions.Icon (Recommended)
<!-- Icon-only button -->
<daisy:DaisyButton Shape="Circle" Variant="Primary">
<daisy:DaisyControlExtensions.Icon>
<PathIcon Width="16" Height="16" Data="M12 4.5v15m7.5-7.5h-15" />
</daisy:DaisyControlExtensions.Icon>
</daisy:DaisyButton>
<!-- Icon + text button -->
<daisy:DaisyButton Content="Save" Variant="Primary">
<daisy:DaisyControlExtensions.Icon>
<PathIcon Width="16" Height="16" Data="M..." />
</daisy:DaisyControlExtensions.Icon>
</daisy:DaisyButton>
<!-- Icon on the right side -->
<daisy:DaisyButton Content="Next">
<daisy:DaisyControlExtensions.Icon>
<PathIcon Data="M..." />
</daisy:DaisyControlExtensions.Icon>
<daisy:DaisyControlExtensions.IconPlacement>Right</daisy:DaisyControlExtensions.IconPlacement>
</daisy:DaisyButton>
Using TriggerIconData for DaisyFab (Best Practice)
For the FAB trigger button, use TriggerIconData (a string containing the path data). This is the safest approach because we create the PathIcon internally, completely avoiding UIElement parentage issues.
<daisy:DaisyFab TriggerVariant="Secondary" Size="Medium"
TriggerIconData="M12 4.5v15m7.5-7.5h-15"
TriggerIconSize="16">
<StackPanel>
<daisy:DaisyButton Shape="Circle">
<PathIcon Width="16" Height="16" Data="M3 9.5l9-7 9 7V20..." />
</daisy:DaisyButton>
</StackPanel>
</daisy:DaisyFab>
Available Attached Properties
| Property | Type | Default | Description |
| -------- | ---- | ------- | ----------- |
| DaisyControlExtensions.Icon | IconElement | null | The icon to display |
| DaisyControlExtensions.IconWidth | double | NaN | Explicit icon width (auto if NaN) |
| DaisyControlExtensions.IconHeight | double | NaN | Explicit icon height (auto if NaN) |
| DaisyControlExtensions.IconPlacement | IconPlacement | Left | Position: Left, Right, Top, Bottom |
| DaisyControlExtensions.IconSpacing | double | 8.0 | Spacing between icon and content |
| DaisyControlExtensions.AlternateContent | object | null | For toggle controls: content when checked |
Note: These properties use
[Bindable]and[DynamicDependency]attributes for proper XAML binding and AOT compilation safety, following the Uno.Themes pattern.
❌ DON'T: Set PathIcon as Direct Content
<!-- ❌ FAILS SILENTLY: PathIcon becomes child of DaisyButton,
then can't be re-parented to internal presenter -->
<daisy:DaisyButton Shape="Circle" Variant="Primary">
<PathIcon Data="M..." />
</daisy:DaisyButton>
✅ DO: Use the Attached Property Pattern
<!-- ✅ WORKS: Icon is picked up by button and placed in its own presenter -->
<daisy:DaisyButton Shape="Circle" Variant="Primary">
<daisy:DaisyControlExtensions.Icon>
<PathIcon Data="M..." />
Truncated for display — read the full file on GitHub.
Related Skills
last30days-skill
62.6kAI agent skill that researches any topic across Reddit, X, YouTube, HN, Polymarket, and the web - then synthesizes a grounded summary
AstrBot
40.8kAI Agent Assistant & development framework that integrates lots of IM platforms, LLMs, plugins and AI feature, and can be your openclaw alternative. ✨
learn-claude-code
77.4kBash is all you need - A nano claude code–like 「agent harness」, built from 0 to 1
wigolo
5.4kThe go-to web for your AI coding agent — local-first search, fetch, crawl & research over MCP. No API keys, no cloud, $0/query. Public beta.
Security Score
Audited on Jul 9, 2026
