app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit e8742848fba7e40d7aa184af70597aff2f34ad79
parent bb7e4e6ce98c797da74d75c5d448636f97a18d4d
Author: triesap <triesap@radroots.dev>
Date:   Wed, 21 Jan 2026 20:53:23 +0000

app: add ui demo settings page

- add ui demo route with list group and sheet preview
- wire sheet open state with local signal callbacks
- add app dependency on ui-components and export demo page
- align sheet component props to accept optional values

Diffstat:
MCargo.lock | 1+
Mapp/Cargo.toml | 1+
Mapp/src/app.rs | 3+++
Mapp/src/lib.rs | 2++
Aapp/src/ui_demo.rs | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/ui-components/src/sheet.rs | 44++++++++++++++++++++++----------------------
6 files changed, 120 insertions(+), 22 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -1651,6 +1651,7 @@ dependencies = [ "leptos", "leptos_router", "radroots-app-core", + "radroots-app-ui-components", "radroots-log", "serde", "serde_json", diff --git a/app/Cargo.toml b/app/Cargo.toml @@ -19,6 +19,7 @@ js-sys.workspace = true web-sys.workspace = true gloo-timers = { workspace = true, features = ["futures"] } radroots-app-core = { path = "../crates/core" } +radroots-app-ui-components = { path = "../crates/ui-components" } radroots-log = { path = "../refs/crates/log", default-features = false } tracing-wasm = "0.2" console_error_panic_hook = "0.1" diff --git a/app/src/app.rs b/app/src/app.rs @@ -40,6 +40,7 @@ use crate::{ RadrootsAppInitStage, RadrootsAppNotifications, RadrootsAppLogsPage, + RadrootsAppUiDemoPage, RadrootsAppTangleClientStub, }; @@ -700,11 +701,13 @@ fn AppShell() -> impl IntoView { <nav style="display:flex;gap:12px;margin-bottom:12px;"> <A href="/" exact=true>"home"</A> <A href="/logs">"logs"</A> + <A href="/ui">"ui"</A> <A href="/setup">"setup"</A> </nav> <Routes fallback=|| view! { <div>"not_found"</div> }> <Route path=path!("") view=HomePage /> <Route path=path!("logs") view=RadrootsAppLogsPage /> + <Route path=path!("ui") view=RadrootsAppUiDemoPage /> <Route path=path!("setup") view=SetupPage /> </Routes> </Show> diff --git a/app/src/lib.rs b/app/src/lib.rs @@ -13,6 +13,7 @@ mod logs; mod notifications; mod setup; mod tangle; +mod ui_demo; mod entry; pub use app::RadrootsApp; @@ -61,6 +62,7 @@ pub use keystore::{ RadrootsAppKeystoreResult, }; pub use logs::RadrootsAppLogsPage; +pub use ui_demo::RadrootsAppUiDemoPage; pub use logging::{ app_log_entry_error, app_log_entry_emit, diff --git a/app/src/ui_demo.rs b/app/src/ui_demo.rs @@ -0,0 +1,91 @@ +use leptos::prelude::*; + +use radroots_app_ui_components::{ + RadrootsAppUiSheetClose, + RadrootsAppUiSheetContent, + RadrootsAppUiSheetDescription, + RadrootsAppUiSheetOverlay, + RadrootsAppUiSheetPortal, + RadrootsAppUiSheetRoot, + RadrootsAppUiSheetTitle, + RadrootsAppUiSheetTrigger, +}; + +#[component] +pub fn RadrootsAppUiDemoPage() -> impl IntoView { + let sheet_open = RwSignal::new(false); + let sheet_open_read = sheet_open.read_only(); + let sheet_open_set = Callback::new(move |value| sheet_open.set(value)); + view! { + <main style="padding: 16px;"> + <div style="font: var(--type-title2); margin-bottom: 12px;">"UI Demo"</div> + <div data-ui="list-group"> + <div data-ui="list-row"> + <div data-ui="list-row-leading">"Wi-Fi"</div> + <div data-ui="list-row-trailing">"On"</div> + </div> + <div data-ui="list-row"> + <div data-ui="list-row-leading">"Bluetooth"</div> + <div data-ui="list-row-trailing">"On"</div> + </div> + <div data-ui="list-row"> + <div data-ui="list-row-leading">"Notifications"</div> + <div data-ui="list-row-trailing">"Enabled"</div> + </div> + </div> + + <RadrootsAppUiSheetRoot + open=Some(sheet_open_read) + default_open=false + modal=None + on_open_change=Some(sheet_open_set) + > + <RadrootsAppUiSheetTrigger + disabled=false + class=Some("ui-card".to_string()) + id=None + style=Some("padding:12px 16px; width: 100%; text-align: left;".to_string()) + > + "Open Sheet" + </RadrootsAppUiSheetTrigger> + <RadrootsAppUiSheetPortal> + <RadrootsAppUiSheetOverlay + close_on_click=None + class=None + id=None + style=None + /> + <RadrootsAppUiSheetContent + disable_outside_pointer_events=false + show_handle=true + class=None + id=None + style=None + > + <RadrootsAppUiSheetTitle + class=None + id=None + style=None + > + "Sheet Preview" + </RadrootsAppUiSheetTitle> + <RadrootsAppUiSheetDescription + class=None + id=None + style=Some("margin-top: 6px;".to_string()) + > + "This is a placeholder sheet for iOS styling." + </RadrootsAppUiSheetDescription> + <RadrootsAppUiSheetClose + class=Some("ui-card".to_string()) + id=None + style=Some("margin-top: 16px; padding: 10px 14px;".to_string()) + > + "Close" + </RadrootsAppUiSheetClose> + </RadrootsAppUiSheetContent> + </RadrootsAppUiSheetPortal> + </RadrootsAppUiSheetRoot> + </main> + } +} diff --git a/crates/ui-components/src/sheet.rs b/crates/ui-components/src/sheet.rs @@ -25,10 +25,10 @@ pub fn radroots_app_ui_sheet_handle_data_ui_value() -> &'static str { #[component] pub fn RadrootsAppUiSheetRoot( - #[prop(optional)] open: Option<ReadSignal<bool>>, + open: Option<ReadSignal<bool>>, #[prop(optional)] default_open: bool, - #[prop(optional)] modal: Option<bool>, - #[prop(optional)] on_open_change: Option<Callback<bool>>, + modal: Option<bool>, + on_open_change: Option<Callback<bool>>, children: ChildrenFn, ) -> impl IntoView { view! { @@ -46,9 +46,9 @@ pub fn RadrootsAppUiSheetRoot( #[component] pub fn RadrootsAppUiSheetTrigger( #[prop(optional)] disabled: bool, - #[prop(optional)] class: Option<String>, - #[prop(optional)] id: Option<String>, - #[prop(optional)] style: Option<String>, + class: Option<String>, + id: Option<String>, + style: Option<String>, children: Children, ) -> impl IntoView { view! { @@ -74,10 +74,10 @@ pub fn RadrootsAppUiSheetPortal(children: ChildrenFn) -> impl IntoView { #[component] pub fn RadrootsAppUiSheetOverlay( - #[prop(optional)] close_on_click: Option<bool>, - #[prop(optional)] class: Option<String>, - #[prop(optional)] id: Option<String>, - #[prop(optional)] style: Option<String>, + close_on_click: Option<bool>, + class: Option<String>, + id: Option<String>, + style: Option<String>, ) -> impl IntoView { view! { <RadrootsAppUiDialogOverlay @@ -94,9 +94,9 @@ pub fn RadrootsAppUiSheetOverlay( pub fn RadrootsAppUiSheetContent( #[prop(optional)] disable_outside_pointer_events: bool, #[prop(optional)] show_handle: bool, - #[prop(optional)] class: Option<String>, - #[prop(optional)] id: Option<String>, - #[prop(optional)] style: Option<String>, + class: Option<String>, + id: Option<String>, + style: Option<String>, children: ChildrenFn, ) -> impl IntoView { let handle = show_handle; @@ -128,9 +128,9 @@ pub fn RadrootsAppUiSheetContent( #[component] pub fn RadrootsAppUiSheetTitle( - #[prop(optional)] class: Option<String>, - #[prop(optional)] id: Option<String>, - #[prop(optional)] style: Option<String>, + class: Option<String>, + id: Option<String>, + style: Option<String>, children: Children, ) -> impl IntoView { view! { @@ -146,9 +146,9 @@ pub fn RadrootsAppUiSheetTitle( #[component] pub fn RadrootsAppUiSheetDescription( - #[prop(optional)] class: Option<String>, - #[prop(optional)] id: Option<String>, - #[prop(optional)] style: Option<String>, + class: Option<String>, + id: Option<String>, + style: Option<String>, children: Children, ) -> impl IntoView { view! { @@ -164,9 +164,9 @@ pub fn RadrootsAppUiSheetDescription( #[component] pub fn RadrootsAppUiSheetClose( - #[prop(optional)] class: Option<String>, - #[prop(optional)] id: Option<String>, - #[prop(optional)] style: Option<String>, + class: Option<String>, + id: Option<String>, + style: Option<String>, children: Children, ) -> impl IntoView { view! {