Add core UI components for TaskWarrior GUI application: Components: - Input: Text input with autocomplete suggestions, keyboard navigation - Button: Multiple variants (Primary, Secondary, Ghost, Danger, Success, Text) - DropdownButton: Compound button with dropdown menu - Icon: SVG icons with customizable sizes - Label: Simple text display - Panel: Container with optional title - List: List container - Modal: Modal dialog - Divider: Visual separator Infrastructure: - Theme system with dark/light modes (Catppuccin colors) - App module with window management
89 lines
2.1 KiB
Rust
89 lines
2.1 KiB
Rust
use gpui::prelude::*;
|
|
|
|
use crate::theme::ActiveTheme;
|
|
|
|
#[derive(gpui::IntoElement)]
|
|
pub struct Panel {
|
|
content: Vec<gpui::AnyElement>,
|
|
title: Option<String>,
|
|
border: f32,
|
|
padding: f32,
|
|
}
|
|
|
|
impl Panel {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
content: Vec::new(),
|
|
title: None,
|
|
border: 1.0,
|
|
padding: 8.0,
|
|
}
|
|
}
|
|
|
|
pub fn title(mut self, title: impl Into<String>) -> Self {
|
|
self.title = Some(title.into());
|
|
self
|
|
}
|
|
|
|
pub fn border(mut self, border: f32) -> Self {
|
|
self.border = border;
|
|
self
|
|
}
|
|
|
|
pub fn padding(mut self, padding: f32) -> Self {
|
|
self.padding = padding;
|
|
self
|
|
}
|
|
|
|
pub fn child(mut self, child: impl gpui::IntoElement) -> Self {
|
|
self.content.push(child.into_any_element());
|
|
self
|
|
}
|
|
|
|
pub fn children<E>(mut self, children: impl IntoIterator<Item = E>) -> Self
|
|
where
|
|
E: gpui::IntoElement,
|
|
{
|
|
self.content
|
|
.extend(children.into_iter().map(|c| c.into_any_element()));
|
|
self
|
|
}
|
|
}
|
|
|
|
impl gpui::RenderOnce for Panel {
|
|
fn render(mut self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoElement {
|
|
let theme = cx.theme();
|
|
|
|
let header = self.title.as_ref().map(|title| {
|
|
gpui::div()
|
|
.px_2()
|
|
.py_1()
|
|
.text_sm()
|
|
.text_color(theme.muted)
|
|
.border_b(gpui::px(self.border))
|
|
.border_color(theme.border)
|
|
.child(title.clone())
|
|
.into_any_element()
|
|
});
|
|
|
|
let children: Vec<gpui::AnyElement> = self
|
|
.content
|
|
.drain(..)
|
|
.enumerate()
|
|
.map(|(ix, c)| gpui::div().id(ix).child(c).into_any_element())
|
|
.collect();
|
|
|
|
gpui::div()
|
|
.size_full()
|
|
.bg(theme.panel)
|
|
.border(gpui::px(self.border))
|
|
.border_color(theme.border)
|
|
.rounded_md()
|
|
.p(gpui::px(self.padding))
|
|
.flex()
|
|
.flex_col()
|
|
.children(header)
|
|
.children(children)
|
|
}
|
|
}
|