feat: Message adds animation

This commit is contained in:
luoxiao 2024-03-30 01:16:24 +08:00 committed by luoxiaozero
parent 32976ed6e1
commit 64ba5a9221
2 changed files with 74 additions and 16 deletions

View file

@ -35,7 +35,7 @@
right: 12px; right: 12px;
} }
.thaw-message-container--top-left{ .thaw-message-container--top-left {
align-items: start; align-items: start;
top: 12px; top: 12px;
left: 12px; left: 12px;
@ -52,6 +52,37 @@
.thaw-message-wrapper { .thaw-message-wrapper {
margin-bottom: 8px; margin-bottom: 8px;
position: relative; position: relative;
transform-origin: top center;
}
.thaw-message-wrapper.fade-in-height-expand-transition-leave-from,
.thaw-message-wrapper.fade-in-height-expand-transition-enter-to {
transform: scale(1);
opacity: 1;
}
.thaw-message-wrapper.fade-in-height-expand-transition-leave-to,
.thaw-message-wrapper.fade-in-height-expand-transition-enter-from {
transform: scale(0.85);
opacity: 0;
margin-bottom: 0 !important;
max-height: 0 !important;
}
.thaw-message-wrapper.fade-in-height-expand-transition-leave-active {
overflow: visible;
transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1) 0s,
opacity 0.3s cubic-bezier(0, 0, 0.2, 1) 0s,
margin-bottom 0.3s cubic-bezier(0.4, 0, 0.2, 1) 0s,
transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.thaw-message-wrapper.fade-in-height-expand-transition-enter-active {
overflow: visible;
transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1),
opacity 0.3s cubic-bezier(0.4, 0, 1, 1),
margin-bottom 0.3s cubic-bezier(0.4, 0, 0.2, 1),
transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
} }
.thaw-message { .thaw-message {

View file

@ -6,7 +6,7 @@ pub use theme::MessageTheme;
use crate::{theme::use_theme, Icon, Theme}; use crate::{theme::use_theme, Icon, Theme};
use leptos::*; use leptos::*;
use thaw_components::{If, Then}; use thaw_components::{CSSTransition, If, Then};
use uuid::Uuid; use uuid::Uuid;
#[derive(Default, Clone)] #[derive(Default, Clone)]
@ -37,11 +37,13 @@ impl MessageVariant {
#[component] #[component]
fn Message(message: MessageType, #[prop(into)] on_close: Callback<Uuid, ()>) -> impl IntoView { fn Message(message: MessageType, #[prop(into)] on_close: Callback<Uuid, ()>) -> impl IntoView {
let (id, content, variant, MessageOptions { duration, closable }) = message; let (id, content, variant, MessageOptions { duration, closable }) = message;
let is_show = RwSignal::new(true);
let message_ref = NodeRef::<html::Div>::new();
if !duration.is_zero() { if !duration.is_zero() {
set_timeout( set_timeout(
move || { move || {
on_close.call(id); is_show.set(false);
}, },
duration, duration,
); );
@ -59,21 +61,46 @@ fn Message(message: MessageType, #[prop(into)] on_close: Callback<Uuid, ()>) ->
css_vars css_vars
}); });
let style = theme.with_untracked(|theme| format!("color: {};", variant.theme_color(theme))); let style = theme.with_untracked(|theme| format!("color: {};", variant.theme_color(theme)));
let on_before_leave = move |_| {
let Some(node_el) = message_ref.get() else {
return;
};
use std::ops::Deref;
let any_el = node_el.into_any();
let el = any_el.deref();
let style = el.style();
let _ = style.set_property("max-height", &format!("{}px", el.offset_height()));
};
let on_after_leave = move |_| {
queue_microtask(move || on_close.call(id));
};
view! { view! {
<div class="thaw-message-wrapper"> <CSSTransition
<div class="thaw-message" style=move || css_vars.get()> node_ref=message_ref
<div class="thaw-message__icon"> name="fade-in-height-expand-transition"
<Icon icon=variant.icon() style/> show=is_show
appear=true
on_before_leave=on_before_leave
on_after_leave=on_after_leave
let:_
>
<div class="thaw-message-wrapper" ref=message_ref>
<div class="thaw-message" style=move || css_vars.get()>
<div class="thaw-message__icon">
<Icon icon=variant.icon() style/>
</div>
<div class="thaw-message__content">{content}</div>
<If cond=closable>
<Then slot>
<div class="thaw-message__close" on:click=move |_| is_show.set(false)>
<Icon icon=icondata_ai::AiCloseOutlined/>
</div>
</Then>
</If>
</div> </div>
<div class="thaw-message__content">{content}</div>
<If cond=closable>
<Then slot>
<div class="thaw-message__close" on:click=move |_| on_close.call(id)>
<Icon icon=icondata_ai::AiCloseOutlined/>
</div>
</Then>
</If>
</div> </div>
</div> </CSSTransition>
} }
} }