feat: add Dioxus and GPUI UI prototypes for framework comparison
Dioxus (ui-dioxus/): 2,169 lines, WebView mode (same wry as Tauri), Catppuccin theme, 12 components, agor-core integration, compiles clean. Evolution path — keeps xterm.js, gradual migration from Tauri. GPUI (ui-gpui/): 2,490 lines, GPU-accelerated rendering, alacritty_terminal for native terminal, 17 files, Catppuccin palette, demo data. Revolution path — pure Rust UI, 120fps target, no WebView. Both are standalone (not in workspace), share agor-core backend. Created for side-by-side comparison to inform framework decision.
This commit is contained in:
parent
90c7315336
commit
f3d2ca78ba
34 changed files with 17467 additions and 0 deletions
151
ui-dioxus/src/components/settings.rs
Normal file
151
ui-dioxus/src/components/settings.rs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
/// Settings panel — drawer that slides out from the sidebar.
|
||||
///
|
||||
/// Mirrors the Svelte app's SettingsTab.svelte: theme selection, font controls,
|
||||
/// provider configuration. Uses the same drawer pattern (18rem wide,
|
||||
/// mantle background).
|
||||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn SettingsPanel() -> Element {
|
||||
let mut theme = use_signal(|| "Catppuccin Mocha".to_string());
|
||||
let mut ui_font = use_signal(|| "Inter".to_string());
|
||||
let mut term_font = use_signal(|| "JetBrains Mono".to_string());
|
||||
let mut default_shell = use_signal(|| "/bin/bash".to_string());
|
||||
|
||||
rsx! {
|
||||
div { class: "drawer-panel",
|
||||
div { class: "drawer-title", "Settings" }
|
||||
|
||||
// Appearance section
|
||||
div { class: "settings-section",
|
||||
div { class: "settings-section-title", "Appearance" }
|
||||
|
||||
div { class: "settings-row",
|
||||
span { class: "settings-label", "Theme" }
|
||||
select {
|
||||
class: "settings-select",
|
||||
value: "{theme}",
|
||||
onchange: move |e| theme.set(e.value()),
|
||||
option { value: "Catppuccin Mocha", "Catppuccin Mocha" }
|
||||
option { value: "Catppuccin Macchiato", "Catppuccin Macchiato" }
|
||||
option { value: "Tokyo Night", "Tokyo Night" }
|
||||
option { value: "Dracula", "Dracula" }
|
||||
option { value: "Nord", "Nord" }
|
||||
}
|
||||
}
|
||||
|
||||
div { class: "settings-row",
|
||||
span { class: "settings-label", "UI Font" }
|
||||
select {
|
||||
class: "settings-select",
|
||||
value: "{ui_font}",
|
||||
onchange: move |e| ui_font.set(e.value()),
|
||||
option { value: "Inter", "Inter" }
|
||||
option { value: "system-ui", "System UI" }
|
||||
option { value: "IBM Plex Sans", "IBM Plex Sans" }
|
||||
}
|
||||
}
|
||||
|
||||
div { class: "settings-row",
|
||||
span { class: "settings-label", "Terminal Font" }
|
||||
select {
|
||||
class: "settings-select",
|
||||
value: "{term_font}",
|
||||
onchange: move |e| term_font.set(e.value()),
|
||||
option { value: "JetBrains Mono", "JetBrains Mono" }
|
||||
option { value: "Fira Code", "Fira Code" }
|
||||
option { value: "Cascadia Code", "Cascadia Code" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Defaults section
|
||||
div { class: "settings-section",
|
||||
div { class: "settings-section-title", "Defaults" }
|
||||
|
||||
div { class: "settings-row",
|
||||
span { class: "settings-label", "Shell" }
|
||||
select {
|
||||
class: "settings-select",
|
||||
value: "{default_shell}",
|
||||
onchange: move |e| default_shell.set(e.value()),
|
||||
option { value: "/bin/bash", "/bin/bash" }
|
||||
option { value: "/bin/zsh", "/bin/zsh" }
|
||||
option { value: "/usr/bin/fish", "/usr/bin/fish" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Providers section
|
||||
div { class: "settings-section",
|
||||
div { class: "settings-section-title", "Providers" }
|
||||
|
||||
ProviderCard {
|
||||
name: "Claude",
|
||||
model: "claude-sonnet-4-20250514",
|
||||
status: "Available",
|
||||
accent: "var(--ctp-mauve)",
|
||||
}
|
||||
ProviderCard {
|
||||
name: "Codex",
|
||||
model: "gpt-5.4",
|
||||
status: "Available",
|
||||
accent: "var(--ctp-green)",
|
||||
}
|
||||
ProviderCard {
|
||||
name: "Ollama",
|
||||
model: "qwen3:8b",
|
||||
status: "Not running",
|
||||
accent: "var(--ctp-peach)",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn ProviderCard(
|
||||
name: String,
|
||||
model: String,
|
||||
status: String,
|
||||
accent: String,
|
||||
) -> Element {
|
||||
let is_available = status == "Available";
|
||||
|
||||
let badge_bg = if is_available {
|
||||
"color-mix(in srgb, var(--ctp-green) 15%, transparent)"
|
||||
} else {
|
||||
"color-mix(in srgb, var(--ctp-overlay0) 15%, transparent)"
|
||||
};
|
||||
let badge_color = if is_available {
|
||||
"var(--ctp-green)"
|
||||
} else {
|
||||
"var(--ctp-overlay0)"
|
||||
};
|
||||
let badge_style = format!(
|
||||
"font-size: 0.625rem; padding: 0.0625rem 0.3125rem; border-radius: 0.1875rem; background: {badge_bg}; color: {badge_color};"
|
||||
);
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
style: "background: var(--ctp-surface0); border-radius: 0.375rem; padding: 0.5rem 0.75rem; margin-bottom: 0.5rem;",
|
||||
|
||||
div {
|
||||
style: "display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.25rem;",
|
||||
span {
|
||||
style: "font-weight: 600; font-size: 0.8125rem; color: {accent};",
|
||||
"{name}"
|
||||
}
|
||||
span {
|
||||
style: "{badge_style}",
|
||||
"{status}"
|
||||
}
|
||||
}
|
||||
div {
|
||||
style: "font-size: 0.6875rem; color: var(--ctp-overlay1); font-family: var(--term-font-family);",
|
||||
"{model}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue