Skip to content

Fix Shell.Background not working#35491

Draft
HarishwaranVijayakumar wants to merge 7 commits into
dotnet:net11.0from
HarishwaranVijayakumar:fix-shellbackground
Draft

Fix Shell.Background not working#35491
HarishwaranVijayakumar wants to merge 7 commits into
dotnet:net11.0from
HarishwaranVijayakumar:fix-shellbackground

Conversation

@HarishwaranVijayakumar

Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Issue Details:

  • Setting a brush via Shell.Background (like LinearGradientBrush) on Shell's navigation bar doesn't work. Only solid colors via Shell.BackgroundColor were supported.

Root Cause of the issue

  • Shell only had BackgroundColor (solid colors), no Brush property for gradients
  • Android: SetColors() only accepted Color; tint settings blocked gradient rendering
  • iOS: Only checked BackgroundColor, ignored Brush backgrounds

Description of Change

Feature: Shell Toolbar Gradient Background Support

  • Added a new Background bindable property to Shell, enabling the use of any Brush (including gradients) as the toolbar background. This is now available as a public API and is reflected in the ShellAppearance class.
    Platform Rendering Updates
  • Updated Android and iOS Shell toolbar appearance trackers to use the new Background brush property if set, falling back to the legacy background color otherwise. This ensures gradient and other brush types are rendered correctly. [

Testing

  • Added a new sample test case (Issue10445) and a corresponding UI test to verify that setting a gradient brush as the Shell background works as expected.

Issues Fixed

Fixes #10445

Tested the behaviour in the following platforms

  • - Windows
  • - Android
  • - iOS
  • - Mac
Platform Before After
Android
iOS
Mac
Windows

@github-actions

github-actions Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35491

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35491"

@dotnet-policy-service dotnet-policy-service Bot added the community ✨ Community Contribution label May 18, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hey there @@HarishwaranVijayakumar! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label May 18, 2026
@kubaflo

kubaflo commented May 21, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/regression-check -p ios

@MauiBot MauiBot added s/agent-review-incomplete s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels May 21, 2026
@kubaflo

kubaflo commented May 24, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/refactor-copilot-yml

@MauiBot

MauiBot commented May 24, 2026

Copy link
Copy Markdown
Collaborator

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

@HarishwaranVijayakumar HarishwaranVijayakumar changed the title [WIP] Fix Shell.Background not working Fix Shell.Background not working May 25, 2026
@dotnet dotnet deleted a comment from MauiBot May 25, 2026

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, this should probably target main

@HarishwaranVijayakumar

Copy link
Copy Markdown
Contributor Author

Hi, this should probably target main

Since this PR includes public API changes that could break custom Shell scenarios, it would be better to target net11 rather than main.

@kubaflo

kubaflo commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

AI code review for net11.0 target

Verdict: Needs discussion (draft; new public API design)

Draft PR adding gradient/Brush support for the Shell toolbar background. It introduces a new public attached property Shell.Background (Brush), ingests it into ShellAppearance, and threads a Brush (instead of Color) through the Android/iOS toolbar appearance trackers.

Main discussion point (API design)

  • Shell.BackgroundProperty is declared as public static readonly new BindableProperty — the new hides the inherited VisualElement.BackgroundProperty. The result is two same-named concepts on Shell: the inherited instance Background (from VisualElement) and a new attached Shell.GetBackground/SetBackground, with different storage and semantics. This is confusing and is exactly the kind of overlap that warrants API review before it ships, even on net11.0. Consider whether reusing/honoring the existing VisualElement.Background, or a differently-named property (e.g. a Shell-specific toolbar background), would be cleaner.
  • New public API is correctly recorded across all TFM PublicAPI.Unshipped.txt files and the Android SetColors signature change is tracked with a *REMOVED*/added pair — mechanically consistent.

Code notes (non-blocking)

  • ToolbarExtensions.UpdateBarBackground now unconditionally clears BackgroundTintMode/BackgroundTintList before UpdateBackground. Previously the tint-mode was only cleared when the brush was null/empty. Double-check this doesn't regress solid-color toolbar tinting in non-Shell toolbars that share this extension.
  • iOS path correctly distinguishes SolidColorBrush (→ BackgroundColor) from gradient brushes (→ GetBackgroundImageBackgroundImage); reasonable.
  • Tests rely on VerifyScreenshot() snapshots for Android/iOS — appropriate for a visual gradient feature.

CI: maui-pr plus shared AOT macOS/RunOniOS_* integration legs are failing; the iOS ones also fail on unrelated PRs in this batch (infra/known), while the Helix Windows Debug failure should be checked by a maintainer. Given draft status, settle the API-design question first.

Confidence: Medium — limited by draft status and the unresolved public-API design.

Automated, non-approval review comment from the net11.0 fleet reviewer. Not a substitute for human approval.

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #35491 — Multi-model synthesis (Shell.Background gradient brush, issue #10445)

Verdict: NEEDS_DISCUSSION — confidence: medium

Note (why split, and how it resolved)

Models split 2 NEEDS_CHANGES (gpt-5.5, gemini) vs 2 NEEDS_DISCUSSION (opus-4.6, opus-4.8). Checking the actual code, the NC drivers soften: the net-tizen "API-validation build would fail" premise is moot (Tizen is hard-disabled in CI), and the Android SetColors signature break is intentional, net11-targeted and *REMOVED*-tracked (a tradeoff, not a defect). The dominant, genuinely unresolved item is the public-API design of the new Shell.BackgroundProperty shadowing VisualElement.BackgroundProperty — an open design question on a DRAFT PR with failing CI — so NEEDS_DISCUSSION is the correct synthesis (you cannot meaningfully "request changes" before the API shape is settled).

Key findings (validated against code at 91c101f)

  • [ND — dominant, already in discussion] new shadowing of VisualElement.BackgroundProperty. Shell.cs declares public static readonly new BindableProperty BackgroundProperty as an attached Brush property, while VisualElement.BackgroundProperty (instance, name "Background", also Brush) remains inherited. Only the attached property is ingested into ShellAppearance (s_ingestBrushArray). Concrete divergence: XAML Background="…" and Shell.SetBackground(shell, …) hit the attached property → reaches the toolbar; code-behind shell.Background = … hits the inherited VisualElement property → does NOT reach the toolbar (paints the Shell body instead). Same name, two behaviors — a real footgun. Resolution is an API-design decision (rename to a Shell/toolbar-specific name, or reuse VisualElement.Background). Already covered in the net11 fleet-review comment, so not re-posted inline.
  • [warning — inline] iOS translucency ignores brush alpha (ShellNavBarAppearanceTracker.cs). Translucency is decided from appearance.BackgroundColor?.Alpha before the new brush branch; a transparent brush with null BackgroundColor falls to ConfigureWithOpaqueBackground() + Translucent=false, so a semi-transparent Shell.Background renders opaque (3-model consensus: opus-4.8, opus-4.6, gemini). Edge case — opaque gradients are unaffected.
  • [suggestion — inline] Android SetColors is binary/source-breaking for subclassers (ShellToolbarAppearanceTracker.cs). Intentional and PublicAPI-tracked for net11.0; flagged so API review can confirm the break and the silent override-resolution change.
  • [warning — inline] Test lacks Windows/Mac baselines (Issue10445.cs). VerifyScreenshot() throws on a missing baseline; the fixture runs on Mac/Windows and only android+ios baselines were committed, so the test will fail on those legs even though the fix targets Windows + Mac.
  • [minor — summary only] net-tizen PublicAPI not updated. The 6 built TFMs are correctly updated; net-tizen is omitted. It will NOT fail CI (IncludeTizenTargetFrameworks=false, "Disabled until net10.0-tizen is available"), but net-tizen is otherwise kept in sync (e.g. 29 LongPress entries match net), so the 4 shared-core entries (ShellAppearance.Background, Shell.GetBackground/SetBackground/BackgroundProperty) should be added for consistency when Tizen is re-enabled. Not inlineable (file not in diff).
  • [dropped] iOS pre-13 UpdateNavigationBarAppearance ignores the brush, but it is gated on !IsIOSVersionAtLeast(13) — below the supported deployment floor, effectively dead. Negligible.
  • [verified OK] Android ToolbarExtensions.UpdateBarBackground now clears BackgroundTintMode/BackgroundTintList before UpdateBackground on the non-SolidColorBrush path — this is the actual Android root-cause fix (stale tint was blocking gradients); SolidColorBrush still takes the tint path, so no regression.

CI

PR-failing: maui-pr plus AOT macOS and several RunOniOS_MauiRelease* integration legs (iOS legs also fail on unrelated PRs in this batch — likely infra/known); the Helix Windows Debug unit-test failure should be checked by a maintainer. Draft + failing CI + unresolved public-API design ⇒ settle the API question first.

if (background != null)
navigationBarAppearance.BackgroundColor = background.ToPlatform();
// Set Background (prefer Brush over Color for gradient support)
if (!Brush.IsNullOrEmpty(appearance.Background))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The translucency decision a few lines above (if (appearance.BackgroundColor?.Alpha < 1.0f)) only inspects BackgroundColor. When the toolbar background comes solely from this new appearance.Background brush, BackgroundColor is null, so null < 1.0f is false and the bar is configured with ConfigureWithOpaqueBackground() + Translucent = false. A semi-transparent brush (a SolidColorBrush, or a gradient stop with alpha < 1) set via Shell.Background therefore renders opaque, unlike the same alpha set via Shell.BackgroundColor. Consider folding the brush's effective alpha into the translucency check. Opaque gradients (the primary scenario for this PR) are unaffected.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This matches the existing NavigationRenderer behavior, where translucency is also driven by color alpha and brush backgrounds are applied afterward (see NavigationRenderer.cs:881 and NavigationRenderer.cs:896).
For this PR, the main target is opaque gradients, which are unaffected. If we want to support semi-transparent brush parity with BackgroundColor, we can handle brush alpha in a follow-up

}

