diff --git a/demo/Semi.Avalonia.Demo/App.axaml b/demo/Semi.Avalonia.Demo/App.axaml
index 1e0383a..c3605fa 100644
--- a/demo/Semi.Avalonia.Demo/App.axaml
+++ b/demo/Semi.Avalonia.Demo/App.axaml
@@ -7,6 +7,7 @@
+
diff --git a/src/Semi.Avalonia/Animations/SemiPopupAnimations.axaml b/src/Semi.Avalonia/Animations/SemiPopupAnimations.axaml
new file mode 100644
index 0000000..3cf0c44
--- /dev/null
+++ b/src/Semi.Avalonia/Animations/SemiPopupAnimations.axaml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Semi.Avalonia/Animations/SemiPopupAnimations.axaml.cs b/src/Semi.Avalonia/Animations/SemiPopupAnimations.axaml.cs
new file mode 100644
index 0000000..00d769e
--- /dev/null
+++ b/src/Semi.Avalonia/Animations/SemiPopupAnimations.axaml.cs
@@ -0,0 +1,8 @@
+using Avalonia.Styling;
+
+namespace Semi.Avalonia;
+
+public class SemiPopupAnimations: Styles
+{
+
+}
\ No newline at end of file
diff --git a/src/Semi.Avalonia/Controls/Popup.axaml b/src/Semi.Avalonia/Controls/Popup.axaml
index 15b6636..e8b6037 100644
--- a/src/Semi.Avalonia/Controls/Popup.axaml
+++ b/src/Semi.Avalonia/Controls/Popup.axaml
@@ -11,12 +11,14 @@
-
+
+
+
@@ -29,12 +31,14 @@
-
+
+
+
diff --git a/src/Semi.Avalonia/Converters/PlacementToRenderTransformOriginConverter.cs b/src/Semi.Avalonia/Converters/PlacementToRenderTransformOriginConverter.cs
new file mode 100644
index 0000000..a370678
--- /dev/null
+++ b/src/Semi.Avalonia/Converters/PlacementToRenderTransformOriginConverter.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Globalization;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Data.Converters;
+
+namespace Semi.Avalonia.Converters;
+
+public class PlacementToRenderTransformOriginConverter: IValueConverter
+{
+ public static PlacementToRenderTransformOriginConverter Instance { get; } = new PlacementToRenderTransformOriginConverter();
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value is not PlacementMode p)
+ {
+ return new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
+ }
+ switch (p)
+ {
+ case PlacementMode.Bottom:
+ return new RelativePoint(0.5, 0.0, RelativeUnit.Relative);
+ case PlacementMode.Left:
+ return new RelativePoint(1.0, 0.5, RelativeUnit.Relative);
+ case PlacementMode.Right:
+ return new RelativePoint(0.0, 0.5, RelativeUnit.Relative);
+ case PlacementMode.Top:
+ return new RelativePoint(0.5, 1.0, RelativeUnit.Relative);
+ case PlacementMode.Pointer:
+ return new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
+ case PlacementMode.Center:
+ case PlacementMode.AnchorAndGravity:
+ return new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
+ case PlacementMode.BottomEdgeAlignedLeft:
+ return new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
+ case PlacementMode.BottomEdgeAlignedRight:
+ return new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
+ case PlacementMode.LeftEdgeAlignedTop:
+ return new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
+ case PlacementMode.LeftEdgeAlignedBottom:
+ return new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
+ case PlacementMode.RightEdgeAlignedTop:
+ return new RelativePoint(0.0, 1.0, RelativeUnit.Relative);
+ case PlacementMode.RightEdgeAlignedBottom:
+ return new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
+ case PlacementMode.TopEdgeAlignedLeft:
+ return new RelativePoint(0.0, 1.0, RelativeUnit.Relative);
+ case PlacementMode.TopEdgeAlignedRight:
+ return new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
+ }
+ return new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file