feat: Routing fuer Workspace-Auswahl und Editor aufbauen

Zwei Router: WorkspaceRoute (Workspace anlegen/oeffnen) und EditorRoute
(Home/Editor), umgeschaltet ueber ein Signal in App.

Die Navigationslinks werden nicht mehr einzeln ausgeschrieben, sondern aus
dem Routen-Enum erzeugt (strum EnumIter). Die Beschriftung haengt per
#[strum(message = "...")] an der Variante selbst, damit eine neue Route nur
an einer Stelle gepflegt werden muss.

CustomLink kapselt Link und markiert den aktiven Eintrag ueber active_class
statt ueber eigenen Klick-Zustand - das funktioniert auch bei Deep-Links und
dem Zurueck-Button.
This commit is contained in:
2026-08-27 14:00:27 +02:00
parent 2a1d5528cd
commit fe1d736a2d
11 changed files with 234 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
use dioxus::prelude::*;
use dioxus_code::Theme;
use dioxus_code_editor::{CodeEditor, Language};
use crate::components::custom_link::custom_link_component::CustomLink;
use strum::{EnumMessage, IntoEnumIterator};
use strum_macros::EnumIter;
const HEADER_SVG: Asset = asset!("/assets/header.svg");
#[derive(Debug, Clone, Routable, PartialEq, EnumIter, EnumMessage)]
#[rustfmt::skip]
pub enum EditorRoute {
#[layout(Navbar)]
#[route("/")]
#[strum(message = "Home")]
Home {},
#[route("/editor")]
#[strum(message = "Editor")]
Editor {},
}
/// Home page
#[component]
fn Home() -> Element {
rsx! {
Hero {}
}
}
#[component]
pub fn Hero() -> Element {
rsx! {
div {
id: "hero",
img { src: HEADER_SVG, id: "header" }
div { id: "links",
a { href: "https://dioxuslabs.com/learn/0.7/", "📚 Learn Dioxus" }
a { href: "https://dioxuslabs.com/awesome", "🚀 Awesome Dioxus" }
a { href: "https://github.com/dioxus-community/", "📡 Community Libraries" }
a { href: "https://github.com/DioxusLabs/sdk", "⚙️ Dioxus Development Kit" }
a { href: "https://marketplace.visualstudio.com/items?itemName=DioxusLabs.dioxus", "💫 VSCode Extension" }
a { href: "https://discord.gg/XgGxMSkvUM", "👋 Community Discord" }
}
}
}
}
#[component]
fn Editor() -> Element {
let mut source = use_signal(String::new);
rsx! {
CodeEditor {
class: "editor-class",
value: source(),
language: Language::Markdown,
theme: Theme::CATPPUCCIN_MOCHA,
oninput: move |value| source.set(value),
}
}
}
/// Shared navbar component.
#[component]
fn Navbar() -> Element {
rsx! {
div {
class: "layout-container",
div {
class: "files-bar",
for entry in EditorRoute::iter() {
CustomLink {
key: "{entry}",
label: entry.get_message().unwrap_or_default(),
href: entry.clone(),
css: "file-selector"
}
}
}
div {
class: "editor-container",
Outlet::<EditorRoute> { }
}
}
}
}