chore: Revert changes made to ui crate structure (#17516)

Piotr Osiewicz created

As a part of https://github.com/zed-industries/zed/pull/17488 I
flattened module structure of ui crate to fix module_inception lint.
However, that's actually unnecessary as we can pass that lint via a
custom knob for clippy.

Closes #ISSUE

Release Notes:

- N/A

Change summary

Cargo.toml                                |   2 
clippy.toml                               |   1 
crates/ui/src/components/avatar.rs        | 130 -------
crates/ui/src/components/avatar/avatar.rs | 127 +++++++
crates/ui/src/components/button.rs        | 441 ------------------------
crates/ui/src/components/button/button.rs | 438 ++++++++++++++++++++++++
crates/ui/src/components/label.rs         | 187 ----------
crates/ui/src/components/label/label.rs   | 184 ++++++++++
crates/ui/src/components/list.rs          |  69 ---
crates/ui/src/components/list/list.rs     |   6 
10 files changed, 760 insertions(+), 825 deletions(-)

Detailed changes

Cargo.toml 🔗

@@ -576,7 +576,7 @@ new_ret_no_self = { level = "allow" }
 # We have a few `next` functions that differ in lifetimes
 # compared to Iterator::next. Yet, clippy complains about those.
 should_implement_trait = { level = "allow" }
-
+module_inception = { level = "deny" }
 # Individual rules that have violations in the codebase:
 type_complexity = "allow"
 

crates/ui/src/components/avatar.rs 🔗

@@ -1,133 +1,7 @@
+mod avatar;
 mod avatar_audio_status_indicator;
 mod avatar_availability_indicator;
 
+pub use avatar::*;
 pub use avatar_audio_status_indicator::*;
 pub use avatar_availability_indicator::*;
-
-use crate::prelude::*;
-
-use gpui::{img, AnyElement, Hsla, ImageSource, Img, IntoElement, Styled};
-
-/// The shape of an [`Avatar`].
-#[derive(Debug, Default, PartialEq, Clone)]
-pub enum AvatarShape {
-    /// The avatar is shown in a circle.
-    #[default]
-    Circle,
-    /// The avatar is shown in a rectangle with rounded corners.
-    RoundedRectangle,
-}
-
-/// An element that renders a user avatar with customizable appearance options.
-///
-/// # Examples
-///
-/// ```
-/// use ui::{Avatar, AvatarShape};
-///
-/// Avatar::new("path/to/image.png")
-///     .shape(AvatarShape::Circle)
-///     .grayscale(true)
-///     .border_color(gpui::red());
-/// ```
-#[derive(IntoElement)]
-pub struct Avatar {
-    image: Img,
-    size: Option<AbsoluteLength>,
-    border_color: Option<Hsla>,
-    indicator: Option<AnyElement>,
-}
-
-impl Avatar {
-    pub fn new(src: impl Into<ImageSource>) -> Self {
-        Avatar {
-            image: img(src),
-            size: None,
-            border_color: None,
-            indicator: None,
-        }
-    }
-
-    /// Sets the shape of the avatar image.
-    ///
-    /// This method allows the shape of the avatar to be specified using an [`AvatarShape`].
-    /// It modifies the corner radius of the image to match the specified shape.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::{Avatar, AvatarShape};
-    ///
-    /// Avatar::new("path/to/image.png").shape(AvatarShape::Circle);
-    /// ```
-    pub fn shape(mut self, shape: AvatarShape) -> Self {
-        self.image = match shape {
-            AvatarShape::Circle => self.image.rounded_full(),
-            AvatarShape::RoundedRectangle => self.image.rounded_md(),
-        };
-        self
-    }
-
-    /// Applies a grayscale filter to the avatar image.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::{Avatar, AvatarShape};
-    ///
-    /// let avatar = Avatar::new("path/to/image.png").grayscale(true);
-    /// ```
-    pub fn grayscale(mut self, grayscale: bool) -> Self {
-        self.image = self.image.grayscale(grayscale);
-        self
-    }
-
-    pub fn border_color(mut self, color: impl Into<Hsla>) -> Self {
-        self.border_color = Some(color.into());
-        self
-    }
-
-    /// Size overrides the avatar size. By default they are 1rem.
-    pub fn size<L: Into<AbsoluteLength>>(mut self, size: impl Into<Option<L>>) -> Self {
-        self.size = size.into().map(Into::into);
-        self
-    }
-
-    pub fn indicator<E: IntoElement>(mut self, indicator: impl Into<Option<E>>) -> Self {
-        self.indicator = indicator.into().map(IntoElement::into_any_element);
-        self
-    }
-}
-
-impl RenderOnce for Avatar {
-    fn render(mut self, cx: &mut WindowContext) -> impl IntoElement {
-        if self.image.style().corner_radii.top_left.is_none() {
-            self = self.shape(AvatarShape::Circle);
-        }
-
-        let border_width = if self.border_color.is_some() {
-            px(2.)
-        } else {
-            px(0.)
-        };
-
-        let image_size = self.size.unwrap_or_else(|| rems(1.).into());
-        let container_size = image_size.to_pixels(cx.rem_size()) + border_width * 2.;
-
-        div()
-            .size(container_size)
-            .map(|mut div| {
-                div.style().corner_radii = self.image.style().corner_radii.clone();
-                div
-            })
-            .when_some(self.border_color, |this, color| {
-                this.border(border_width).border_color(color)
-            })
-            .child(
-                self.image
-                    .size(image_size)
-                    .bg(cx.theme().colors().ghost_element_background),
-            )
-            .children(self.indicator.map(|indicator| div().child(indicator)))
-    }
-}

crates/ui/src/components/avatar/avatar.rs 🔗

@@ -0,0 +1,127 @@
+use crate::prelude::*;
+
+use gpui::{img, AnyElement, Hsla, ImageSource, Img, IntoElement, Styled};
+
+/// The shape of an [`Avatar`].
+#[derive(Debug, Default, PartialEq, Clone)]
+pub enum AvatarShape {
+    /// The avatar is shown in a circle.
+    #[default]
+    Circle,
+    /// The avatar is shown in a rectangle with rounded corners.
+    RoundedRectangle,
+}
+
+/// An element that renders a user avatar with customizable appearance options.
+///
+/// # Examples
+///
+/// ```
+/// use ui::{Avatar, AvatarShape};
+///
+/// Avatar::new("path/to/image.png")
+///     .shape(AvatarShape::Circle)
+///     .grayscale(true)
+///     .border_color(gpui::red());
+/// ```
+#[derive(IntoElement)]
+pub struct Avatar {
+    image: Img,
+    size: Option<AbsoluteLength>,
+    border_color: Option<Hsla>,
+    indicator: Option<AnyElement>,
+}
+
+impl Avatar {
+    pub fn new(src: impl Into<ImageSource>) -> Self {
+        Avatar {
+            image: img(src),
+            size: None,
+            border_color: None,
+            indicator: None,
+        }
+    }
+
+    /// Sets the shape of the avatar image.
+    ///
+    /// This method allows the shape of the avatar to be specified using an [`AvatarShape`].
+    /// It modifies the corner radius of the image to match the specified shape.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::{Avatar, AvatarShape};
+    ///
+    /// Avatar::new("path/to/image.png").shape(AvatarShape::Circle);
+    /// ```
+    pub fn shape(mut self, shape: AvatarShape) -> Self {
+        self.image = match shape {
+            AvatarShape::Circle => self.image.rounded_full(),
+            AvatarShape::RoundedRectangle => self.image.rounded_md(),
+        };
+        self
+    }
+
+    /// Applies a grayscale filter to the avatar image.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::{Avatar, AvatarShape};
+    ///
+    /// let avatar = Avatar::new("path/to/image.png").grayscale(true);
+    /// ```
+    pub fn grayscale(mut self, grayscale: bool) -> Self {
+        self.image = self.image.grayscale(grayscale);
+        self
+    }
+
+    pub fn border_color(mut self, color: impl Into<Hsla>) -> Self {
+        self.border_color = Some(color.into());
+        self
+    }
+
+    /// Size overrides the avatar size. By default they are 1rem.
+    pub fn size<L: Into<AbsoluteLength>>(mut self, size: impl Into<Option<L>>) -> Self {
+        self.size = size.into().map(Into::into);
+        self
+    }
+
+    pub fn indicator<E: IntoElement>(mut self, indicator: impl Into<Option<E>>) -> Self {
+        self.indicator = indicator.into().map(IntoElement::into_any_element);
+        self
+    }
+}
+
+impl RenderOnce for Avatar {
+    fn render(mut self, cx: &mut WindowContext) -> impl IntoElement {
+        if self.image.style().corner_radii.top_left.is_none() {
+            self = self.shape(AvatarShape::Circle);
+        }
+
+        let border_width = if self.border_color.is_some() {
+            px(2.)
+        } else {
+            px(0.)
+        };
+
+        let image_size = self.size.unwrap_or_else(|| rems(1.).into());
+        let container_size = image_size.to_pixels(cx.rem_size()) + border_width * 2.;
+
+        div()
+            .size(container_size)
+            .map(|mut div| {
+                div.style().corner_radii = self.image.style().corner_radii.clone();
+                div
+            })
+            .when_some(self.border_color, |this, color| {
+                this.border(border_width).border_color(color)
+            })
+            .child(
+                self.image
+                    .size(image_size)
+                    .bg(cx.theme().colors().ghost_element_background),
+            )
+            .children(self.indicator.map(|indicator| div().child(indicator)))
+    }
+}

crates/ui/src/components/button.rs 🔗

@@ -1,445 +1,10 @@
-mod button_icon;
+mod button;
+pub(self) mod button_icon;
 mod button_like;
 mod icon_button;
 mod toggle_button;
 
+pub use button::*;
 pub use button_like::*;
 pub use icon_button::*;
 pub use toggle_button::*;
-
-use gpui::{AnyView, DefiniteLength};
-
-use crate::{prelude::*, ElevationIndex, KeyBinding, Spacing};
-use crate::{IconName, IconSize, Label, LineHeightStyle};
-
-use button_icon::ButtonIcon;
-
-/// An element that creates a button with a label and an optional icon.
-///
-/// Common buttons:
-/// - Label, Icon + Label: [`Button`] (this component)
-/// - Icon only: [`IconButton`]
-/// - Custom: [`ButtonLike`]
-///
-/// To create a more complex button than what the [`Button`] or [`IconButton`] components provide, use
-/// [`ButtonLike`] directly.
-///
-/// # Examples
-///
-/// **A button with a label**, is typically used in scenarios such as a form, where the button's label
-/// indicates what action will be performed when the button is clicked.
-///
-/// ```
-/// use ui::prelude::*;
-///
-/// Button::new("button_id", "Click me!")
-///     .on_click(|event, cx| {
-///         // Handle click event
-///     });
-/// ```
-///
-/// **A toggleable button**, is typically used in scenarios such as a toolbar,
-/// where the button's state indicates whether a feature is enabled or not, or
-/// a trigger for a popover menu, where clicking the button toggles the visibility of the menu.
-///
-/// ```
-/// use ui::prelude::*;
-///
-/// Button::new("button_id", "Click me!")
-///     .icon(IconName::Check)
-///     .selected(true)
-///     .on_click(|event, cx| {
-///         // Handle click event
-///     });
-/// ```
-///
-/// To change the style of the button when it is selected use the [`selected_style`][Button::selected_style] method.
-///
-/// ```
-/// use ui::prelude::*;
-/// use ui::TintColor;
-///
-/// Button::new("button_id", "Click me!")
-///     .selected(true)
-///     .selected_style(ButtonStyle::Tinted(TintColor::Accent))
-///     .on_click(|event, cx| {
-///         // Handle click event
-///     });
-/// ```
-/// This will create a button with a blue tinted background when selected.
-///
-/// **A full-width button**, is typically used in scenarios such as the bottom of a modal or form, where it occupies the entire width of its container.
-/// The button's content, including text and icons, is centered by default.
-///
-/// ```
-/// use ui::prelude::*;
-///
-/// let button = Button::new("button_id", "Click me!")
-///     .full_width()
-///     .on_click(|event, cx| {
-///         // Handle click event
-///     });
-/// ```
-///
-#[derive(IntoElement)]
-pub struct Button {
-    base: ButtonLike,
-    label: SharedString,
-    label_color: Option<Color>,
-    label_size: Option<LabelSize>,
-    selected_label: Option<SharedString>,
-    selected_label_color: Option<Color>,
-    icon: Option<IconName>,
-    icon_position: Option<IconPosition>,
-    icon_size: Option<IconSize>,
-    icon_color: Option<Color>,
-    selected_icon: Option<IconName>,
-    selected_icon_color: Option<Color>,
-    key_binding: Option<KeyBinding>,
-    alpha: Option<f32>,
-}
-
-impl Button {
-    /// Creates a new [`Button`] with a specified identifier and label.
-    ///
-    /// This is the primary constructor for a [`Button`] component. It initializes
-    /// the button with the provided identifier and label text, setting all other
-    /// properties to their default values, which can be customized using the
-    /// builder pattern methods provided by this struct.
-    pub fn new(id: impl Into<ElementId>, label: impl Into<SharedString>) -> Self {
-        Self {
-            base: ButtonLike::new(id),
-            label: label.into(),
-            label_color: None,
-            label_size: None,
-            selected_label: None,
-            selected_label_color: None,
-            icon: None,
-            icon_position: None,
-            icon_size: None,
-            icon_color: None,
-            selected_icon: None,
-            selected_icon_color: None,
-            key_binding: None,
-            alpha: None,
-        }
-    }
-
-    /// Sets the color of the button's label.
-    pub fn color(mut self, label_color: impl Into<Option<Color>>) -> Self {
-        self.label_color = label_color.into();
-        self
-    }
-
-    /// Defines the size of the button's label.
-    pub fn label_size(mut self, label_size: impl Into<Option<LabelSize>>) -> Self {
-        self.label_size = label_size.into();
-        self
-    }
-
-    /// Sets the label used when the button is in a selected state.
-    pub fn selected_label<L: Into<SharedString>>(mut self, label: impl Into<Option<L>>) -> Self {
-        self.selected_label = label.into().map(Into::into);
-        self
-    }
-
-    /// Sets the label color used when the button is in a selected state.
-    pub fn selected_label_color(mut self, color: impl Into<Option<Color>>) -> Self {
-        self.selected_label_color = color.into();
-        self
-    }
-
-    /// Assigns an icon to the button.
-    pub fn icon(mut self, icon: impl Into<Option<IconName>>) -> Self {
-        self.icon = icon.into();
-        self
-    }
-
-    /// Sets the position of the icon relative to the label.
-    pub fn icon_position(mut self, icon_position: impl Into<Option<IconPosition>>) -> Self {
-        self.icon_position = icon_position.into();
-        self
-    }
-
-    /// Specifies the size of the button's icon.
-    pub fn icon_size(mut self, icon_size: impl Into<Option<IconSize>>) -> Self {
-        self.icon_size = icon_size.into();
-        self
-    }
-
-    /// Sets the color of the button's icon.
-    pub fn icon_color(mut self, icon_color: impl Into<Option<Color>>) -> Self {
-        self.icon_color = icon_color.into();
-        self
-    }
-
-    /// Chooses an icon to display when the button is in a selected state.
-    pub fn selected_icon(mut self, icon: impl Into<Option<IconName>>) -> Self {
-        self.selected_icon = icon.into();
-        self
-    }
-
-    /// Sets the icon color used when the button is in a selected state.
-    pub fn selected_icon_color(mut self, color: impl Into<Option<Color>>) -> Self {
-        self.selected_icon_color = color.into();
-        self
-    }
-
-    /// Binds a key combination to the button for keyboard shortcuts.
-    pub fn key_binding(mut self, key_binding: impl Into<Option<KeyBinding>>) -> Self {
-        self.key_binding = key_binding.into();
-        self
-    }
-
-    /// Sets the alpha property of the color of label.
-    pub fn alpha(mut self, alpha: f32) -> Self {
-        self.alpha = Some(alpha);
-        self
-    }
-}
-
-impl Selectable for Button {
-    /// Sets the selected state of the button.
-    ///
-    /// This method allows the selection state of the button to be specified.
-    /// It modifies the button's appearance to reflect its selected state.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    ///
-    /// Button::new("button_id", "Click me!")
-    ///     .selected(true)
-    ///     .on_click(|event, cx| {
-    ///         // Handle click event
-    ///     });
-    /// ```
-    ///
-    /// Use [`selected_style`](Button::selected_style) to change the style of the button when it is selected.
-    fn selected(mut self, selected: bool) -> Self {
-        self.base = self.base.selected(selected);
-        self
-    }
-}
-
-impl SelectableButton for Button {
-    /// Sets the style for the button when selected.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    /// use ui::TintColor;
-    ///
-    /// Button::new("button_id", "Click me!")
-    ///     .selected(true)
-    ///     .selected_style(ButtonStyle::Tinted(TintColor::Accent))
-    ///     .on_click(|event, cx| {
-    ///         // Handle click event
-    ///     });
-    /// ```
-    /// This results in a button with a blue tinted background when selected.
-    fn selected_style(mut self, style: ButtonStyle) -> Self {
-        self.base = self.base.selected_style(style);
-        self
-    }
-}
-
-impl Disableable for Button {
-    /// Disables the button.
-    ///
-    /// This method allows the button to be disabled. When a button is disabled,
-    /// it doesn't react to user interactions and its appearance is updated to reflect this.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    ///
-    /// Button::new("button_id", "Click me!")
-    ///     .disabled(true)
-    ///     .on_click(|event, cx| {
-    ///         // Handle click event
-    ///     });
-    /// ```
-    ///
-    /// This results in a button that is disabled and does not respond to click events.
-    fn disabled(mut self, disabled: bool) -> Self {
-        self.base = self.base.disabled(disabled);
-        self
-    }
-}
-
-impl Clickable for Button {
-    /// Sets the click event handler for the button.
-    fn on_click(
-        mut self,
-        handler: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static,
-    ) -> Self {
-        self.base = self.base.on_click(handler);
-        self
-    }
-
-    fn cursor_style(mut self, cursor_style: gpui::CursorStyle) -> Self {
-        self.base = self.base.cursor_style(cursor_style);
-        self
-    }
-}
-
-impl FixedWidth for Button {
-    /// Sets a fixed width for the button.
-    ///
-    /// This function allows a button to have a fixed width instead of automatically growing or shrinking.
-    /// Sets a fixed width for the button.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    ///
-    /// Button::new("button_id", "Click me!")
-    ///     .width(px(100.).into())
-    ///     .on_click(|event, cx| {
-    ///         // Handle click event
-    ///     });
-    /// ```
-    ///
-    /// This sets the button's width to be exactly 100 pixels.
-    fn width(mut self, width: DefiniteLength) -> Self {
-        self.base = self.base.width(width);
-        self
-    }
-
-    /// Sets the button to occupy the full width of its container.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    ///
-    /// Button::new("button_id", "Click me!")
-    ///     .full_width()
-    ///     .on_click(|event, cx| {
-    ///         // Handle click event
-    ///     });
-    /// ```
-    ///
-    /// This stretches the button to the full width of its container.
-    fn full_width(mut self) -> Self {
-        self.base = self.base.full_width();
-        self
-    }
-}
-
-impl ButtonCommon for Button {
-    /// Sets the button's id.
-    fn id(&self) -> &ElementId {
-        self.base.id()
-    }
-
-    /// Sets the visual style of the button using a [`ButtonStyle`].
-    fn style(mut self, style: ButtonStyle) -> Self {
-        self.base = self.base.style(style);
-        self
-    }
-
-    /// Sets the button's size using a [`ButtonSize`].
-    fn size(mut self, size: ButtonSize) -> Self {
-        self.base = self.base.size(size);
-        self
-    }
-
-    /// Sets a tooltip for the button.
-    ///
-    /// This method allows a tooltip to be set for the button. The tooltip is a function that
-    /// takes a mutable reference to a [`WindowContext`] and returns an [`AnyView`]. The tooltip
-    /// is displayed when the user hovers over the button.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    /// use ui::Tooltip;
-    ///
-    /// Button::new("button_id", "Click me!")
-    ///     .tooltip(move |cx| {
-    ///         Tooltip::text("This is a tooltip", cx)
-    ///     })
-    ///     .on_click(|event, cx| {
-    ///         // Handle click event
-    ///     });
-    /// ```
-    ///
-    /// This will create a button with a tooltip that displays "This is a tooltip" when hovered over.
-    fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
-        self.base = self.base.tooltip(tooltip);
-        self
-    }
-
-    fn layer(mut self, elevation: ElevationIndex) -> Self {
-        self.base = self.base.layer(elevation);
-        self
-    }
-}
-
-impl RenderOnce for Button {
-    #[allow(refining_impl_trait)]
-    fn render(self, cx: &mut WindowContext) -> ButtonLike {
-        let is_disabled = self.base.disabled;
-        let is_selected = self.base.selected;
-
-        let label = self
-            .selected_label
-            .filter(|_| is_selected)
-            .unwrap_or(self.label);
-
-        let label_color = if is_disabled {
-            Color::Disabled
-        } else if is_selected {
-            self.selected_label_color.unwrap_or(Color::Selected)
-        } else {
-            self.label_color.unwrap_or_default()
-        };
-
-        self.base.child(
-            h_flex()
-                .gap(Spacing::Small.rems(cx))
-                .when(self.icon_position == Some(IconPosition::Start), |this| {
-                    this.children(self.icon.map(|icon| {
-                        ButtonIcon::new(icon)
-                            .disabled(is_disabled)
-                            .selected(is_selected)
-                            .selected_icon(self.selected_icon)
-                            .selected_icon_color(self.selected_icon_color)
-                            .size(self.icon_size)
-                            .color(self.icon_color)
-                    }))
-                })
-                .child(
-                    h_flex()
-                        .gap(Spacing::Medium.rems(cx))
-                        .justify_between()
-                        .child(
-                            Label::new(label)
-                                .color(label_color)
-                                .size(self.label_size.unwrap_or_default())
-                                .when_some(self.alpha, |this, alpha| this.alpha(alpha))
-                                .line_height_style(LineHeightStyle::UiLabel),
-                        )
-                        .children(self.key_binding),
-                )
-                .when(self.icon_position != Some(IconPosition::Start), |this| {
-                    this.children(self.icon.map(|icon| {
-                        ButtonIcon::new(icon)
-                            .disabled(is_disabled)
-                            .selected(is_selected)
-                            .selected_icon(self.selected_icon)
-                            .selected_icon_color(self.selected_icon_color)
-                            .size(self.icon_size)
-                            .color(self.icon_color)
-                    }))
-                }),
-        )
-    }
-}

