diff --git a/samples/XCT.Sample/Pages/Effects/CornerRadiusEffectPage.xaml b/samples/XCT.Sample/Pages/Effects/CornerRadiusEffectPage.xaml
new file mode 100644
index 000000000..b7a2ebe72
--- /dev/null
+++ b/samples/XCT.Sample/Pages/Effects/CornerRadiusEffectPage.xaml
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/XCT.Sample/Pages/Effects/CornerRadiusEffectPage.xaml.cs b/samples/XCT.Sample/Pages/Effects/CornerRadiusEffectPage.xaml.cs
new file mode 100644
index 000000000..37e17ff04
--- /dev/null
+++ b/samples/XCT.Sample/Pages/Effects/CornerRadiusEffectPage.xaml.cs
@@ -0,0 +1,27 @@
+using Xamarin.Forms;
+
+namespace Xamarin.CommunityToolkit.Sample.Pages.Effects
+{
+ public partial class CornerRadiusEffectPage
+ {
+ public CornerRadiusEffectPage()
+ {
+ InitializeComponent();
+
+ SliderCornerRadiusTopLeft.ValueChanged += OnCornerRadiusValueChanged;
+ SliderCornerRadiusTopRight.ValueChanged += OnCornerRadiusValueChanged;
+ SliderCornerRadiusBottomLeft.ValueChanged += OnCornerRadiusValueChanged;
+ SliderCornerRadiusBottomRight.ValueChanged += OnCornerRadiusValueChanged;
+ }
+
+ void OnCornerRadiusValueChanged(object sender, ValueChangedEventArgs e)
+ {
+ CornerRadius = new CornerRadius(
+ SliderCornerRadiusTopLeft.Value, SliderCornerRadiusTopRight.Value,
+ SliderCornerRadiusBottomLeft.Value, SliderCornerRadiusBottomRight.Value);
+ OnPropertyChanged(nameof(CornerRadius));
+ }
+
+ public CornerRadius CornerRadius { get; private set; } = new (10);
+ }
+}
\ No newline at end of file
diff --git a/samples/XCT.Sample/ViewModels/Effects/EffectsGalleryViewModel.cs b/samples/XCT.Sample/ViewModels/Effects/EffectsGalleryViewModel.cs
index fe74f2616..309f609ce 100644
--- a/samples/XCT.Sample/ViewModels/Effects/EffectsGalleryViewModel.cs
+++ b/samples/XCT.Sample/ViewModels/Effects/EffectsGalleryViewModel.cs
@@ -50,6 +50,11 @@ protected override IEnumerable CreateItems() => new[]
"The SemanticEffect allows you to set semantic properties for accessibility."),
new SectionModel(
+ typeof(CornerRadiusEffectPage),
+ nameof(CornerRadiusEffect),
+ "The CornerRadius allows rounded corners everywhere."),
+
+ new SectionModel(
typeof(StatusBarEffectPage),
nameof(StatusBarEffect),
"The StatusBar allows to change status bar color and style. This page also demonstrates Android only NavigationBar changes.")
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/CornerRadius/CornerRadiusEffect.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/CornerRadius/CornerRadiusEffect.shared.cs
new file mode 100644
index 000000000..1ea6c9a29
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/CornerRadius/CornerRadiusEffect.shared.cs
@@ -0,0 +1,83 @@
+using System;
+using Xamarin.Forms;
+using Xamarin.Forms.Shapes;
+
+namespace Xamarin.CommunityToolkit.Effects
+{
+ public class CornerRadiusEffect
+ {
+ public static readonly BindableProperty CornerRadiusProperty = BindableProperty.CreateAttached(
+ nameof(CornerRadius),
+ typeof(CornerRadius),
+ typeof(CornerRadiusEffect),
+ default(CornerRadius),
+ propertyChanged: OnCornerRadiusPropertyChanged);
+
+ static void OnCornerRadiusPropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ if (bindable is not VisualElement elementView)
+ return;
+
+ elementView.SizeChanged -= ElementViewSizeChanged;
+ elementView.SizeChanged += ElementViewSizeChanged;
+
+ UpdateClip(elementView);
+ }
+
+ static void ElementViewSizeChanged(object? sender, EventArgs e)
+ {
+ if (sender == null)
+ return;
+
+ UpdateClip((VisualElement)sender);
+ }
+
+ public static CornerRadius GetCornerRadius(BindableObject? bindable)
+ => (CornerRadius)(bindable?.GetValue(CornerRadiusProperty) ?? throw new ArgumentNullException(nameof(bindable)));
+
+ public static void SetCornerRadius(BindableObject? bindable, CornerRadius value)
+ => bindable?.SetValue(CornerRadiusProperty, value);
+
+ static void UpdateClip(VisualElement elementView)
+ {
+ var rect = new Rect(0, 0, elementView.Width, elementView.Height);
+ var cornerRadius = GetCornerRadius(rect, elementView);
+ if (cornerRadius == default)
+ {
+ elementView.Clip = null;
+ return;
+ }
+
+ if (elementView.Clip is not RoundRectangleGeometry roundRectangleGeometry)
+ {
+ elementView.Clip = new RoundRectangleGeometry(cornerRadius, rect);
+ return;
+ }
+
+ roundRectangleGeometry.CornerRadius = cornerRadius;
+ roundRectangleGeometry.Rect = rect;
+ }
+
+ static CornerRadius GetCornerRadius(Rect rect, VisualElement elementView)
+ {
+ var maxCornerRadius = Math.Min(rect.Width, rect.Height) / 2;
+ if (maxCornerRadius <= 0)
+ return default;
+
+ var cornerRadius = GetCornerRadius(elementView);
+ if (cornerRadius.TopLeft > maxCornerRadius ||
+ cornerRadius.TopRight > maxCornerRadius ||
+ cornerRadius.BottomLeft > maxCornerRadius ||
+ cornerRadius.BottomRight > maxCornerRadius)
+ {
+ return new CornerRadius(
+ Math.Min(cornerRadius.TopLeft, maxCornerRadius),
+ Math.Min(cornerRadius.TopRight, maxCornerRadius),
+ Math.Min(cornerRadius.BottomLeft, maxCornerRadius),
+ Math.Min(cornerRadius.BottomRight, maxCornerRadius));
+ }
+
+ return cornerRadius;
+ }
+ }
+}