instruction_list_item.rs

 1use gpui::{AnyElement, IntoElement, ParentElement, SharedString};
 2use ui::{ListItem, prelude::*};
 3
 4/// A reusable list item component for adding LLM provider configuration instructions
 5pub struct InstructionListItem {
 6    id: ElementId,
 7    label: SharedString,
 8    button_label: Option<SharedString>,
 9    button_link: Option<String>,
10}
11
12impl InstructionListItem {
13    pub fn new(
14        id: impl Into<ElementId>,
15        label: impl Into<SharedString>,
16        button_label: Option<impl Into<SharedString>>,
17        button_link: Option<impl Into<String>>,
18    ) -> Self {
19        Self {
20            id: id.into(),
21            label: label.into(),
22            button_label: button_label.map(|l| l.into()),
23            button_link: button_link.map(|l| l.into()),
24        }
25    }
26
27    pub fn text_only(label: impl Into<SharedString>) -> Self {
28        Self {
29            id: id.into(),
30            label: label.into(),
31            button_label: None,
32            button_link: None,
33        }
34    }
35}
36
37impl IntoElement for InstructionListItem {
38    type Element = AnyElement;
39
40    fn into_element(self) -> Self::Element {
41        let item_content = if let (Some(button_label), Some(button_link)) =
42            (self.button_label, self.button_link)
43        {
44            h_flex()
45                .flex_wrap()
46                .child(Label::new(self.label))
47                .child(
48                    Button::new("button", button_label)
49                        .style(ButtonStyle::Subtle)
50                        .icon(IconName::ArrowUpRight)
51                        .icon_size(IconSize::Small)
52                        .icon_color(Color::Muted)
53                        .on_click(move |_, _window, cx| cx.open_url(&button_link)),
54                )
55                .into_any_element()
56        } else {
57            Label::new(self.label).into_any_element()
58        };
59
60        ListItem::new(self.id)
61            .selectable(false)
62            .start_slot(
63                Icon::new(IconName::Dash)
64                    .size(IconSize::XSmall)
65                    .color(Color::Hidden),
66            )
67            .child(div().w_full().child(item_content))
68            .into_any_element()
69    }
70}