protected virtual void SetColors(AToolbar toolbar, IShellToolbarTracker toolbarTracker, Color foreground, Color background, Color title)
protected virtual void SetColors(AToolbar toolbar, IShellToolbarTracker toolbarTracker, Color foreground, Brush background, Color title)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes the protected virtual signature from Color background to Brush background. It is correctly tracked in PublicAPI with a *REMOVED*/added pair and is reasonable for the net11.0 target, but it is binary/source-breaking for subclasses that override the old Color overload: after this change SetAppearance calls the Brush overload, so an existing override of the Color overload silently stops being invoked. Worth confirming during API review that dropping the old overload (vs. keeping it as an [Obsolete] overload that delegates to the new one) is the intended net11 break — this is the kind of decision that pairs with the broader Shell.Background API-design discussion on this PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for flagging this! Yes, this is an intentional change for .NET 11 — we've updated the signature from Color to Brush to enable gradient background support. It's properly tracked in PublicAPI.Unshipped.txt with the REMOVED/added pair. For anyone with a custom subclass overriding the old Color overload, the migration is straightforward — just update the parameter type to Brush. Happy to discuss further if there are concerns!

App.WaitForElement("GradientInfoLabel");

// Verify the Shell renders correctly with a gradient background
VerifyScreenshot();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VerifyScreenshot() fails when no baseline exists for the running platform — VisualRegressionTester.VerifyMatchesSnapshot throws VisualTestFailedException ("Baseline snapshot not yet created") when the file is missing. This fixture also runs on Mac and Windows ([TestFixture(TestDevice.Mac)] / [TestFixture(TestDevice.Windows)] in UITest.cs) and the test is not platform-scoped, but the PR only commits android + ios baselines. Since the fix explicitly targets Windows and Mac (per the PR description), this test will fail on the Mac/Windows UI legs for lack of a baseline. Note TestCases.WinUI.Tests/snapshots/windows and TestCases.Mac.Tests/snapshots/mac already hold ~1.4k baselines each, so all-platform baselines are the convention.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add the Windows and Mac baseline images once CI is triggered.

