use topcoat::{
Result,
runtime::Expr,
view::{Attributes, Child, StaticClass, View, class, component, view},
};
const OVERLAY: StaticClass = class!(
"fixed inset-0 z-50 size-full max-h-none max-w-none items-start \
justify-center overflow-y-auto bg-background/80 p-4 text-foreground backdrop-blur-sm \
open:flex",
);
const FADE: StaticClass = class!(
"opacity-0 open:opacity-100 starting:open:opacity-0 \
[transition:opacity_200ms_ease-out,display_200ms_allow-discrete]",
);
#[component]
pub async fn dialog(
#[into]
open: Expr<bool>,
#[default]
mut attrs: Attributes,
#[default]
child: Child<'_>,
) -> Result<impl View> {
Ok(view! {
<dialog
:open=(open)
class=(class!(OVERLAY, FADE, attrs.remove("class")))
(attrs)
>
(child)
</dialog>
})
}
const CONTENT: StaticClass = class!(
"relative my-auto flex w-full max-w-lg flex-col gap-4 rounded-xl \
border border-border bg-card p-6 text-card-foreground shadow-sm",
);
const MOTION: StaticClass = class!(
"scale-95 opacity-0 in-[[open]]:scale-100 in-[[open]]:opacity-100 \
starting:in-[[open]]:scale-95 starting:in-[[open]]:opacity-0 \
[transition:scale_200ms_ease-out,opacity_200ms_ease-out]",
);
#[component]
pub async fn dialog_content(
#[default] mut attrs: Attributes,
#[default] child: Child<'_>,
) -> Result<impl View> {
Ok(view! {
<div class=(class!(CONTENT, MOTION, attrs.remove("class"))) (attrs)>
(child)
</div>
})
}
#[component]
pub async fn dialog_header(
#[default] mut attrs: Attributes,
#[default] child: Child<'_>,
) -> Result<impl View> {
Ok(view! {
<div class=(class!("flex flex-col gap-1.5", attrs.remove("class"))) (attrs)>
(child)
</div>
})
}
#[component]
pub async fn dialog_title(
#[default] mut attrs: Attributes,
#[default] child: Child<'_>,
) -> Result<impl View> {
Ok(view! {
<h2
class=(class!("text-lg leading-none font-semibold", attrs.remove("class")))
(attrs)
>
(child)
</h2>
})
}
#[component]
pub async fn dialog_description(
#[default] mut attrs: Attributes,
#[default] child: Child<'_>,
) -> Result<impl View> {
Ok(view! {
<p
class=(class!("text-sm text-muted-foreground", attrs.remove("class")))
(attrs)
>
(child)
</p>
})
}
#[component]
pub async fn dialog_footer(
#[default] mut attrs: Attributes,
#[default] child: Child<'_>,
) -> Result<impl View> {
Ok(view! {
<div
class=(class!(
"flex flex-wrap items-center justify-end gap-2",
attrs.remove("class"),
))
(attrs)
>
(child)
</div>
})
}