@Message
diff --git a/samples/InteractiveWebAssembly/Pages/Animation.razor b/samples/InteractiveWebAssembly/Pages/Animation.razor
index 5960ddb..3c5e71b 100644
--- a/samples/InteractiveWebAssembly/Pages/Animation.razor
+++ b/samples/InteractiveWebAssembly/Pages/Animation.razor
@@ -35,6 +35,8 @@
+
+
@@ -63,6 +65,20 @@
var options = new ModalOptions { AnimationType = ModalAnimationType.PopIn };
Modal.Show("Animation Type: PopIn", options);
+ }
+
+ void AnimationFadeIn()
+ {
+ var options = new ModalOptions { AnimationType = ModalAnimationType.FadeIn };
+
+ Modal.Show("Animation Type: FadeIn", options);
+ }
+
+ void AnimationMoveInOut()
+ {
+ var options = new ModalOptions { AnimationType = ModalAnimationType.MoveInOut };
+
+ Modal.Show("Animation Type: MoveInOut", options);
}
void NoAnimation()
diff --git a/samples/InteractiveWebAssembly/Pages/CustomLayout.razor b/samples/InteractiveWebAssembly/Pages/CustomLayout.razor
index 035169c..8d746bb 100644
--- a/samples/InteractiveWebAssembly/Pages/CustomLayout.razor
+++ b/samples/InteractiveWebAssembly/Pages/CustomLayout.razor
@@ -33,6 +33,8 @@
+
+
@code {
[CascadingParameter] public IModalService Modal { get; set; } = default!;
@@ -45,4 +47,12 @@
Modal.Show("Custom Layout", parameters, options);
}
+ void ShowAnimatedModalCustomLayout()
+ {
+ var options = new ModalOptions { UseCustomLayout = true, AnimationType = ModalAnimationType.MoveInOut };
+ var parameters = new ModalParameters();
+ parameters.Add(nameof(CustomBootstrapModal.Message), "Hello Bootstrap modal!!");
+ Modal.Show("Custom Layout", parameters, options);
+ }
+
}
diff --git a/samples/InteractiveWebAssembly/Shared/CustomAnimatedBootstrapModal.razor b/samples/InteractiveWebAssembly/Shared/CustomAnimatedBootstrapModal.razor
new file mode 100644
index 0000000..995ed77
--- /dev/null
+++ b/samples/InteractiveWebAssembly/Shared/CustomAnimatedBootstrapModal.razor
@@ -0,0 +1,29 @@
+
+
+@code {
+
+ [CascadingParameter] BlazoredModalInstance BlazoredModal { get; set; } = default!;
+
+ [Parameter] public string? Message { get; set; }
+
+ async Task Close() => await BlazoredModal.CloseAsync(ModalResult.Ok(true));
+ async Task Cancel() => await BlazoredModal.CancelAsync();
+
+}
\ No newline at end of file
diff --git a/samples/InteractiveWebAssembly/Shared/CustomBootstrapModal.razor b/samples/InteractiveWebAssembly/Shared/CustomBootstrapModal.razor
index b72ca68..bbb8a7d 100644
--- a/samples/InteractiveWebAssembly/Shared/CustomBootstrapModal.razor
+++ b/samples/InteractiveWebAssembly/Shared/CustomBootstrapModal.razor
@@ -1,13 +1,11 @@
-
+
@Message
diff --git a/src/Blazored.Modal/BlazoredModalInstance.razor b/src/Blazored.Modal/BlazoredModalInstance.razor
index aa9f7d0..c38d778 100644
--- a/src/Blazored.Modal/BlazoredModalInstance.razor
+++ b/src/Blazored.Modal/BlazoredModalInstance.razor
@@ -1,8 +1,10 @@
@if (UseCustomLayout)
{
-
- @Content
-
+
+
+ @Content
+
+
}
else
{
@@ -13,7 +15,7 @@ else
@onclick="StopListeningToBackgroundClick">
-
}
\ No newline at end of file
diff --git a/src/Blazored.Modal/BlazoredModalInstance.razor.cs b/src/Blazored.Modal/BlazoredModalInstance.razor.cs
index bca1b08..d592ce4 100644
--- a/src/Blazored.Modal/BlazoredModalInstance.razor.cs
+++ b/src/Blazored.Modal/BlazoredModalInstance.razor.cs
@@ -19,7 +19,8 @@ public partial class BlazoredModalInstance : IDisposable
private bool HideHeader { get; set; }
private bool HideCloseButton { get; set; }
private bool DisableBackgroundCancel { get; set; }
- private string? OverlayAnimationClass { get; set; }
+ public string? ModalAnimationClass { get; set; }
+ public string? OverlayAnimationClass { get; set; }
private string? OverlayCustomClass { get; set; }
private ModalAnimationType? AnimationType { get; set; }
private bool ActivateFocusTrap { get; set; }
@@ -95,20 +96,31 @@ public async Task CloseAsync()
public async Task CloseAsync(ModalResult modalResult)
{
// Fade out the modal, and after that actually remove it
- if (AnimationType is ModalAnimationType.FadeInOut)
+ if (AnimationType is not ModalAnimationType.None && AnimationType is not ModalAnimationType.FadeIn &&
+ AnimationType is not ModalAnimationType.MoveIn && AnimationType is not ModalAnimationType.PopIn)
{
- OverlayAnimationClass += " fade-out";
+ OverlayAnimationClass = AnimationType switch
+ {
+ ModalAnimationType.FadeInOut or ModalAnimationType.FadeOut or
+ ModalAnimationType.MoveInOut or ModalAnimationType.MoveOut or
+ ModalAnimationType.PopInOut => "fade-out",
+ _ => string.Empty,
+ };
+
+ FocusTrap?.TriggerRender();
+
+ ModalAnimationClass = AnimationType switch
+ {
+ ModalAnimationType.FadeInOut or ModalAnimationType.FadeOut => "fade-out",
+ ModalAnimationType.MoveInOut or ModalAnimationType.MoveOut => "move-out",
+ ModalAnimationType.PopInOut => "pop-out",
+ _ => string.Empty,
+ };
+
StateHasChanged();
await Task.Delay(400); // Needs to be a bit more than the animation time because of delays in the animation being applied between server and client (at least when using blazor server side), I think.
}
- else if (AnimationType is ModalAnimationType.PopInOut)
- {
- OverlayAnimationClass += " pop-out";
- StateHasChanged();
-
- await Task.Delay(400);
- }
await Parent.DismissInstance(Id, modalResult);
}
@@ -127,16 +139,17 @@ public async Task CancelAsync(TPayload payload)
private void ConfigureInstance()
{
+ UseCustomLayout = SetUseCustomLayout();
AnimationType = SetAnimation();
Position = SetPosition();
ModalClass = SetModalClass();
HideHeader = SetHideHeader();
HideCloseButton = SetHideCloseButton();
DisableBackgroundCancel = SetDisableBackgroundCancel();
- UseCustomLayout = SetUseCustomLayout();
OverlayCustomClass = SetOverlayCustomClass();
ActivateFocusTrap = SetActivateFocusTrap();
- OverlayAnimationClass = SetAnimationClass();
+ OverlayAnimationClass = SetOverlayAnimationClass();
+ ModalAnimationClass = SetModalAnimationClass();
Parent.OnModalClosed += AttemptFocus;
}
@@ -275,11 +288,20 @@ private string SetModalClass()
}
private ModalAnimationType SetAnimation()
- => Options.AnimationType ?? GlobalModalOptions.AnimationType ?? ModalAnimationType.FadeInOut;
+ => Options.AnimationType ?? GlobalModalOptions.AnimationType ?? (!UseCustomLayout ? ModalAnimationType.FadeInOut : ModalAnimationType.None);
+
+ private string SetOverlayAnimationClass() => AnimationType switch
+ {
+ ModalAnimationType.FadeInOut or ModalAnimationType.FadeIn or
+ ModalAnimationType.MoveInOut or ModalAnimationType.MoveIn or
+ ModalAnimationType.PopInOut or ModalAnimationType.PopIn => "fade-in",
+ _ => string.Empty
+ };
- private string SetAnimationClass() => AnimationType switch
+ private string SetModalAnimationClass() => AnimationType switch
{
- ModalAnimationType.FadeInOut => "fade-in",
+ ModalAnimationType.FadeInOut or ModalAnimationType.FadeIn => "fade-in",
+ ModalAnimationType.MoveInOut or ModalAnimationType.MoveIn => "move-in",
ModalAnimationType.PopInOut or ModalAnimationType.PopIn => "pop-in",
_ => string.Empty,
};
diff --git a/src/Blazored.Modal/BlazoredModalInstance.razor.css b/src/Blazored.Modal/BlazoredModalInstance.razor.css
index dd76baa..0a61c9a 100644
--- a/src/Blazored.Modal/BlazoredModalInstance.razor.css
+++ b/src/Blazored.Modal/BlazoredModalInstance.razor.css
@@ -102,40 +102,69 @@
align-items: center;
}
-.fade-in {
- animation: 300ms ease-out 0s ModalFadeIn;
+.fade-in, ::deep .fade-in {
+ animation: 300ms ease-out 0s ModalFadeIn;
}
-.fade-out {
- animation: 300ms ease-out 0s ModalFadeOut;
- opacity: 0;
+.fade-out, ::deep .fade-out {
+ animation: 300ms ease-out 0s ModalFadeOut;
+ opacity: 0;
}
@keyframes ModalFadeIn {
- 0% {
- opacity: 0;
- }
+ 0% {
+ opacity: 0;
+ }
- 100% {
- opacity: 1;
- }
- }
+ 100% {
+ opacity: 1;
+ }
+}
@keyframes ModalFadeOut {
- 0% {
- opacity: 1;
- }
+ 0% {
+ opacity: 1;
+ }
+
+ 100% {
+ opacity: 0;
+ }
+}
+
+.move-in, ::deep .move-in {
+ animation: 300ms ease-out 0s ModalMoveIn;
+}
+
+.move-out, ::deep .move-out {
+ animation: 300ms ease-out 0s ModalMoveOut;
+ transform: translate(0, -50px);
+}
+
+@keyframes ModalMoveIn {
+ 0% {
+ transform: translate(0, -50px);
+ }
+
+ 100% {
+ transform: none;
+ }
+}
+
+@keyframes ModalMoveOut {
+ 0% {
+ transform: none;
+ }
- 100% {
- opacity: 0;
- }
- }
+ 100% {
+ transform: translate(0, -50px);
+ }
+}
-.bm-container.pop-in .blazored-modal {
+.pop-in, ::deep .pop-in {
animation: 300ms ease-out 0s ModalPopIn;
}
-.bm-container.pop-out .blazored-modal {
+.pop-out, ::deep .pop-out {
animation: 300ms ease-in 0s ModalPopOut;
transform: scale(0%);
}
diff --git a/src/Blazored.Modal/Configuration/ModalAnimationType.cs b/src/Blazored.Modal/Configuration/ModalAnimationType.cs
index 172fbeb..c6d8cf3 100644
--- a/src/Blazored.Modal/Configuration/ModalAnimationType.cs
+++ b/src/Blazored.Modal/Configuration/ModalAnimationType.cs
@@ -3,6 +3,11 @@
public enum ModalAnimationType
{
FadeInOut,
+ FadeIn,
+ FadeOut,
+ MoveInOut,
+ MoveIn,
+ MoveOut,
PopInOut,
PopIn,
None
diff --git a/src/Blazored.Modal/FocusTrap.razor b/src/Blazored.Modal/FocusTrap.razor
index a6e11e7..99f458f 100644
--- a/src/Blazored.Modal/FocusTrap.razor
+++ b/src/Blazored.Modal/FocusTrap.razor
@@ -13,13 +13,20 @@
private ElementReference _endFirst;
private ElementReference _endSecond;
private bool _shiftPressed;
+ private bool _shouldRender = false;
[Parameter] public RenderFragment ChildContent { get; set; } = default!;
[Parameter] public bool IsActive { get; set; }
protected override bool ShouldRender()
- => false;
+ => _shouldRender;
+ public void TriggerRender()
+ {
+ _shouldRender = true;
+ StateHasChanged();
+ _shouldRender = false;
+ }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)