diff --git a/demo/src/app.rs b/demo/src/app.rs
index 38818b1..d120200 100644
--- a/demo/src/app.rs
+++ b/demo/src/app.rs
@@ -110,9 +110,9 @@ fn TheProvider(children: Children) -> impl IntoView {
view! {
- //
- {children()}
- //
+
+ {children()}
+
}
}
diff --git a/demo_markdown/docs/toast/mod.md b/demo_markdown/docs/toast/mod.md
index d77d29b..8bda118 100644
--- a/demo_markdown/docs/toast/mod.md
+++ b/demo_markdown/docs/toast/mod.md
@@ -1,9 +1,14 @@
# Toast
-```rust
+```rust demo
+let toaster = ToasterInjection::use_();
+
+let on_click = move |_| {
+ toaster.dispatch_toast(view! { "Hello" }.into_any(), Default::default());
+};
+
view! {
-
-
+
}
```
\ No newline at end of file
diff --git a/thaw/src/toast/mod.rs b/thaw/src/toast/mod.rs
index 4baa1df..2a74025 100644
--- a/thaw/src/toast/mod.rs
+++ b/thaw/src/toast/mod.rs
@@ -1,7 +1,59 @@
mod toast;
-mod toast_title;
-mod toaster;
mod toast_body;
mod toast_footer;
+mod toast_title;
+mod toaster;
+mod toaster_provider;
+pub use toast::*;
pub use toast_title::*;
+pub use toaster_provider::*;
+
+use leptos::{html::AnyElement, *};
+use std::sync::mpsc::{channel, Receiver, Sender, TryIter};
+
+#[derive(Clone)]
+pub struct ToasterInjection {
+ sender: Sender<(HtmlElement, ToastOptions)>,
+ trigger: Trigger,
+}
+
+impl ToasterInjection {
+ pub fn use_() -> Self {
+ expect_context()
+ }
+
+ pub fn channel() -> (Self, ToasterReceiver) {
+ let (sender, receiver) = channel::<(HtmlElement, ToastOptions)>();
+ let trigger = Trigger::new();
+
+ (
+ Self { sender, trigger },
+ ToasterReceiver::new(receiver, trigger),
+ )
+ }
+
+ pub fn dispatch_toast(&self, any_element: HtmlElement, options: ToastOptions) {
+ self.sender.send((any_element, options)).unwrap();
+ self.trigger.notify();
+ }
+}
+
+pub struct ToasterReceiver {
+ receiver: Receiver<(HtmlElement, ToastOptions)>,
+ trigger: Trigger,
+}
+
+impl ToasterReceiver {
+ pub fn new(
+ receiver: Receiver<(HtmlElement, ToastOptions)>,
+ trigger: Trigger,
+ ) -> Self {
+ Self { receiver, trigger }
+ }
+
+ pub fn try_recv(&self) -> TryIter<'_, (HtmlElement, ToastOptions)> {
+ self.trigger.track();
+ self.receiver.try_iter()
+ }
+}
diff --git a/thaw/src/toast/toast.rs b/thaw/src/toast/toast.rs
index 3bf9735..399fd5c 100644
--- a/thaw/src/toast/toast.rs
+++ b/thaw/src/toast/toast.rs
@@ -1,8 +1,49 @@
use leptos::*;
#[component]
-pub fn Toast(id: String) -> impl IntoView {
+pub fn Toast(children: Children) -> impl IntoView {
view! {
-
+
+ {children()}
+
+ }
+}
+
+#[derive(Default, Clone)]
+pub enum ToastPosition {
+ Top,
+ TopStart,
+ #[default]
+ TopEnd,
+ Bottom,
+ BottomStart,
+ BottomEnd,
+}
+
+impl ToastPosition {
+ pub fn as_str(&self) -> &'static str {
+ match self {
+ Self::Top => "top",
+ Self::TopStart => "top-left",
+ Self::TopEnd => "top-right",
+ Self::Bottom => "bottom",
+ Self::BottomStart => "bottom-left",
+ Self::BottomEnd => "bottom-right",
+ }
+ }
+}
+
+#[derive(Clone)]
+pub struct ToastOptions {
+ pub id: uuid::Uuid,
+ pub postition: Option,
+}
+
+impl Default for ToastOptions {
+ fn default() -> Self {
+ Self {
+ id: uuid::Uuid::new_v4(),
+ postition: None,
+ }
}
}
diff --git a/thaw/src/toast/toaster.css b/thaw/src/toast/toaster.css
index 972920f..d323a47 100644
--- a/thaw/src/toast/toaster.css
+++ b/thaw/src/toast/toaster.css
@@ -1,3 +1,27 @@
+div.thaw-toaster-container {
+ z-index: 1000000;
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ right: 0px;
+ line-height: var(--lineHeightBase300);
+ font-weight: var(--fontWeightRegular);
+ font-size: var(--fontSizeBase300);
+ font-family: var(--fontFamilyBase);
+ text-align: left;
+ background-color: var(--colorNeutralBackground1);
+ color: var(--colorNeutralForeground1);
+}
+
+.thaw-toaster {
+ bottom: 16px;
+ right: 20px;
+
+ position: fixed;
+ width: 292px;
+ pointer-events: none;
+}
+
.thaw-toast {
display: grid;
grid-template-columns: auto 1fr auto;
diff --git a/thaw/src/toast/toaster.rs b/thaw/src/toast/toaster.rs
index b668d83..3f66118 100644
--- a/thaw/src/toast/toaster.rs
+++ b/thaw/src/toast/toaster.rs
@@ -1,10 +1,36 @@
+use super::{ToastPosition, ToasterReceiver};
use leptos::*;
-use thaw_utils::mount_style;
+use thaw_components::Teleport;
+use thaw_utils::{class_list, mount_style};
#[component]
-pub fn Toaster(toaster_id: String) -> impl IntoView {
+pub fn Toaster(
+ receiver: ToasterReceiver,
+ #[prop(optional)] position: ToastPosition,
+) -> impl IntoView {
mount_style("toaster", include_str!("./toaster.css"));
- view! {
+ let toast_list = RwSignal::new(vec![]);
+ Effect::new(move |_| {
+ for view in receiver.try_recv() {
+ toast_list.update(move |list| {
+ list.push(view);
+ });
+ }
+ });
+ view! {
+
+
+
}
}
diff --git a/thaw/src/toast/toaster_provider.rs b/thaw/src/toast/toaster_provider.rs
new file mode 100644
index 0000000..504bc86
--- /dev/null
+++ b/thaw/src/toast/toaster_provider.rs
@@ -0,0 +1,16 @@
+use super::{toaster::Toaster, ToastPosition, ToasterInjection};
+use leptos::*;
+
+#[component]
+pub fn ToasterProvider(
+ #[prop(optional)] position: ToastPosition,
+ children: Children,
+) -> impl IntoView {
+ let (injection, receiver) = ToasterInjection::channel();
+ view! {
+
+
+ {children()}
+
+ }
+}