crates/ui/src/components/button/button.rs 🔗

@@ -0,0 +1,438 @@
+use gpui::{AnyView, DefiniteLength};
+
+use crate::{prelude::*, ElevationIndex, IconPosition, KeyBinding, Spacing};
+use crate::{
+    ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, IconName, IconSize, Label, LineHeightStyle,
+};
+
+use super::button_icon::ButtonIcon;
+
+/// An element that creates a button with a label and an optional icon.
+///
+/// Common buttons:
+/// - Label, Icon + Label: [`Button`] (this component)
+/// - Icon only: [`IconButton`]
+/// - Custom: [`ButtonLike`]
+///
+/// To create a more complex button than what the [`Button`] or [`IconButton`] components provide, use
+/// [`ButtonLike`] directly.
+///
+/// # Examples
+///
+/// **A button with a label**, is typically used in scenarios such as a form, where the button's label
+/// indicates what action will be performed when the button is clicked.
+///
+/// ```
+/// use ui::prelude::*;
+///
+/// Button::new("button_id", "Click me!")
+///     .on_click(|event, cx| {
+///         // Handle click event
+///     });
+/// ```
+///
+/// **A toggleable button**, is typically used in scenarios such as a toolbar,
+/// where the button's state indicates whether a feature is enabled or not, or
+/// a trigger for a popover menu, where clicking the button toggles the visibility of the menu.
+///
+/// ```
+/// use ui::prelude::*;
+///
+/// Button::new("button_id", "Click me!")
+///     .icon(IconName::Check)
+///     .selected(true)
+///     .on_click(|event, cx| {
+///         // Handle click event
+///     });
+/// ```
+///
+/// To change the style of the button when it is selected use the [`selected_style`][Button::selected_style] method.
+///
+/// ```
+/// use ui::prelude::*;
+/// use ui::TintColor;
+///
+/// Button::new("button_id", "Click me!")
+///     .selected(true)
+///     .selected_style(ButtonStyle::Tinted(TintColor::Accent))
+///     .on_click(|event, cx| {
+///         // Handle click event
+///     });
+/// ```
+/// This will create a button with a blue tinted background when selected.
+///
+/// **A full-width button**, is typically used in scenarios such as the bottom of a modal or form, where it occupies the entire width of its container.
+/// The button's content, including text and icons, is centered by default.
+///
+/// ```
+/// use ui::prelude::*;
+///
+/// let button = Button::new("button_id", "Click me!")
+///     .full_width()
+///     .on_click(|event, cx| {
+///         // Handle click event
+///     });
+/// ```
+///
+#[derive(IntoElement)]
+pub struct Button {
+    base: ButtonLike,
+    label: SharedString,
+    label_color: Option<Color>,
+    label_size: Option<LabelSize>,
+    selected_label: Option<SharedString>,
+    selected_label_color: Option<Color>,
+    icon: Option<IconName>,
+    icon_position: Option<IconPosition>,
+    icon_size: Option<IconSize>,
+    icon_color: Option<Color>,
+    selected_icon: Option<IconName>,
+    selected_icon_color: Option<Color>,
+    key_binding: Option<KeyBinding>,
+    alpha: Option<f32>,
+}
+
+impl Button {
+    /// Creates a new [`Button`] with a specified identifier and label.
+    ///
+    /// This is the primary constructor for a [`Button`] component. It initializes
+    /// the button with the provided identifier and label text, setting all other
+    /// properties to their default values, which can be customized using the
+    /// builder pattern methods provided by this struct.
+    pub fn new(id: impl Into<ElementId>, label: impl Into<SharedString>) -> Self {
+        Self {
+            base: ButtonLike::new(id),
+            label: label.into(),
+            label_color: None,
+            label_size: None,
+            selected_label: None,
+            selected_label_color: None,
+            icon: None,
+            icon_position: None,
+            icon_size: None,
+            icon_color: None,
+            selected_icon: None,
+            selected_icon_color: None,
+            key_binding: None,
+            alpha: None,
+        }
+    }
+
+    /// Sets the color of the button's label.
+    pub fn color(mut self, label_color: impl Into<Option<Color>>) -> Self {
+        self.label_color = label_color.into();
+        self
+    }
+
+    /// Defines the size of the button's label.
+    pub fn label_size(mut self, label_size: impl Into<Option<LabelSize>>) -> Self {
+        self.label_size = label_size.into();
+        self
+    }
+
+    /// Sets the label used when the button is in a selected state.
+    pub fn selected_label<L: Into<SharedString>>(mut self, label: impl Into<Option<L>>) -> Self {
+        self.selected_label = label.into().map(Into::into);
+        self
+    }
+
+    /// Sets the label color used when the button is in a selected state.
+    pub fn selected_label_color(mut self, color: impl Into<Option<Color>>) -> Self {
+        self.selected_label_color = color.into();
+        self
+    }
+
+    /// Assigns an icon to the button.
+    pub fn icon(mut self, icon: impl Into<Option<IconName>>) -> Self {
+        self.icon = icon.into();
+        self
+    }
+
+    /// Sets the position of the icon relative to the label.
+    pub fn icon_position(mut self, icon_position: impl Into<Option<IconPosition>>) -> Self {
+        self.icon_position = icon_position.into();
+        self
+    }
+
+    /// Specifies the size of the button's icon.
+    pub fn icon_size(mut self, icon_size: impl Into<Option<IconSize>>) -> Self {
+        self.icon_size = icon_size.into();
+        self
+    }
+
+    /// Sets the color of the button's icon.
+    pub fn icon_color(mut self, icon_color: impl Into<Option<Color>>) -> Self {
+        self.icon_color = icon_color.into();
+        self
+    }
+
+    /// Chooses an icon to display when the button is in a selected state.
+    pub fn selected_icon(mut self, icon: impl Into<Option<IconName>>) -> Self {
+        self.selected_icon = icon.into();
+        self
+    }
+
+    /// Sets the icon color used when the button is in a selected state.
+    pub fn selected_icon_color(mut self, color: impl Into<Option<Color>>) -> Self {
+        self.selected_icon_color = color.into();
+        self
+    }
+
+    /// Binds a key combination to the button for keyboard shortcuts.
+    pub fn key_binding(mut self, key_binding: impl Into<Option<KeyBinding>>) -> Self {
+        self.key_binding = key_binding.into();
+        self
+    }
+
+    /// Sets the alpha property of the color of label.
+    pub fn alpha(mut self, alpha: f32) -> Self {
+        self.alpha = Some(alpha);
+        self
+    }
+}
+
+impl Selectable for Button {
+    /// Sets the selected state of the button.
+    ///
+    /// This method allows the selection state of the button to be specified.
+    /// It modifies the button's appearance to reflect its selected state.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    ///
+    /// Button::new("button_id", "Click me!")
+    ///     .selected(true)
+    ///     .on_click(|event, cx| {
+    ///         // Handle click event
+    ///     });
+    /// ```
+    ///
+    /// Use [`selected_style`](Button::selected_style) to change the style of the button when it is selected.
+    fn selected(mut self, selected: bool) -> Self {
+        self.base = self.base.selected(selected);
+        self
+    }
+}
+
+impl SelectableButton for Button {
+    /// Sets the style for the button when selected.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    /// use ui::TintColor;
+    ///
+    /// Button::new("button_id", "Click me!")
+    ///     .selected(true)
+    ///     .selected_style(ButtonStyle::Tinted(TintColor::Accent))
+    ///     .on_click(|event, cx| {
+    ///         // Handle click event
+    ///     });
+    /// ```
+    /// This results in a button with a blue tinted background when selected.
+    fn selected_style(mut self, style: ButtonStyle) -> Self {
+        self.base = self.base.selected_style(style);
+        self
+    }
+}
+
+impl Disableable for Button {
+    /// Disables the button.
+    ///
+    /// This method allows the button to be disabled. When a button is disabled,
+    /// it doesn't react to user interactions and its appearance is updated to reflect this.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    ///
+    /// Button::new("button_id", "Click me!")
+    ///     .disabled(true)
+    ///     .on_click(|event, cx| {
+    ///         // Handle click event
+    ///     });
+    /// ```
+    ///
+    /// This results in a button that is disabled and does not respond to click events.
+    fn disabled(mut self, disabled: bool) -> Self {
+        self.base = self.base.disabled(disabled);
+        self
+    }
+}
+
+impl Clickable for Button {
+    /// Sets the click event handler for the button.
+    fn on_click(
+        mut self,
+        handler: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static,
+    ) -> Self {
+        self.base = self.base.on_click(handler);
+        self
+    }
+
+    fn cursor_style(mut self, cursor_style: gpui::CursorStyle) -> Self {
+        self.base = self.base.cursor_style(cursor_style);
+        self
+    }
+}
+
+impl FixedWidth for Button {
+    /// Sets a fixed width for the button.
+    ///
+    /// This function allows a button to have a fixed width instead of automatically growing or shrinking.
+    /// Sets a fixed width for the button.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    ///
+    /// Button::new("button_id", "Click me!")
+    ///     .width(px(100.).into())
+    ///     .on_click(|event, cx| {
+    ///         // Handle click event
+    ///     });
+    /// ```
+    ///
+    /// This sets the button's width to be exactly 100 pixels.
+    fn width(mut self, width: DefiniteLength) -> Self {
+        self.base = self.base.width(width);
+        self
+    }
+
+    /// Sets the button to occupy the full width of its container.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    ///
+    /// Button::new("button_id", "Click me!")
+    ///     .full_width()
+    ///     .on_click(|event, cx| {
+    ///         // Handle click event
+    ///     });
+    /// ```
+    ///
+    /// This stretches the button to the full width of its container.
+    fn full_width(mut self) -> Self {
+        self.base = self.base.full_width();
+        self
+    }
+}
+
+impl ButtonCommon for Button {
+    /// Sets the button's id.
+    fn id(&self) -> &ElementId {
+        self.base.id()
+    }
+
+    /// Sets the visual style of the button using a [`ButtonStyle`].
+    fn style(mut self, style: ButtonStyle) -> Self {
+        self.base = self.base.style(style);
+        self
+    }
+
+    /// Sets the button's size using a [`ButtonSize`].
+    fn size(mut self, size: ButtonSize) -> Self {
+        self.base = self.base.size(size);
+        self
+    }
+
+    /// Sets a tooltip for the button.
+    ///
+    /// This method allows a tooltip to be set for the button. The tooltip is a function that
+    /// takes a mutable reference to a [`WindowContext`] and returns an [`AnyView`]. The tooltip
+    /// is displayed when the user hovers over the button.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    /// use ui::Tooltip;
+    ///
+    /// Button::new("button_id", "Click me!")
+    ///     .tooltip(move |cx| {
+    ///         Tooltip::text("This is a tooltip", cx)
+    ///     })
+    ///     .on_click(|event, cx| {
+    ///         // Handle click event
+    ///     });
+    /// ```
+    ///
+    /// This will create a button with a tooltip that displays "This is a tooltip" when hovered over.
+    fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
+        self.base = self.base.tooltip(tooltip);
+        self
+    }
+
+    fn layer(mut self, elevation: ElevationIndex) -> Self {
+        self.base = self.base.layer(elevation);
+        self
+    }
+}
+
+impl RenderOnce for Button {
+    #[allow(refining_impl_trait)]
+    fn render(self, cx: &mut WindowContext) -> ButtonLike {
+        let is_disabled = self.base.disabled;
+        let is_selected = self.base.selected;
+
+        let label = self
+            .selected_label
+            .filter(|_| is_selected)
+            .unwrap_or(self.label);
+
+        let label_color = if is_disabled {
+            Color::Disabled
+        } else if is_selected {
+            self.selected_label_color.unwrap_or(Color::Selected)
+        } else {
+            self.label_color.unwrap_or_default()
+        };
+
+        self.base.child(
+            h_flex()
+                .gap(Spacing::Small.rems(cx))
+                .when(self.icon_position == Some(IconPosition::Start), |this| {
+                    this.children(self.icon.map(|icon| {
+                        ButtonIcon::new(icon)
+                            .disabled(is_disabled)
+                            .selected(is_selected)
+                            .selected_icon(self.selected_icon)
+                            .selected_icon_color(self.selected_icon_color)
+                            .size(self.icon_size)
+                            .color(self.icon_color)
+                    }))
+                })
+                .child(
+                    h_flex()
+                        .gap(Spacing::Medium.rems(cx))
+                        .justify_between()
+                        .child(
+                            Label::new(label)
+                                .color(label_color)
+                                .size(self.label_size.unwrap_or_default())
+                                .when_some(self.alpha, |this, alpha| this.alpha(alpha))
+                                .line_height_style(LineHeightStyle::UiLabel),
+                        )
+                        .children(self.key_binding),
+                )
+                .when(self.icon_position != Some(IconPosition::Start), |this| {
+                    this.children(self.icon.map(|icon| {
+                        ButtonIcon::new(icon)
+                            .disabled(is_disabled)
+                            .selected(is_selected)
+                            .selected_icon(self.selected_icon)
+                            .selected_icon_color(self.selected_icon_color)
+                            .size(self.icon_size)
+                            .color(self.icon_color)
+                    }))
+                }),
+        )
+    }
+}