@vishnumenon2684

Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cross-model synthesis — PR #35491

"Fix Shell.Background not working" — HarishwaranVijayakumar — base net11.0DRAFT
HEAD: af58706bc5286886ebf55c0c25071e4dea984bbd
Fixes #10445 (community / partner-syncfusion).

Verdict: NEEDS_CHANGES (confidence: medium)

Four independent model reviews (gemini-3.1-pro-preview, gpt-5.5, claude-opus-4.6, claude-opus-4.8)
were validated line-by-line against HEAD. 5 findings survived validation with 0 false
positives:
1 error, 3 warnings, 1 suggestion. The error (missing Windows/Mac screenshot
baselines) is code- and CI-verified and triggers NEEDS_CHANGES under the "any validated error"
rule. The strategically dominant issue, however, is the unresolved public-API design
(new Shell.BackgroundProperty), which is NEEDS_DISCUSSION-flavored — hence the 2/2 per-model
split and medium confidence.

This PR adds a new attached Shell.Background (Brush) property, ingests it into ShellAppearance,
and threads a Brush (instead of Color) through the Android and iOS Shell toolbar appearance
trackers so gradient brushes render in the navigation bar. The core rendering logic and the fallback
to BackgroundColor are correct.


❌ Blocking (1)

1. New VerifyScreenshot() test has no Windows/Mac baseline — Issue10445.cs:23

