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}