crates/ui/src/components/label.rs 🔗

@@ -1,190 +1,7 @@
 mod highlighted_label;
+mod label;
 mod label_like;
 
 pub use highlighted_label::*;
+pub use label::*;
 pub use label_like::*;
-
-use gpui::{StyleRefinement, WindowContext};
-
-use crate::prelude::*;
-
-/// A struct representing a label element in the UI.
-///
-/// The `Label` struct stores the label text and common properties for a label element.
-/// It provides methods for modifying these properties.
-///
-/// # Examples
-///
-/// ```
-/// use ui::prelude::*;
-///
-/// Label::new("Hello, World!");
-/// ```
-///
-/// **A colored label**, for example labeling a dangerous action:
-///
-/// ```
-/// use ui::prelude::*;
-///
-/// let my_label = Label::new("Delete").color(Color::Error);
-/// ```
-///
-/// **A label with a strikethrough**, for example labeling something that has been deleted:
-///
-/// ```
-/// use ui::prelude::*;
-///
-/// let my_label = Label::new("Deleted").strikethrough(true);
-/// ```
-#[derive(IntoElement)]
-pub struct Label {
-    base: LabelLike,
-    label: SharedString,
-    single_line: bool,
-}
-
-impl Label {
-    /// Creates a new [`Label`] with the given text.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    ///
-    /// let my_label = Label::new("Hello, World!");
-    /// ```
-    pub fn new(label: impl Into<SharedString>) -> Self {
-        Self {
-            base: LabelLike::new(),
-            label: label.into(),
-            single_line: false,
-        }
-    }
-
-    /// Make the label display in a single line mode
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    ///
-    /// let my_label = Label::new("Hello, World!").single_line();
-    /// ```
-    pub fn single_line(mut self) -> Self {
-        self.single_line = true;
-        self
-    }
-}
-
-// Style methods.
-impl Label {
-    fn style(&mut self) -> &mut StyleRefinement {
-        self.base.base.style()
-    }
-
-    gpui::margin_style_methods!({
-        visibility: pub
-    });
-}
-
-impl LabelCommon for Label {
-    /// Sets the size of the label using a [`LabelSize`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    ///
-    /// let my_label = Label::new("Hello, World!").size(LabelSize::Small);
-    /// ```
-    fn size(mut self, size: LabelSize) -> Self {
-        self.base = self.base.size(size);
-        self
-    }
-
-    fn weight(mut self, weight: gpui::FontWeight) -> Self {
-        self.base = self.base.weight(weight);
-        self
-    }
-
-    /// Sets the line height style of the label using a [`LineHeightStyle`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    ///
-    /// let my_label = Label::new("Hello, World!").line_height_style(LineHeightStyle::UiLabel);
-    /// ```
-    fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
-        self.base = self.base.line_height_style(line_height_style);
-        self
-    }
-
-    /// Sets the color of the label using a [`Color`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    ///
-    /// let my_label = Label::new("Hello, World!").color(Color::Accent);
-    /// ```
-    fn color(mut self, color: Color) -> Self {
-        self.base = self.base.color(color);
-        self
-    }
-
-    /// Sets the strikethrough property of the label.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    ///
-    /// let my_label = Label::new("Hello, World!").strikethrough(true);
-    /// ```
-    fn strikethrough(mut self, strikethrough: bool) -> Self {
-        self.base = self.base.strikethrough(strikethrough);
-        self
-    }
-
-    /// Sets the italic property of the label.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    ///
-    /// let my_label = Label::new("Hello, World!").italic(true);
-    /// ```
-    fn italic(mut self, italic: bool) -> Self {
-        self.base = self.base.italic(italic);
-        self
-    }
-
-    /// Sets the alpha property of the color of label.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use ui::prelude::*;
-    ///
-    /// let my_label = Label::new("Hello, World!").alpha(0.5);
-    /// ```
-    fn alpha(mut self, alpha: f32) -> Self {
-        self.base = self.base.alpha(alpha);
-        self
-    }
-}
-
-impl RenderOnce for Label {
-    fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
-        let target_label = if self.single_line {
-            SharedString::from(self.label.replace('\n', "␤"))
-        } else {
-            self.label
-        };
-        self.base.child(target_label)
-    }
-}