ShellBackgroundSupportsGradientBrush (TestCases.Shared.Tests) calls VerifyScreenshot() with
[Category(UITestCategories.Shell)] and no platform exclusion, so it runs on every UI-test
platform. Only the android and ios baselines were committed. Verified at HEAD af58706b: there
is no TestCases.WinUI.Tests/snapshots/windows/ShellBackgroundSupportsGradientBrush.png and
no TestCases.Mac.Tests/snapshots/mac/..., while both snapshots/windows and snapshots/mac
directories already exist (shipping those baselines is the established convention). A missing
baseline makes VerifyScreenshot fail, so the test fails on the Windows and Mac Shell legs —
corroborated by the red maui-pr-uitests (WinUI UITests Controls Shell) leg on this build. The PR
description claims Windows/Mac were tested, but no baseline backs that. Fix: commit the windows/mac
baselines, or exclude those platforms if the feature is not yet supported there.
(found by: claude-opus-4.8)


⚠️ Warnings (3)

2. new Shell.BackgroundProperty shadows VisualElement.BackgroundPropertyShell.cs:535 (dominant design question)

Shell.cs:535 declares public static readonly new BindableProperty BackgroundProperty as an
attached Brush property, while Shell still inherits the instance VisualElement.Background
(VisualElement.cs:289/:569, also a Brush named "Background"). Only the attached property is
ingested into ShellAppearance (s_ingestBrushArray). Concrete footgun verified at HEAD:
Shell.SetBackground(shell, brush) / XAML Background="…" write the attached property → reach
the toolbar; shell.Background = brush in code-behind writes the inherited VisualElement
property → does not reach the toolbar (it paints the Shell body). Same name, two storages, two
behaviors. This is already raised in the PR discussion and a prior net11 fleet-review and is the
primary verdict driver for gpt-5.5 and claude-opus-4.6. It is an API-design decision that should go
through API review before shipping (even on net11.0): honor/reuse VisualElement.Background, or
rename to a toolbar-specific member.
(found by: gpt-5.5, claude-opus-4.6, claude-opus-4.8)

