Move sidebar navigation to separate module
Some checks failed
Push Workflows / test (push) Failing after 9m50s
Push Workflows / build (push) Failing after 16m49s
Push Workflows / docker-build (push) Failing after 21m36s
Push Workflows / docs (push) Successful in 4m49s
Push Workflows / leptos-test (push) Successful in 14m36s
Push Workflows / clippy (push) Successful in 5m9s
Push Workflows / nix-build (push) Failing after 26m50s

This commit is contained in:
Ethan Girouard 2025-03-07 23:26:11 -05:00
parent f1862a6bd6
commit 6572d7313a
Signed by: eta357
GPG Key ID: 7BCDC36DFD11C146
4 changed files with 110 additions and 46 deletions

95
src/components/menu.rs Normal file
View File

@ -0,0 +1,95 @@
use leptos::prelude::*;
use leptos_icons::*;
use crate::components::upload_dropdown::*;
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum MenuEntry {
Dashboard,
Search,
}
impl MenuEntry {
pub const fn path(&self) -> &'static str {
match self {
MenuEntry::Dashboard => "/dashboard",
MenuEntry::Search => "/search",
}
}
pub const fn icon(&self) -> icondata::Icon {
match self {
MenuEntry::Dashboard => icondata::OcHomeFillLg,
MenuEntry::Search => icondata::BiSearchRegular,
}
}
pub const fn title(&self) -> &'static str {
match self {
MenuEntry::Dashboard => "Dashboard",
MenuEntry::Search => "Search",
}
}
pub const fn all() -> [MenuEntry; 2] {
[
MenuEntry::Dashboard,
MenuEntry::Search,
]
}
}
#[component]
pub fn MenuItem(entry: MenuEntry, #[prop(into)] active: Signal<bool>) -> impl IntoView {
view! {
<a class="menu-btn" href={entry.path().to_string()}
style={move || if active() {"color: var(--color-menu-active);"} else {""}}
>
<Icon height="1.7rem" width="1.7rem" icon={entry.icon()} {..} class="mr-2" />
<h2>{entry.title()}</h2>
</a>
}
}
#[component]
pub fn Menu(upload_open: RwSignal<bool>, add_artist_open: RwSignal<bool>, add_album_open: RwSignal<bool>) -> impl IntoView {
use leptos_router::hooks::use_location;
let location = use_location();
let active_entry = Signal::derive(move || {
let path = location.pathname.get();
MenuEntry::all().into_iter().find(|entry| entry.path() == path)
});
let dropdown_open = RwSignal::new(false);
view! {
<div class="home-card">
<Show
when=move || {upload_open.get() || add_artist_open.get() || add_album_open.get()}
fallback=move || view! {}
>
<div class="upload-overlay" on:click=move |_| {
upload_open.set(false);
add_artist_open.set(false);
add_album_open.set(false);
}></div>
</Show>
<div class="flex">
<h1 class="text-xl font-bold">"LibreTunes"</h1>
<div class="upload-dropdown-container">
<UploadDropdownBtn dropdown_open=dropdown_open/>
<Show
when= move || dropdown_open()
fallback=move || view! {}
>
<UploadDropdown dropdown_open=dropdown_open upload_open=upload_open add_artist_open=add_artist_open add_album_open=add_album_open/>
</Show>
</div>
</div>
{MenuEntry::all().into_iter().map(|entry| {
let active = Signal::derive(move || active_entry.get() == Some(entry));
view! { <MenuItem entry active /> }
}).collect::<Vec<_>>()}
</div>
}
}

View File

@ -15,3 +15,4 @@ pub mod playbar;
pub mod song;
pub mod error_template;
pub mod fancy_input;
pub mod menu;

View File

@ -1,56 +1,13 @@
use leptos::prelude::*;
use leptos_icons::*;
use crate::components::upload_dropdown::*;
use crate::components::menu::*;
#[component]
pub fn Sidebar(upload_open: RwSignal<bool>, add_artist_open: RwSignal<bool>, add_album_open: RwSignal<bool>) -> impl IntoView {
use leptos_router::hooks::use_location;
let location = use_location();
let dropdown_open = RwSignal::new(false);
let on_dashboard = Signal::derive(
move || location.pathname.get().starts_with("/dashboard") || location.pathname.get() == "/",
);
let on_search = Signal::derive(
move || location.pathname.get().starts_with("/search"),
);
view! {
<div class="sidebar-container">
<div class="sidebar-top-container">
<Show
when=move || {upload_open.get() || add_artist_open.get() || add_album_open.get()}
fallback=move || view! {}
>
<div class="upload-overlay" on:click=move |_| {
upload_open.set(false);
add_artist_open.set(false);
add_album_open.set(false);
}></div>
</Show>
<h2 class="header">LibreTunes</h2>
<div class="upload-dropdown-container">
<UploadDropdownBtn dropdown_open=dropdown_open/>
<Show
when= move || dropdown_open()
fallback=move || view! {}
>
<UploadDropdown dropdown_open=dropdown_open upload_open=upload_open add_artist_open=add_artist_open add_album_open=add_album_open/>
</Show>
</div>
<a class="buttons" href="/dashboard" style={move || if on_dashboard() {"color: #e1e3e1"} else {""}} >
<Icon icon={icondata::OcHomeFillLg} />
<h1>Dashboard</h1>
</a>
<a class="buttons" href="/search" style={move || if on_search() {"color: #e1e3e1"} else {""}}>
<Icon icon={icondata::BiSearchRegular} />
<h1>Search</h1>
</a>
</div>
<div class="flex flex-col">
<Menu upload_open add_artist_open add_album_open />
<Playlists />
</div>
}
}

View File

@ -8,6 +8,7 @@
--color-controls: #e0e0e0;
--color-controls-hover: #c0c0c0;
--color-controls-active: #a0a0a0;
--color-menu-active: white;
--color-play-grad-start: #0a0533;
--color-play-grad-end: var(--color-accent);
}
@ -37,4 +38,14 @@
@apply last-of-type:pb-[85px]; /* Hard-coded height of the playbar + 5px */
@apply overflow-scroll;
}
.menu-btn {
@apply flex;
@apply items-center;
@apply text-base;
@apply mt-3;
@apply text-neutral-400;
@apply hover:text-neutral-500;
@apply active:text-neutral-600;
}
}