crates/ui/src/components/label/label.rs 🔗

@@ -0,0 +1,184 @@
+use gpui::{StyleRefinement, WindowContext};
+
+use crate::{prelude::*, LabelCommon, LabelLike, LabelSize, LineHeightStyle};
+
+/// A struct representing a label element in the UI.
+///
+/// The `Label` struct stores the label text and common properties for a label element.
+/// It provides methods for modifying these properties.
+///
+/// # Examples
+///
+/// ```
+/// use ui::prelude::*;
+///
+/// Label::new("Hello, World!");
+/// ```
+///
+/// **A colored label**, for example labeling a dangerous action:
+///
+/// ```
+/// use ui::prelude::*;
+///
+/// let my_label = Label::new("Delete").color(Color::Error);
+/// ```
+///
+/// **A label with a strikethrough**, for example labeling something that has been deleted:
+///
+/// ```
+/// use ui::prelude::*;
+///
+/// let my_label = Label::new("Deleted").strikethrough(true);
+/// ```
+#[derive(IntoElement)]
+pub struct Label {
+    base: LabelLike,
+    label: SharedString,
+    single_line: bool,
+}
+
+impl Label {
+    /// Creates a new [`Label`] with the given text.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    ///
+    /// let my_label = Label::new("Hello, World!");
+    /// ```
+    pub fn new(label: impl Into<SharedString>) -> Self {
+        Self {
+            base: LabelLike::new(),
+            label: label.into(),
+            single_line: false,
+        }
+    }
+
+    /// Make the label display in a single line mode
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    ///
+    /// let my_label = Label::new("Hello, World!").single_line();
+    /// ```
+    pub fn single_line(mut self) -> Self {
+        self.single_line = true;
+        self
+    }
+}
+
+// Style methods.
+impl Label {
+    fn style(&mut self) -> &mut StyleRefinement {
+        self.base.base.style()
+    }
+
+    gpui::margin_style_methods!({
+        visibility: pub
+    });
+}
+
+impl LabelCommon for Label {
+    /// Sets the size of the label using a [`LabelSize`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    ///
+    /// let my_label = Label::new("Hello, World!").size(LabelSize::Small);
+    /// ```
+    fn size(mut self, size: LabelSize) -> Self {
+        self.base = self.base.size(size);
+        self
+    }
+
+    fn weight(mut self, weight: gpui::FontWeight) -> Self {
+        self.base = self.base.weight(weight);
+        self
+    }
+
+    /// Sets the line height style of the label using a [`LineHeightStyle`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    ///
+    /// let my_label = Label::new("Hello, World!").line_height_style(LineHeightStyle::UiLabel);
+    /// ```
+    fn line_height_style(mut self, line_height_style: LineHeightStyle) -> Self {
+        self.base = self.base.line_height_style(line_height_style);
+        self
+    }
+
+    /// Sets the color of the label using a [`Color`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    ///
+    /// let my_label = Label::new("Hello, World!").color(Color::Accent);
+    /// ```
+    fn color(mut self, color: Color) -> Self {
+        self.base = self.base.color(color);
+        self
+    }
+
+    /// Sets the strikethrough property of the label.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    ///
+    /// let my_label = Label::new("Hello, World!").strikethrough(true);
+    /// ```
+    fn strikethrough(mut self, strikethrough: bool) -> Self {
+        self.base = self.base.strikethrough(strikethrough);
+        self
+    }
+
+    /// Sets the italic property of the label.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    ///
+    /// let my_label = Label::new("Hello, World!").italic(true);
+    /// ```
+    fn italic(mut self, italic: bool) -> Self {
+        self.base = self.base.italic(italic);
+        self
+    }
+
+    /// Sets the alpha property of the color of label.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use ui::prelude::*;
+    ///
+    /// let my_label = Label::new("Hello, World!").alpha(0.5);
+    /// ```
+    fn alpha(mut self, alpha: f32) -> Self {
+        self.base = self.base.alpha(alpha);
+        self
+    }
+}
+
+impl RenderOnce for Label {
+    fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+        let target_label = if self.single_line {
+            SharedString::from(self.label.replace('\n', "␤"))
+        } else {
+            self.label
+        };
+        self.base.child(target_label)
+    }
+}

