Files
oak-gpui/crates/ui/src/components/list_item.rs
T
2023-09-21 23:46:06 -04:00

113 lines
3.6 KiB
Rust

use crate::prelude::{DisclosureControlVisibility, InteractionState, ToggleState};
use crate::theme::theme;
use crate::tokens::token;
use crate::{icon, IconAsset, Label};
use gpui2::style::{StyleHelpers, Styleable};
use gpui2::{elements::div, IntoElement};
use gpui2::{Element, ParentElement, ViewContext};
#[derive(Element, Clone)]
pub struct ListItem {
label: Label,
left_icon: Option<IconAsset>,
indent_level: u32,
state: InteractionState,
disclosure_control_style: DisclosureControlVisibility,
toggle: Option<ToggleState>,
}
pub fn list_item(label: Label) -> ListItem {
ListItem {
label,
indent_level: 0,
left_icon: None,
disclosure_control_style: DisclosureControlVisibility::default(),
state: InteractionState::default(),
toggle: None,
}
}
impl ListItem {
pub fn indent_level(mut self, indent_level: u32) -> Self {
self.indent_level = indent_level;
self
}
pub fn set_toggle(mut self, toggle: ToggleState) -> Self {
self.toggle = Some(toggle);
self
}
pub fn left_icon(mut self, left_icon: Option<IconAsset>) -> Self {
self.left_icon = left_icon;
self
}
pub fn state(mut self, state: InteractionState) -> Self {
self.state = state;
self
}
pub fn disclosure_control_style(
mut self,
disclosure_control_style: DisclosureControlVisibility,
) -> Self {
self.disclosure_control_style = disclosure_control_style;
self
}
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
let theme = theme(cx);
let token = token();
let mut disclosure_control = match self.toggle {
Some(ToggleState::NotToggled) => Some(div().child(icon(IconAsset::ChevronRight))),
Some(ToggleState::Toggled) => Some(div().child(icon(IconAsset::ChevronDown))),
None => Some(div()),
};
match self.disclosure_control_style {
DisclosureControlVisibility::OnHover => {
disclosure_control =
disclosure_control.map(|c| div().absolute().neg_left_5().child(c));
}
DisclosureControlVisibility::Always => {}
}
div()
.fill(theme.middle.base.default.background)
.hover()
.fill(theme.middle.base.hovered.background)
.active()
.fill(theme.middle.base.pressed.background)
.relative()
.py_1()
.child(
div()
.h_6()
.px_2()
// .ml(rems(0.75 * self.indent_level as f32))
.children((0..self.indent_level).map(|_| {
div()
.w(token.list_indent_depth)
.h_full()
.flex()
.justify_center()
.child(
div()
.ml_px()
.w_px()
.h_full()
.fill(theme.middle.base.default.border),
)
}))
.flex()
.gap_1()
.items_center()
.relative()
.children(disclosure_control)
.children(self.left_icon.map(|i| icon(i)))
.child(self.label.clone()),
)
}
}