commit 5cbc36e2720b81422942fc419cfeb465052c01af
parent f364dde6de8d44c0cdf8d92bb0b674b4c7708604
Author: triesap <tyson@radroots.org>
Date: Fri, 6 Feb 2026 11:52:52 +0000
app: adjust navigation and settings title
- add settings gear icon and topbar layout
- move ui demo route to /test and remove old nav
- add settings icon key for lucide
- tune settings title sizing and casing
Diffstat:
3 files changed, 61 insertions(+), 13 deletions(-)
diff --git a/app/src/app.rs b/app/src/app.rs
@@ -17,6 +17,8 @@ use radroots_app_ui_components::{
RadrootsAppUiButtonLayoutAction,
RadrootsAppUiButtonLayoutBackAction,
RadrootsAppUiButtonLayoutPair,
+ RadrootsAppUiIcon,
+ RadrootsAppUiIconKey,
RadrootsAppUiSpinner,
};
use uuid::Uuid;
@@ -716,7 +718,7 @@ fn SetupPage() -> impl IntoView {
</header>
<footer
id="app-setup-intro-footer"
- class="absolute bottom-0 left-0 flex flex-col h-[20rem] w-full px-10 gap-2 justify-start items-center"
+ class="absolute bottom-0 left-0 flex flex-col h-[20rem] w-full gap-2 justify-start items-center"
>
<p
id="app-setup-intro-kicker"
@@ -1616,12 +1618,18 @@ fn AppShell() -> impl IntoView {
if gate.show_app {
return view! {
<div id="app-shell">
- <nav id="app-nav" aria-label=t!("app.nav.primary_aria") style="display:flex;gap:12px;margin-bottom:12px;">
- <A href="/" exact=true>{t!("app.nav.home")}</A>
- <A href="/logs">{t!("app.nav.logs")}</A>
- <A href="/ui">{t!("app.nav.ui")}</A>
- <A href="/settings">{t!("app.nav.settings")}</A>
- </nav>
+ <div
+ id="app-topbar"
+ class="flex items-center justify-end px-4 pt-4"
+ >
+ <A
+ href="/settings"
+ attr:aria-label=t!("app.nav.settings")
+ attr:class="inline-flex h-9 w-9 items-center justify-center rounded-full"
+ >
+ <RadrootsAppUiIcon key=RadrootsAppUiIconKey::Settings size=20 />
+ </A>
+ </div>
<Routes
fallback=|| view! {
<main id="app-not-found" class="app-page app-page-fixed">
@@ -1630,8 +1638,8 @@ fn AppShell() -> impl IntoView {
}
>
<Route path=path!("") view=HomePage />
- <Route path=path!("logs") view=RadrootsAppLogsPage />
- <Route path=path!("ui") view=RadrootsAppUiDemoPage />
+ <Route path=path!("settings/logs") view=RadrootsAppLogsPage />
+ <Route path=path!("test") view=RadrootsAppUiDemoPage />
<Route
path=path!("settings/status")
view=RadrootsAppSettingsStatusPage
diff --git a/app/src/settings.rs b/app/src/settings.rs
@@ -152,6 +152,7 @@ pub fn RadrootsAppSettingsPage() -> impl IntoView {
hide_offset: false,
styles: None,
};
+ let logs_navigate = navigate.clone();
let actions_list = RadrootsAppUiList {
id: Some("settings-actions".to_string()),
view: Some("settings".to_string()),
@@ -187,6 +188,30 @@ pub fn RadrootsAppSettingsPage() -> impl IntoView {
Some(RadrootsAppUiListItem {
kind: RadrootsAppUiListItemKind::Touch(RadrootsAppUiListTouch {
label: RadrootsAppUiListLabel {
+ left: vec![settings_label(t!("app.nav.logs"), Some("capitalize"))],
+ right: Vec::new(),
+ },
+ display: None,
+ end: Some(RadrootsAppUiListTouchEnd {
+ icon: RadrootsAppUiListIcon {
+ key: "caret-right".to_string(),
+ class: None,
+ },
+ on_click: None,
+ }),
+ on_click: Some(Callback::new(move |_| {
+ logs_navigate("/settings/logs", Default::default());
+ })),
+ }),
+ loading: false,
+ hide_active: true,
+ hide_field: false,
+ full_rounded: false,
+ offset: None,
+ }),
+ Some(RadrootsAppUiListItem {
+ kind: RadrootsAppUiListItemKind::Touch(RadrootsAppUiListTouch {
+ label: RadrootsAppUiListLabel {
left: vec![settings_label(
t!("app.settings.actions.logout"),
Some("capitalize"),
@@ -261,8 +286,11 @@ pub fn RadrootsAppSettingsPage() -> impl IntoView {
};
view! {
<main id="app-settings" class="app-page app-page-scroll" style="padding: 16px;">
- <header id="app-settings-header" style="font: var(--type-title2); margin-bottom: 12px;">
- <h1 id="app-settings-title">{t!("app.settings.title")}</h1>
+ <header
+ id="app-settings-header"
+ style="font-family: var(--font-sans); font-size: 34px; line-height: 41px; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 12px;"
+ >
+ <h1 id="app-settings-title" class="capitalize">{t!("app.settings.title")}</h1>
</header>
<section id="app-settings-content" style="display:flex;flex-direction:column;gap:16px;">
<RadrootsAppUiListView basis=appearance_list />
diff --git a/crates/ui-components/src/icon.rs b/crates/ui-components/src/icon.rs
@@ -1,6 +1,6 @@
#![forbid(unsafe_code)]
-use icondata::{Icon, LuChevronRight, LuChevronsUpDown, LuPlus};
+use icondata::{Icon, LuChevronRight, LuChevronsUpDown, LuPlus, LuSettings};
use leptos::prelude::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -8,6 +8,7 @@ pub enum RadrootsAppUiIconKey {
CaretRight,
CaretUpDown,
Plus,
+ Settings,
}
impl RadrootsAppUiIconKey {
@@ -16,6 +17,7 @@ impl RadrootsAppUiIconKey {
RadrootsAppUiIconKey::CaretRight => "caret-right",
RadrootsAppUiIconKey::CaretUpDown => "caret-up-down",
RadrootsAppUiIconKey::Plus => "plus",
+ RadrootsAppUiIconKey::Settings => "settings",
}
}
}
@@ -25,6 +27,7 @@ pub fn radroots_app_ui_icon_key_from_name(name: &str) -> Option<RadrootsAppUiIco
"caret-right" | "chevron-right" => Some(RadrootsAppUiIconKey::CaretRight),
"caret-up-down" | "chevrons-up-down" => Some(RadrootsAppUiIconKey::CaretUpDown),
"plus" => Some(RadrootsAppUiIconKey::Plus),
+ "settings" | "gear" => Some(RadrootsAppUiIconKey::Settings),
_ => None,
}
}
@@ -34,6 +37,7 @@ pub fn radroots_app_ui_icon_data(key: RadrootsAppUiIconKey) -> Icon {
RadrootsAppUiIconKey::CaretRight => LuChevronRight,
RadrootsAppUiIconKey::CaretUpDown => LuChevronsUpDown,
RadrootsAppUiIconKey::Plus => LuPlus,
+ RadrootsAppUiIconKey::Settings => LuSettings,
}
}
@@ -104,12 +108,20 @@ mod tests {
radroots_app_ui_icon_key_from_name("plus"),
Some(RadrootsAppUiIconKey::Plus)
);
+ assert_eq!(
+ radroots_app_ui_icon_key_from_name("settings"),
+ Some(RadrootsAppUiIconKey::Settings)
+ );
+ assert_eq!(
+ radroots_app_ui_icon_key_from_name("gear"),
+ Some(RadrootsAppUiIconKey::Settings)
+ );
assert_eq!(radroots_app_ui_icon_key_from_name("unknown"), None);
}
#[test]
fn icon_data_resolves() {
- let icon = radroots_app_ui_icon_data(RadrootsAppUiIconKey::Plus);
+ let icon = radroots_app_ui_icon_data(RadrootsAppUiIconKey::Settings);
assert!(!icon.data.is_empty());
}
}