3. iOS navbar translucency ignores the brush alpha — ShellNavBarAppearanceTracker.cs:135

Translucency is decided at line 111 from appearance.BackgroundColor?.Alpha < 1.0f, before the
new brush branch at line 135. When only Shell.Background is set, BackgroundColor is null, so
null < 1.0f is false → the navbar is configured with ConfigureWithOpaqueBackground() and
Translucent = false. The brush is then applied over an already-opaque appearance, so a
semi-transparent SolidColorBrush or a gradient with transparent stops renders opaque. Opaque
gradients (e.g. the test's Yellow→Green) are unaffected. Fix: factor brush alpha into the
translucency decision (e.g. Brush.HasTransparency(appearance.Background)).
(found by: gemini-3.1-pro-preview, claude-opus-4.8)

4. SetColors break to a shipped protected virtual API — ShellToolbarAppearanceTracker.cs:39

The signature changes from Color background to Brush background. Verified at HEAD: the old
Color overload is in PublicAPI.Shipped.txt (net-android line 4422); the PR removes it via
*REMOVED* and adds the Brush overload in PublicAPI.Unshipped.txt. Subclasses that override
SetColors will no longer compile or will silently stop being called. This is intentional,
net11.0-targeted and PublicAPI-tracked (the author explicitly chose net11.0 for this break), so
it is a heads-up for API-review sign-off rather than a defect. If avoiding the break is preferred,
keep the Color overload and add a separate Brush virtual that SetAppearance calls, with the
legacy overload delegating to it.
(found by: gemini-3.1-pro-preview, claude-opus-4.8)

Severity reconciliation: gemini graded #4 an error and claude-opus-4.8 a suggestion. On
validation it is a genuine break (so not a false positive) but intentional and correctly tracked
on the branch where breaks are allowed — synthesized to warning (API-review sign-off).


💡 Suggestion (1)

5. Gradient rendered to a fixed-size image, not refreshed on rotation — ShellNavBarAppearanceTracker.cs:143

For non-solid brushes the iOS path renders the gradient to a UIImage at the nav bar's current
bounds via navBar.GetBackgroundImage(appearance.Background) and assigns it to
navigationBarAppearance.BackgroundImage. SetAppearance is only re-invoked on Shell appearance
property changes, not on layout/orientation changes, so a rotation can stretch/distort the
pre-rendered gradient. This mirrors ShellFlyoutContentRenderer.UpdateBackground, so it may be an
acceptable limitation, but the toolbar width changes more visibly on rotation than the flyout.
(found by: claude-opus-4.6)


Why NEEDS_CHANGES rather than NEEDS_DISCUSSION

The strongest strategic signal (3 of 4 models + the PR discussion) is the unresolved
new-shadowing API design — a NEEDS_DISCUSSION concern. But there is also a concrete, independently
verified Error (missing Windows/Mac baselines → deterministic CI failure, with the WinUI Shell
leg actually red), which mandates NEEDS_CHANGES under the verdict rules. Both must be addressed:
settle the API shape first (it changes the test/baselines), then land the missing baselines or
platform exclusions. The draft status is consistent with this not yet being merge-ready.

CI status (context, not a standalone finding)

maui-pr is failing, and maui-pr-uitests shows the WinUI / Android / iOS Controls Shell legs
red — consistent with the new Shell screenshot test. Some other red legs (e.g. integration
AOT macOS, RunOniOS_*, unrelated Android category legs, macOS WebView) overlap with known/infra
failures seen on sibling PRs and are not attributed to this change.

Per-model verdicts

model verdict confidence contribution
gemini-3.1-pro-preview NEEDS_CHANGES high #4 Android break (as error), #3 iOS translucency
claude-opus-4.8 NEEDS_CHANGES high #1 missing baselines (error), #3 translucency, #4 break, #2 design
gpt-5.5 NEEDS_DISCUSSION low #2 public-API shape (no inline findings); CI red
claude-opus-4.6 NEEDS_DISCUSSION medium #5 gradient orientation; #2 design

Not re-raised in inline findings (context only)

  • A prior net11 fleet-review flagged that ToolbarExtensions.UpdateBarBackground now
    unconditionally clears BackgroundTintMode/BackgroundTintList before UpdateBackground
    (previously only when the brush was null/empty). None of the four current models raised it, so it
    is left out of the synthesized findings; a maintainer may still want to confirm it does not
    regress solid-color tinting for non-Shell toolbars that share this extension.
  • net-tizen PublicAPI.Unshipped.txt is not updated (only the 6 built TFMs are). Tizen is disabled
    in CI, so this will not fail the build; noted for completeness.

Validation method

Each finding was re-checked against HEAD with git show af58706bc5286886ebf55c0c25071e4dea984bbd:<path>
and against the PR diff; anchor line numbers (Issue10445.cs:23, Shell.cs:535,
ShellNavBarAppearanceTracker.cs:111/135/143, ShellToolbarAppearanceTracker.cs:39,
PublicAPI.Shipped.txt:4422, VisualElement.cs:289/569) were all confirmed. No working-tree files
were modified.

Data-location note

The prompt referenced files/reviews/pr-35491/, which did not exist under the cwd. The live 4-model
input set was located in session-state 0330ad36-…/files/reviews/pr-35491/ (fresh model-*.json
dated 2026-06-18; stale derived outputs dated 2026-06-14 reviewed an older head 91c101f). This
synthesis was performed against that actual data and mirrored to both that directory and the cwd
files/reviews/pr-35491/.

App.WaitForElement("GradientInfoLabel");

// Verify the Shell renders correctly with a gradient background
VerifyScreenshot();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error: New VerifyScreenshot() UI test ships only android+ios baselines — it fails on the Windows and Mac Shell legs

ShellBackgroundSupportsGradientBrush (added in this PR) calls VerifyScreenshot() with [Category(UITestCategories.Shell)] and no platform exclusion (Issue10445.cs lines 15-23), so it runs on every UI-test platform. Only the android and ios snapshots were committed (TestCases.Android.Tests/snapshots/android/ShellBackgroundSupportsGradientBrush.png, TestCases.iOS.Tests/snapshots/ios/ShellBackgroundSupportsGradientBrush.png).

Verified at HEAD af58706b: there is no TestCases.WinUI.Tests/snapshots/windows/ShellBackgroundSupportsGradientBrush.png and no TestCases.Mac.Tests/snapshots/mac/ShellBackgroundSupportsGradientBrush.png, while both the snapshots/windows and snapshots/mac directories already exist (the established convention is to ship those baselines). A missing baseline makes VerifyScreenshot fail, so this test fails on the Windows and Mac Shell legs — consistent with the red maui-pr-uitests (WinUI UITests Controls Shell) leg on this build. The PR description claims the feature was tested on Windows and Mac, but no baseline backs that.

Fix: commit the windows and mac baselines, or explicitly exclude Windows/Mac from this test if the feature is not yet supported there.

(found by: claude-opus-4.8)

/// <summary>
/// Defines the background brush for the Shell toolbar. Supports gradient brushes.
/// </summary>
public static readonly new BindableProperty BackgroundProperty =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Warning: new Shell.BackgroundProperty shadows the inherited VisualElement.BackgroundProperty — two same-named properties with different semantics (API design — needs review)

Shell.cs:535 declares public static readonly new BindableProperty BackgroundProperty as an attached Brush property, while Shell still inherits the instance VisualElement.Background (VisualElement.cs:289/:569, also a Brush named "Background"). Only the new attached property is ingested into ShellAppearance (ShellAppearance.cs s_ingestBrushArray).

Concrete footgun verified at HEAD: Shell.SetBackground(shell, brush) and XAML Background="…" write the attached property → reaches the toolbar; shell.Background = brush in code-behind writes the inherited VisualElement property → does not reach the toolbar (it paints the Shell body). Same name, two storages, two behaviors.

This is the dominant unresolved item on the PR (already raised in the PR discussion and a prior net11 fleet-review). It is an API-design decision that should go through API review before shipping, even on net11.0. Consider honoring/reusing VisualElement.Background, or naming the new member something toolbar-specific to remove the overlap.

(found by: gpt-5.5, claude-opus-4.6, claude-opus-4.8)

if (background != null)
navigationBarAppearance.BackgroundColor = background.ToPlatform();
// Set Background (prefer Brush over Color for gradient support)
if (!Brush.IsNullOrEmpty(appearance.Background))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Warning: iOS navbar translucency ignores the Shell.Background brush alpha — transparent brushes render opaque

In UpdateiOS13NavigationBarAppearance, translucency is decided at ShellNavBarAppearanceTracker.cs:111 from appearance.BackgroundColor?.Alpha < 1.0f, before the new brush branch here at line 135. When only Shell.Background is set, appearance.BackgroundColor is null, so null < 1.0f evaluates to false → the navbar is configured with ConfigureWithOpaqueBackground() and Translucent = false. The brush is then applied (solid → BackgroundColor, gradient → BackgroundImage) on top of an already-opaque appearance, so a semi-transparent SolidColorBrush or a gradient with transparent stops renders opaque. Opaque gradients (e.g. the test's Yellow→Green) are unaffected.

Fix: factor the brush alpha into the translucency decision (e.g. Brush.HasTransparency(appearance.Background), or inspect solidBrush.Color.Alpha / gradient stops) before choosing opaque vs. transparent.

(found by: gemini-3.1-pro-preview, claude-opus-4.8)

}

protected virtual void SetColors(AToolbar toolbar, IShellToolbarTracker toolbarTracker, Color foreground, Color background, Color title)
protected virtual void SetColors(AToolbar toolbar, IShellToolbarTracker toolbarTracker, Color foreground, Brush background, Color title)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Warning: SetColors signature change is a binary/source-breaking change to a shipped protected virtual API (intentional — confirm API-review sign-off)

This changes the shipped protected virtual void SetColors(…, Color background, …) to take a Brush background. Verified at HEAD: the old Color-based overload is in PublicAPI.Shipped.txt (net-android line 4422), and the PR removes it via *REMOVED* and adds the Brush overload in PublicAPI.Unshipped.txt. External code that subclasses ShellToolbarAppearanceTracker and overrides SetColors will no longer compile, or its override will silently stop being called.

This is intentional and correctly tracked, targets net11.0 (where breaks are allowed), and the author explicitly chose net11.0 for this reason — so it is a heads-up for API-review sign-off, not a code defect. If avoiding the break is preferred, keep the Color overload and add a separate Brush-based virtual that SetAppearance calls, with the legacy overload delegating to it.

(found by: gemini-3.1-pro-preview, claude-opus-4.8)

}
else
{
var backgroundImage = navBar.GetBackgroundImage(appearance.Background);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Suggestion: Gradient navbar background is rendered to a fixed-size image and not refreshed on rotation/resize

For non-solid brushes the iOS path renders the gradient to a UIImage sized to the nav bar's current bounds via navBar.GetBackgroundImage(appearance.Background) (line 143) and assigns it to navigationBarAppearance.BackgroundImage. SetAppearance is only re-invoked when Shell appearance properties change, not on layout/orientation changes, so rotating the device can stretch or distort the pre-rendered gradient until appearance is re-applied. This mirrors ShellFlyoutContentRenderer.UpdateBackground, so it may be an acceptable limitation, but the toolbar width changes more visibly on rotation than the flyout. Consider a frame-change observer/override to re-render the gradient on bounds changes.

(found by: claude-opus-4.6)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants