mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-26 20:22:30 +00:00
Allow ListHeader to take a meta
This commit is contained in:
parent
6ed60769ac
commit
8dafd5f1f3
9 changed files with 105 additions and 74 deletions
1
assets/icons/at-sign.svg
Normal file
1
assets/icons/at-sign.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-at-sign"><circle cx="12" cy="12" r="4"/><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8"/></svg>
|
After Width: | Height: | Size: 300 B |
1
assets/icons/bell-off.svg
Normal file
1
assets/icons/bell-off.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell-off"><path d="M8.7 3A6 6 0 0 1 18 8a21.3 21.3 0 0 0 .6 5"/><path d="M17 17H3s3-2 3-9a4.67 4.67 0 0 1 .3-1.7"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/><path d="m2 2 20 20"/></svg>
|
After Width: | Height: | Size: 387 B |
1
assets/icons/bell-ring.svg
Normal file
1
assets/icons/bell-ring.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell-ring"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/><path d="M4 2C2.8 3.7 2 5.7 2 8"/><path d="M22 8c0-2.3-.8-4.3-2-6"/></svg>
|
After Width: | Height: | Size: 382 B |
|
@ -1,8 +1 @@
|
|||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M8.60124 1.25086C8.60124 1.75459 8.26278 2.17927 7.80087 2.30989C10.1459 2.4647 12 4.41582 12 6.79999V10.25C12 11.0563 12.0329 11.7074 12.7236 12.0528C12.931 12.1565 13.0399 12.3892 12.9866 12.6149C12.9333 12.8406 12.7319 13 12.5 13H8.16144C8.36904 13.1832 8.49997 13.4513 8.49997 13.75C8.49997 14.3023 8.05226 14.75 7.49997 14.75C6.94769 14.75 6.49997 14.3023 6.49997 13.75C6.49997 13.4513 6.63091 13.1832 6.83851 13H2.49999C2.2681 13 2.06664 12.8406 2.01336 12.6149C1.96009 12.3892 2.06897 12.1565 2.27638 12.0528C2.96708 11.7074 2.99999 11.0563 2.99999 10.25V6.79999C2.99999 4.41537 4.85481 2.46396 7.20042 2.3098C6.73867 2.17908 6.40036 1.75448 6.40036 1.25086C6.40036 0.643104 6.89304 0.150421 7.5008 0.150421C8.10855 0.150421 8.60124 0.643104 8.60124 1.25086ZM7.49999 3.29999C5.56699 3.29999 3.99999 4.86699 3.99999 6.79999V10.25L4.00002 10.3009C4.0005 10.7463 4.00121 11.4084 3.69929 12H11.3007C10.9988 11.4084 10.9995 10.7463 11 10.3009L11 10.25V6.79999C11 4.86699 9.43299 3.29999 7.49999 3.29999Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg>
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 309 B |
1
assets/icons/mail-open.svg
Normal file
1
assets/icons/mail-open.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mail-open"><path d="M21.2 8.4c.5.38.8.97.8 1.6v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V10a2 2 0 0 1 .8-1.6l8-6a2 2 0 0 1 2.4 0l8 6Z"/><path d="m22 10-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 10"/></svg>
|
After Width: | Height: | Size: 390 B |
|
@ -15,12 +15,20 @@ pub enum ListItemVariant {
|
|||
Inset,
|
||||
}
|
||||
|
||||
pub enum ListHeaderMeta {
|
||||
// TODO: These should be IconButtons
|
||||
Tools(Vec<Icon>),
|
||||
// TODO: This should be a button
|
||||
Button(Label),
|
||||
Text(Label),
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct ListHeader {
|
||||
label: SharedString,
|
||||
left_icon: Option<Icon>,
|
||||
meta: Option<ListHeaderMeta>,
|
||||
variant: ListItemVariant,
|
||||
state: InteractionState,
|
||||
toggleable: Toggleable,
|
||||
}
|
||||
|
||||
|
@ -29,8 +37,8 @@ impl ListHeader {
|
|||
Self {
|
||||
label: label.into(),
|
||||
left_icon: None,
|
||||
meta: None,
|
||||
variant: ListItemVariant::default(),
|
||||
state: InteractionState::default(),
|
||||
toggleable: Toggleable::Toggleable(ToggleState::Toggled),
|
||||
}
|
||||
}
|
||||
|
@ -50,8 +58,8 @@ impl ListHeader {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn state(mut self, state: InteractionState) -> Self {
|
||||
self.state = state;
|
||||
pub fn meta(mut self, meta: Option<ListHeaderMeta>) -> Self {
|
||||
self.meta = meta;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -74,34 +82,37 @@ impl ListHeader {
|
|||
}
|
||||
}
|
||||
|
||||
fn label_color(&self) -> LabelColor {
|
||||
match self.state {
|
||||
InteractionState::Disabled => LabelColor::Disabled,
|
||||
_ => Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn icon_color(&self) -> IconColor {
|
||||
match self.state {
|
||||
InteractionState::Disabled => IconColor::Disabled,
|
||||
_ => Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
|
||||
let is_toggleable = self.toggleable != Toggleable::NotToggleable;
|
||||
let is_toggled = self.toggleable.is_toggled();
|
||||
|
||||
let disclosure_control = self.disclosure_control();
|
||||
|
||||
let meta = match self.meta {
|
||||
Some(ListHeaderMeta::Tools(icons)) => div().child(
|
||||
h_stack()
|
||||
.gap_2()
|
||||
.items_center()
|
||||
.children(icons.into_iter().map(|i| {
|
||||
IconElement::new(i)
|
||||
.color(IconColor::Muted)
|
||||
.size(IconSize::Small)
|
||||
})),
|
||||
),
|
||||
Some(ListHeaderMeta::Button(label)) => div().child(label),
|
||||
Some(ListHeaderMeta::Text(label)) => div().child(label),
|
||||
None => div(),
|
||||
};
|
||||
|
||||
h_stack()
|
||||
.flex_1()
|
||||
.w_full()
|
||||
.bg(cx.theme().colors().surface)
|
||||
.when(self.state == InteractionState::Focused, |this| {
|
||||
this.border()
|
||||
.border_color(cx.theme().colors().border_focused)
|
||||
})
|
||||
// TODO: Add focus state
|
||||
// .when(self.state == InteractionState::Focused, |this| {
|
||||
// this.border()
|
||||
// .border_color(cx.theme().colors().border_focused)
|
||||
// })
|
||||
.relative()
|
||||
.child(
|
||||
div()
|
||||
|
@ -109,22 +120,28 @@ impl ListHeader {
|
|||
.when(self.variant == ListItemVariant::Inset, |this| this.px_2())
|
||||
.flex()
|
||||
.flex_1()
|
||||
.items_center()
|
||||
.justify_between()
|
||||
.w_full()
|
||||
.gap_1()
|
||||
.items_center()
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
h_stack()
|
||||
.gap_1()
|
||||
.items_center()
|
||||
.children(self.left_icon.map(|i| {
|
||||
IconElement::new(i)
|
||||
.color(IconColor::Muted)
|
||||
.size(IconSize::Small)
|
||||
}))
|
||||
.child(Label::new(self.label.clone()).color(LabelColor::Muted)),
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.gap_1()
|
||||
.items_center()
|
||||
.children(self.left_icon.map(|i| {
|
||||
IconElement::new(i)
|
||||
.color(IconColor::Muted)
|
||||
.size(IconSize::Small)
|
||||
}))
|
||||
.child(Label::new(self.label.clone()).color(LabelColor::Muted)),
|
||||
)
|
||||
.child(disclosure_control),
|
||||
)
|
||||
.child(disclosure_control),
|
||||
.child(meta),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -593,6 +610,7 @@ impl<V: 'static> List<V> {
|
|||
};
|
||||
|
||||
v_stack()
|
||||
.w_full()
|
||||
.py_1()
|
||||
.children(self.header.map(|header| header.toggleable(self.toggleable)))
|
||||
.child(list_content)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{prelude::*, static_new_notification_items, static_read_notification_items};
|
||||
use crate::{prelude::*, static_new_notification_items, Icon, ListHeaderMeta};
|
||||
use crate::{List, ListHeader};
|
||||
|
||||
#[derive(Component)]
|
||||
|
@ -28,14 +28,16 @@ impl NotificationsPanel {
|
|||
.overflow_y_scroll()
|
||||
.child(
|
||||
List::new(static_new_notification_items())
|
||||
.header(ListHeader::new("NEW").toggle(ToggleState::Toggled))
|
||||
.toggle(ToggleState::Toggled),
|
||||
)
|
||||
.child(
|
||||
List::new(static_read_notification_items())
|
||||
.header(ListHeader::new("EARLIER").toggle(ToggleState::Toggled))
|
||||
.empty_message("No new notifications")
|
||||
.toggle(ToggleState::Toggled),
|
||||
.toggle(ToggleState::Toggled)
|
||||
.header(
|
||||
ListHeader::new("Notifications")
|
||||
.toggle(ToggleState::Toggled)
|
||||
.meta(Some(ListHeaderMeta::Tools(vec![
|
||||
Icon::AtSign,
|
||||
Icon::BellOff,
|
||||
Icon::MailOpen,
|
||||
]))),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ impl IconColor {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Copy, Clone, EnumIter)]
|
||||
#[derive(Debug, PartialEq, Copy, Clone, EnumIter)]
|
||||
pub enum Icon {
|
||||
Ai,
|
||||
ArrowLeft,
|
||||
|
@ -67,7 +67,6 @@ pub enum Icon {
|
|||
Folder,
|
||||
FolderOpen,
|
||||
FolderX,
|
||||
#[default]
|
||||
Hash,
|
||||
InlayHint,
|
||||
MagicWand,
|
||||
|
@ -89,6 +88,11 @@ pub enum Icon {
|
|||
XCircle,
|
||||
Copilot,
|
||||
Envelope,
|
||||
Bell,
|
||||
BellOff,
|
||||
BellRing,
|
||||
MailOpen,
|
||||
AtSign,
|
||||
}
|
||||
|
||||
impl Icon {
|
||||
|
@ -140,6 +144,11 @@ impl Icon {
|
|||
Icon::XCircle => "icons/error.svg",
|
||||
Icon::Copilot => "icons/copilot.svg",
|
||||
Icon::Envelope => "icons/feedback.svg",
|
||||
Icon::Bell => "icons/bell.svg",
|
||||
Icon::BellOff => "icons/bell-off.svg",
|
||||
Icon::BellRing => "icons/bell-ring.svg",
|
||||
Icon::MailOpen => "icons/mail-open.svg",
|
||||
Icon::AtSign => "icons/at-sign.svg",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,10 @@ use theme2::ActiveTheme;
|
|||
|
||||
use crate::{
|
||||
Buffer, BufferRow, BufferRows, Button, EditorPane, FileSystemStatus, GitStatus,
|
||||
HighlightedLine, Icon, Keybinding, Label, LabelColor, ListEntry, ListEntrySize, ListItem,
|
||||
Livestream, MicStatus, ModifierKeys, PaletteItem, Player, PlayerCallStatus,
|
||||
PlayerWithCallStatus, ScreenShareStatus, Symbol, Tab, ToggleState, VideoStatus,
|
||||
HighlightedLine, Icon, Keybinding, Label, LabelColor, ListEntry, ListEntrySize, ListHeaderMeta,
|
||||
ListItem, ListSubHeader, Livestream, MicStatus, ModifierKeys, PaletteItem, Player,
|
||||
PlayerCallStatus, PlayerWithCallStatus, ScreenShareStatus, Symbol, Tab, ToggleState,
|
||||
VideoStatus,
|
||||
};
|
||||
use crate::{HighlightedText, ListDetailsEntry};
|
||||
|
||||
|
@ -327,25 +328,29 @@ pub fn static_players_with_call_status() -> Vec<PlayerWithCallStatus> {
|
|||
|
||||
pub fn static_new_notification_items<V: 'static>() -> Vec<ListItem<V>> {
|
||||
vec![
|
||||
ListDetailsEntry::new("maxdeviant invited you to join a stream in #design.")
|
||||
.meta("4 people in stream."),
|
||||
ListDetailsEntry::new("nathansobo accepted your contact request."),
|
||||
]
|
||||
.into_iter()
|
||||
.map(From::from)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn static_read_notification_items<V: 'static>() -> Vec<ListItem<V>> {
|
||||
vec![
|
||||
ListDetailsEntry::new("mikaylamaki added you as a contact.").actions(vec![
|
||||
Button::new("Decline"),
|
||||
Button::new("Accept").variant(crate::ButtonVariant::Filled),
|
||||
]),
|
||||
ListDetailsEntry::new("maxdeviant invited you to a stream in #design.")
|
||||
.seen(true)
|
||||
.meta("This stream has ended."),
|
||||
ListDetailsEntry::new("as-cii accepted your contact request."),
|
||||
ListItem::Header(ListSubHeader::new("New")),
|
||||
ListItem::Details(
|
||||
ListDetailsEntry::new("maxdeviant invited you to join a stream in #design.")
|
||||
.meta("4 people in stream."),
|
||||
),
|
||||
ListItem::Details(ListDetailsEntry::new(
|
||||
"nathansobo accepted your contact request.",
|
||||
)),
|
||||
ListItem::Header(ListSubHeader::new("Earlier")),
|
||||
ListItem::Details(
|
||||
ListDetailsEntry::new("mikaylamaki added you as a contact.").actions(vec![
|
||||
Button::new("Decline"),
|
||||
Button::new("Accept").variant(crate::ButtonVariant::Filled),
|
||||
]),
|
||||
),
|
||||
ListItem::Details(
|
||||
ListDetailsEntry::new("maxdeviant invited you to a stream in #design.")
|
||||
.seen(true)
|
||||
.meta("This stream has ended."),
|
||||
),
|
||||
ListItem::Details(ListDetailsEntry::new(
|
||||
"as-cii accepted your contact request.",
|
||||
)),
|
||||
]
|
||||
.into_iter()
|
||||
.map(From::from)
|
||||
|
|
Loading…
Reference in a new issue