crates/ui/src/components/list.rs 🔗

@@ -1,76 +1,11 @@
+mod list;
 mod list_header;
 mod list_item;
 mod list_separator;
 mod list_sub_header;
 
+pub use list::*;
 pub use list_header::*;
 pub use list_item::*;
 pub use list_separator::*;
 pub use list_sub_header::*;
-
-use gpui::AnyElement;
-use smallvec::SmallVec;
-
-use crate::{prelude::*, v_flex, Label};
-
-pub use ListHeader;
-
-#[derive(IntoElement)]
-pub struct List {
-    /// Message to display when the list is empty
-    /// Defaults to "No items"
-    empty_message: SharedString,
-    header: Option<ListHeader>,
-    toggle: Option<bool>,
-    children: SmallVec<[AnyElement; 2]>,
-}
-
-impl Default for List {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-impl List {
-    pub fn new() -> Self {
-        Self {
-            empty_message: "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();
-        self
-    }
-
-    pub fn header(mut self, header: impl Into<Option<ListHeader>>) -> Self {
-        self.header = header.into();
-        self
-    }
-
-    pub fn toggle(mut self, toggle: impl Into<Option<bool>>) -> Self {
-        self.toggle = toggle.into();
-        self
-    }
-}
-
-impl ParentElement for List {
-    fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
-        self.children.extend(elements)
-    }
-}
-
-impl RenderOnce for List {
-    fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
-        v_flex().w_full().py_1().children(self.header).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)),
-            }
-        })
-    }
-}

crates/ui/src/components/list/list.rs 🔗

@@ -13,12 +13,6 @@ pub struct List {
     children: SmallVec<[AnyElement; 2]>,
 }
 
-impl Default for List {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
 impl List {
     pub fn new() -> Self {
         Self {