diff --git a/Toolkit.UI.Controls.Avalonia/ContentBadge/ContentBadge.axaml b/Toolkit.UI.Controls.Avalonia/ContentBadge/ContentBadge.axaml
new file mode 100644
index 0000000..26b79d6
--- /dev/null
+++ b/Toolkit.UI.Controls.Avalonia/ContentBadge/ContentBadge.axaml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Toolkit.UI.Controls.Avalonia/ContentBadge/ContentBadge.cs b/Toolkit.UI.Controls.Avalonia/ContentBadge/ContentBadge.cs
new file mode 100644
index 0000000..2b0d87a
--- /dev/null
+++ b/Toolkit.UI.Controls.Avalonia/ContentBadge/ContentBadge.cs
@@ -0,0 +1,97 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
+using Avalonia.Media;
+using Path = Avalonia.Controls.Shapes.Path;
+
+namespace Toolkit.UI.Controls.Avalonia;
+
+public class ContentBadge :
+ ContentControl
+{
+ public static readonly StyledProperty BadgePathProperty =
+ AvaloniaProperty.Register(nameof(BadgePath));
+
+ public static readonly StyledProperty BadgeSizeProperty =
+ AvaloniaProperty.Register(nameof(BadgeSize), 14);
+
+ private ContentControl? badgeContent;
+
+ public string? BadgePath
+ {
+ get => GetValue(BadgePathProperty);
+ set => SetValue(BadgePathProperty, value);
+ }
+
+ public double BadgeSize
+ {
+ get => GetValue(BadgeSizeProperty);
+ set => SetValue(BadgeSizeProperty, value);
+ }
+
+ public void UpdateClip()
+ {
+ if (Content is Control content &&
+ badgeContent is not null &&
+ BadgePath is { Length: > 0 } &&
+ Geometry.Parse(BadgePath) is Geometry geometry)
+ {
+ double backgroundWidth = DesiredSize.Width;
+ double backgroundHeight = DesiredSize.Height;
+
+ double scaleX = BadgeSize / geometry.Bounds.Width;
+ double scaleY = BadgeSize / geometry.Bounds.Height;
+
+ double adjustedStrokeWidth = Math.Min(scaleX, scaleY) * 8;
+
+ Geometry knockoutGeometry = geometry.GetWidenedGeometry(new Pen(new SolidColorBrush(Colors.Transparent), adjustedStrokeWidth);
+
+ TransformGroup transformGroup = new();
+ transformGroup.Children.Add(new ScaleTransform(scaleX, scaleY));
+
+ double scaledWidth = knockoutGeometry.Bounds.Width * scaleX;
+ double scaledHeight = knockoutGeometry.Bounds.Height * scaleY;
+ double offsetX = backgroundWidth - scaledWidth;
+ double offsetY = backgroundHeight - scaledHeight;
+
+ transformGroup.Children.Add(new TranslateTransform(offsetX, offsetY));
+ knockoutGeometry.Transform = transformGroup;
+
+ CombinedGeometry combinedGeometry = new()
+ {
+ GeometryCombineMode = GeometryCombineMode.Exclude,
+ Geometry1 = new RectangleGeometry { Rect = new Rect(0, 0, backgroundWidth, backgroundHeight) },
+ Geometry2 = knockoutGeometry
+ };
+
+ content.Clip = combinedGeometry;
+
+ Geometry overlayGeometry = geometry.Clone();
+
+ TransformGroup overlayTransformGroup = new();
+ overlayTransformGroup.Children.Add(new ScaleTransform(scaleX, scaleY));
+
+ overlayTransformGroup.Children.Add(new TranslateTransform(offsetX, offsetY));
+ overlayGeometry.Transform = overlayTransformGroup;
+
+ badgeContent.Content = new Path
+ {
+ Data = overlayGeometry,
+ Fill = Foreground
+ };
+ }
+ }
+
+ protected override void OnApplyTemplate(TemplateAppliedEventArgs args)
+ {
+ base.OnApplyTemplate(args);
+ badgeContent = args.NameScope.Get("BadgeContent");
+ }
+
+ protected override void OnSizeChanged(SizeChangedEventArgs args)
+ {
+ base.OnSizeChanged(args);
+ UpdateClip();
+ }
+}
+
diff --git a/Toolkit.UI.Controls.Avalonia/Overflow/Overflow.cs b/Toolkit.UI.Controls.Avalonia/Overflow/Overflow.cs
index e6a0754..a8f2b9d 100644
--- a/Toolkit.UI.Controls.Avalonia/Overflow/Overflow.cs
+++ b/Toolkit.UI.Controls.Avalonia/Overflow/Overflow.cs
@@ -84,16 +84,10 @@ public class Overflow :
base.OnApplyTemplate(args);
primaryListBox = args.NameScope.Get("PrimaryListBox");
- if (primaryListBox is not null)
- {
- primaryListBox.SetValue(ItemsControl.ItemsSourceProperty, primaryCollection);
- }
+ primaryListBox?.SetValue(ItemsControl.ItemsSourceProperty, primaryCollection);
secondaryListBox = args.NameScope.Get("SecondaryListBox");
- if (secondaryListBox is not null)
- {
- secondaryListBox.SetValue(ItemsControl.ItemsSourceProperty, secondaryCollection);
- }
+ secondaryListBox?.SetValue(ItemsControl.ItemsSourceProperty, secondaryCollection);
InitializeCollections();
UpdateOverflow();
diff --git a/Toolkit.UI.Controls.Avalonia/Themes/ControlResources.axaml b/Toolkit.UI.Controls.Avalonia/Themes/ControlResources.axaml
index 196bb1a..b943686 100644
--- a/Toolkit.UI.Controls.Avalonia/Themes/ControlResources.axaml
+++ b/Toolkit.UI.Controls.Avalonia/Themes/ControlResources.axaml
@@ -7,6 +7,7 @@
+