ssh: Refine the modal UI (#19256)

This PR refines the SSH modal UI, adjusting spacing and alignment. Via
these changes, I'm also introducing the ability for the `empty_message`
on the `List` component to receive not just a string but any element.
The custom way in which the SSH modal was designed made it feel like
this was needed for proper spacing.

<img width="700" alt="Screenshot 2024-10-16 at 1 20 54 AM"
src="https://github.com/user-attachments/assets/f2e0586b-4c9f-4497-b4cb-e90c8157512b">


Release Notes:

- N/A
This commit is contained in:
Danilo Leal 2024-10-16 01:39:27 +02:00 committed by GitHub
parent b752548742
commit b64919aa11
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 111 additions and 84 deletions

View file

@ -5,11 +5,16 @@ use smallvec::SmallVec;
use crate::{prelude::*, v_flex, Label, ListHeader};
pub enum EmptyMessage {
Text(SharedString),
Element(AnyElement),
}
#[derive(IntoElement)]
pub struct List {
/// Message to display when the list is empty
/// Defaults to "No items"
empty_message: SharedString,
empty_message: EmptyMessage,
header: Option<ListHeader>,
toggle: Option<bool>,
children: SmallVec<[AnyElement; 2]>,
@ -24,15 +29,15 @@ impl Default for List {
impl List {
pub fn new() -> Self {
Self {
empty_message: "No items".into(),
empty_message: EmptyMessage::Text("No items".into()),
header: None,
toggle: None,
children: SmallVec::new(),
}
}
pub fn empty_message(mut self, empty_message: impl Into<SharedString>) -> Self {
self.empty_message = empty_message.into();
pub fn empty_message(mut self, message: impl Into<EmptyMessage>) -> Self {
self.empty_message = message.into();
self
}
@ -53,6 +58,24 @@ impl ParentElement for List {
}
}
impl From<String> for EmptyMessage {
fn from(s: String) -> Self {
EmptyMessage::Text(SharedString::from(s))
}
}
impl From<&str> for EmptyMessage {
fn from(s: &str) -> Self {
EmptyMessage::Text(SharedString::from(s.to_owned()))
}
}
impl From<AnyElement> for EmptyMessage {
fn from(e: AnyElement) -> Self {
EmptyMessage::Element(e)
}
}
impl RenderOnce for List {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
v_flex()
@ -62,7 +85,10 @@ impl RenderOnce for List {
.map(|this| match (self.children.is_empty(), self.toggle) {
(false, _) => this.children(self.children),
(true, Some(false)) => this,
(true, _) => this.child(Label::new(self.empty_message.clone()).color(Color::Muted)),
(true, _) => match self.empty_message {
EmptyMessage::Text(text) => this.child(Label::new(text).color(Color::Muted)),
EmptyMessage::Element(element) => this.child(element),
},
})
}
}

View file

@ -77,6 +77,7 @@ impl RenderOnce for Modal {
v_flex()
.id(self.container_id.clone())
.w_full()
.flex_1()
.gap(Spacing::Large.rems(cx))
.when_some(
self.container_scroll_handler,
@ -344,6 +345,7 @@ impl RenderOnce for Section {
} else {
v_flex()
.w_full()
.flex_1()
.gap_y(Spacing::Small.rems(cx))
.when(self.padded, |this| {
this.px(Spacing::Medium.rems(cx) + Spacing::Medium.rems(cx))