commit ead3ccc62a182b566252506552269555be31814a
parent d829181a5d3bfaaa16983eabe72097d2533f8255
Author: triesap <tyson@radroots.org>
Date: Tue, 27 Jan 2026 14:31:20 +0000
ui: migrate dialog attributes to ui-primitives
- add ui-primitives-leptos dependency and re-exports
- drive dialog trigger/content attributes via builders
- attach dialog attributes through use_primitive node refs
- update workspace lockfile for new dependency graph
Diffstat:
4 files changed, 51 insertions(+), 13 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -1761,6 +1761,7 @@ dependencies = [
"radroots-app-ui-core",
"send_wrapper",
"ui-primitives-core",
+ "ui-primitives-leptos",
"wasm-bindgen",
"web-sys",
]
@@ -2699,6 +2700,16 @@ name = "ui-primitives-core"
version = "0.1.0"
[[package]]
+name = "ui-primitives-leptos"
+version = "0.1.0"
+dependencies = [
+ "leptos",
+ "ui-primitives-core",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
name = "unicode-ident"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/crates/ui-components/src/dialog.rs b/crates/ui-components/src/dialog.rs
@@ -5,6 +5,10 @@ use std::sync::{Arc, Mutex};
use radroots_app_ui_core::RadrootsAppUiId;
use radroots_app_ui_primitives::{
+ dialog_content_attrs,
+ dialog_trigger_attrs,
+ use_primitive,
+ DialogModel,
RadrootsAppUiDismissableReason,
RadrootsAppUiDismissableLayer,
RadrootsAppUiFocusScope,
@@ -95,7 +99,13 @@ pub fn RadrootsAppUiDialogTrigger(
) -> impl IntoView {
let context = use_context::<RadrootsAppUiDialogContext>()
.expect("dialog context");
+ let open = context.open;
let content_id = context.content_id.clone();
+ let attrs = Signal::derive(move || {
+ let model = DialogModel::new(open.get());
+ dialog_trigger_attrs(&model, Some(content_id.as_str()))
+ });
+ let trigger = use_primitive::<html::Button>(attrs, Vec::new());
let on_click = move |_event: MouseEvent| {
if disabled {
return;
@@ -104,16 +114,13 @@ pub fn RadrootsAppUiDialogTrigger(
};
view! {
<button
+ node_ref=trigger.node_ref()
type="button"
id=id
class=class
style=style
disabled=disabled
- aria-haspopup="dialog"
- aria-expanded=move || if context.open.get() { "true" } else { "false" }
- aria-controls=content_id
data-ui="dialog-trigger"
- data-state=move || radroots_app_ui_dialog_state_value(context.open.get())
on:click=on_click
>
{children()}
@@ -176,11 +183,24 @@ pub fn RadrootsAppUiDialogContent(
) -> impl IntoView {
let context = use_context::<RadrootsAppUiDialogContext>()
.expect("dialog context");
- let node_ref = NodeRef::<html::Div>::new();
let content_id = context.content_id.clone();
+ let open = context.open;
+ let title_id = context.title_id;
+ let description_id = context.description_id;
let scroll_guard = Arc::new(Mutex::new(None::<RadrootsAppUiScrollLockGuard>));
let modal_guard = Arc::new(Mutex::new(None::<RadrootsAppUiModalGuard>));
let modal = context.modal;
+ let attrs = Signal::derive(move || {
+ let mut model = DialogModel::new(open.get());
+ model.set_modal(modal);
+ dialog_content_attrs(
+ &model,
+ title_id.get().as_deref(),
+ description_id.get().as_deref(),
+ )
+ });
+ let primitive = use_primitive::<html::Div>(attrs, Vec::new());
+ let node_ref = primitive.node_ref();
#[cfg(target_arch = "wasm32")]
{
@@ -224,9 +244,6 @@ pub fn RadrootsAppUiDialogContent(
let on_dismiss = context.dismiss.clone();
- let labelled_by = move || context.title_id.get();
- let described_by = move || context.description_id.get();
- let aria_modal = StoredValue::new(if modal { Some("true".to_string()) } else { None });
let data_ui = StoredValue::new(data_ui.unwrap_or_else(|| "dialog".to_string()));
let id_value = StoredValue::new(id.unwrap_or_else(|| content_id.clone()));
let class_value = StoredValue::new(class);
@@ -244,12 +261,7 @@ pub fn RadrootsAppUiDialogContent(
id=move || id_value.get_value()
class=move || class_value.get_value()
style=move || style_value.get_value()
- role="dialog"
- aria-modal=move || aria_modal.get_value()
- aria-labelledby=labelled_by
- aria-describedby=described_by
data-ui=move || data_ui.get_value()
- data-state=move || radroots_app_ui_dialog_state_value(context.open.get())
>
{(children.get_value())()}
</div>
diff --git a/crates/ui-primitives/Cargo.toml b/crates/ui-primitives/Cargo.toml
@@ -13,6 +13,7 @@ crate-type = ["rlib"]
radroots-app-ui-core = { path = "../ui-core" }
leptos = { workspace = true, features = ["csr"] }
ui-primitives-core = { path = "../../refs/ui-primitives/crates/ui-primitives-core" }
+ui-primitives-leptos = { path = "../../refs/ui-primitives/crates/ui-primitives-leptos" }
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = { workspace = true }
diff --git a/crates/ui-primitives/src/lib.rs b/crates/ui-primitives/src/lib.rs
@@ -46,3 +46,17 @@ pub use aria_hidden::{
RadrootsAppUiModalResult,
RadrootsAppUiModalTarget,
};
+pub use ui_primitives_core::dialog::DialogModel;
+pub use ui_primitives_leptos::builders::{
+ dialog_content_attrs,
+ dialog_trigger_attrs,
+};
+pub use ui_primitives_leptos::{
+ use_primitive,
+ PrimitiveAttribute,
+ PrimitiveAttributeValue,
+ PrimitiveElement,
+ PrimitiveError,
+ PrimitiveEvent,
+ PrimitiveResult,
+};