/ web / src / components / navbar.rs
navbar.rs
 1  use crate::Route;
 2  use crate::APIDAE_SYMBOL;
 3  use dioxus::prelude::*;
 4  use lucide_dioxus::{Cpu, MemoryStick, Search, Wifi};
 5  use ui::components::button::{Button, ButtonSize, ButtonVariant};
 6  
 7  #[component]
 8  pub fn Navbar(
 9      on_search: EventHandler<()>,
10      on_network: EventHandler<()>,
11      chip_model: String,
12      heap_memory: String,
13  ) -> Element {
14      rsx! {
15          header {
16              class: "sticky top-0 z-20 border-b border-border bg-background/60 backdrop-blur-md",
17              div {
18                  class: "mx-auto w-[min(100%-24px,980px)] grid grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 min-h-[62px]",
19  
20                  Link {
21                      to: Route::Home {},
22                      class: "inline-flex items-center gap-2 text-foreground no-underline font-semibold",
23                      img { class: "w-7 h-7", src: APIDAE_SYMBOL }
24                      span { "Apidae Systems" }
25                  }
26  
27                  Button {
28                      variant: ButtonVariant::Outline,
29                      size: ButtonSize::Small,
30                      on_click: move |_| on_search.call(()),
31                      icon_left: rsx! { Search { class: "w-4 h-4 text-muted-foreground" } },
32                      span { class: "text-muted-foreground", "Search..." }
33                      span { class: "text-xs text-muted-foreground bg-muted px-1.5 py-0.5 rounded", "Ctrl+K" }
34                  }
35  
36                  div { class: "justify-self-end inline-flex items-center gap-2",
37                      if !chip_model.is_empty() {
38                          span { class: "inline-flex items-center gap-1.5 rounded-full border border-border bg-background/60 px-2.5 py-1 text-xs font-mono text-foreground",
39                              Cpu { class: "w-3.5 h-3.5" }
40                              "{chip_model}"
41                          }
42                          span { class: "inline-flex items-center gap-1.5 rounded-full border border-border bg-background/60 px-2.5 py-1 text-xs font-mono text-foreground",
43                              MemoryStick { class: "w-3.5 h-3.5" }
44                              "{heap_memory}"
45                          }
46                      } else {
47                          span { class: "inline-flex items-center gap-1.5 rounded-full border border-border bg-background/60 px-2.5 py-1",
48                              div { class: "w-3.5 h-3.5 bg-muted rounded animate-pulse" }
49                              div { class: "w-16 h-3.5 bg-muted rounded animate-pulse" }
50                          }
51                          span { class: "inline-flex items-center gap-1.5 rounded-full border border-border bg-background/60 px-2.5 py-1",
52                              div { class: "w-3.5 h-3.5 bg-muted rounded animate-pulse" }
53                              div { class: "w-20 h-3.5 bg-muted rounded animate-pulse" }
54                          }
55                      }
56                      div {
57                          onmouseenter: move |_| on_network.call(()),
58                          Button {
59                              variant: ButtonVariant::Ghost,
60                              size: ButtonSize::Small,
61                              is_icon_button: true,
62                              aria_label: "Network settings".to_string(),
63                              on_click: move |_| on_network.call(()),
64                              Wifi { class: "w-3.5 h-3.5" }
65                          }
66                      }
67                  }
68              }
69          }
70      }
71  }