Merge remote-tracking branch 'origin/main' into cache
# Conflicts: # crates/copilot/src/sign_in.rs # crates/gpui/src/window.rs # crates/workspace/src/pane_group.rs
This commit is contained in:
commit
1c260e6dfd
216 changed files with 4218 additions and 2389 deletions
|
@ -1,13 +1,28 @@
|
|||
use crate::prelude::*;
|
||||
use gpui::{img, Hsla, ImageSource, Img, IntoElement, Styled};
|
||||
|
||||
/// The shape of an [`Avatar`].
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
pub enum Shape {
|
||||
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,
|
||||
|
@ -18,7 +33,7 @@ pub struct Avatar {
|
|||
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(Shape::Circle);
|
||||
self = self.shape(AvatarShape::Circle);
|
||||
}
|
||||
|
||||
let size = cx.rem_size();
|
||||
|
@ -66,14 +81,35 @@ impl Avatar {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn shape(mut self, shape: Shape) -> Self {
|
||||
/// Sets the shape of the avatar image.
|
||||
///
|
||||
/// This method allows the shape of the avatar to be specified using a [`Shape`].
|
||||
/// 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 {
|
||||
Shape::Circle => self.image.rounded_full(),
|
||||
Shape::RoundedRectangle => self.image.rounded_md(),
|
||||
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
|
||||
|
|
|
@ -2,11 +2,78 @@ use gpui::{AnyView, DefiniteLength};
|
|||
|
||||
use crate::{prelude::*, IconPosition, KeyBinding};
|
||||
use crate::{
|
||||
ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, IconSize, Label, LineHeightStyle,
|
||||
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,
|
||||
|
@ -14,15 +81,21 @@ pub struct Button {
|
|||
label_color: Option<Color>,
|
||||
label_size: Option<LabelSize>,
|
||||
selected_label: Option<SharedString>,
|
||||
icon: Option<Icon>,
|
||||
icon: Option<IconName>,
|
||||
icon_position: Option<IconPosition>,
|
||||
icon_size: Option<IconSize>,
|
||||
icon_color: Option<Color>,
|
||||
selected_icon: Option<Icon>,
|
||||
selected_icon: Option<IconName>,
|
||||
key_binding: Option<KeyBinding>,
|
||||
}
|
||||
|
||||
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),
|
||||
|
@ -39,46 +112,55 @@ impl Button {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
}
|
||||
|
||||
pub fn icon(mut self, icon: impl Into<Option<Icon>>) -> 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
|
||||
}
|
||||
|
||||
pub fn selected_icon(mut self, icon: impl Into<Option<Icon>>) -> 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
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
@ -86,6 +168,24 @@ impl Button {
|
|||
}
|
||||
|
||||
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
|
||||
|
@ -93,6 +193,22 @@ impl Selectable for Button {
|
|||
}
|
||||
|
||||
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
|
||||
|
@ -100,6 +216,24 @@ impl SelectableButton for Button {
|
|||
}
|
||||
|
||||
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
|
||||
|
@ -107,6 +241,7 @@ impl Disableable for Button {
|
|||
}
|
||||
|
||||
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,
|
||||
|
@ -117,11 +252,44 @@ impl Clickable for Button {
|
|||
}
|
||||
|
||||
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
|
||||
|
@ -129,20 +297,45 @@ impl FixedWidth for Button {
|
|||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{prelude::*, Icon, IconElement, IconSize};
|
||||
use crate::{prelude::*, Icon, IconName, IconSize};
|
||||
|
||||
/// An icon that appears within a button.
|
||||
///
|
||||
|
@ -6,17 +6,17 @@ use crate::{prelude::*, Icon, IconElement, IconSize};
|
|||
/// or as a standalone icon, like in [`IconButton`](crate::IconButton).
|
||||
#[derive(IntoElement)]
|
||||
pub(super) struct ButtonIcon {
|
||||
icon: Icon,
|
||||
icon: IconName,
|
||||
size: IconSize,
|
||||
color: Color,
|
||||
disabled: bool,
|
||||
selected: bool,
|
||||
selected_icon: Option<Icon>,
|
||||
selected_icon: Option<IconName>,
|
||||
selected_style: Option<ButtonStyle>,
|
||||
}
|
||||
|
||||
impl ButtonIcon {
|
||||
pub fn new(icon: Icon) -> Self {
|
||||
pub fn new(icon: IconName) -> Self {
|
||||
Self {
|
||||
icon,
|
||||
size: IconSize::default(),
|
||||
|
@ -44,7 +44,7 @@ impl ButtonIcon {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn selected_icon(mut self, icon: impl Into<Option<Icon>>) -> Self {
|
||||
pub fn selected_icon(mut self, icon: impl Into<Option<IconName>>) -> Self {
|
||||
self.selected_icon = icon.into();
|
||||
self
|
||||
}
|
||||
|
@ -88,6 +88,6 @@ impl RenderOnce for ButtonIcon {
|
|||
self.color
|
||||
};
|
||||
|
||||
IconElement::new(icon).size(self.size).color(icon_color)
|
||||
Icon::new(icon).size(self.size).color(icon_color)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,12 @@ use smallvec::SmallVec;
|
|||
|
||||
use crate::prelude::*;
|
||||
|
||||
/// A trait for buttons that can be Selected. Enables setting the [`ButtonStyle`] of a button when it is selected.
|
||||
pub trait SelectableButton: Selectable {
|
||||
fn selected_style(self, style: ButtonStyle) -> Self;
|
||||
}
|
||||
|
||||
/// A common set of traits all buttons must implement.
|
||||
pub trait ButtonCommon: Clickable + Disableable {
|
||||
/// A unique element ID to identify the button.
|
||||
fn id(&self) -> &ElementId;
|
||||
|
@ -93,6 +95,7 @@ impl From<ButtonStyle> for Color {
|
|||
}
|
||||
}
|
||||
|
||||
/// The visual appearance of a button.
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
|
||||
pub enum ButtonStyle {
|
||||
/// A filled button with a solid background color. Provides emphasis versus
|
||||
|
@ -260,8 +263,9 @@ impl ButtonStyle {
|
|||
}
|
||||
}
|
||||
|
||||
/// ButtonSize can also be used to help build non-button elements
|
||||
/// that are consistently sized with buttons.
|
||||
/// The height of a button.
|
||||
///
|
||||
/// Can also be used to size non-button elements to align with [`Button`]s.
|
||||
#[derive(Default, PartialEq, Clone, Copy)]
|
||||
pub enum ButtonSize {
|
||||
Large,
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
use gpui::{AnyView, DefiniteLength};
|
||||
|
||||
use crate::{prelude::*, SelectableButton};
|
||||
use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, IconSize};
|
||||
use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, IconName, IconSize};
|
||||
|
||||
use super::button_icon::ButtonIcon;
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct IconButton {
|
||||
base: ButtonLike,
|
||||
icon: Icon,
|
||||
icon: IconName,
|
||||
icon_size: IconSize,
|
||||
icon_color: Color,
|
||||
selected_icon: Option<Icon>,
|
||||
selected_icon: Option<IconName>,
|
||||
}
|
||||
|
||||
impl IconButton {
|
||||
pub fn new(id: impl Into<ElementId>, icon: Icon) -> Self {
|
||||
pub fn new(id: impl Into<ElementId>, icon: IconName) -> Self {
|
||||
Self {
|
||||
base: ButtonLike::new(id),
|
||||
icon,
|
||||
|
@ -35,7 +35,7 @@ impl IconButton {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn selected_icon(mut self, icon: impl Into<Option<Icon>>) -> Self {
|
||||
pub fn selected_icon(mut self, icon: impl Into<Option<IconName>>) -> Self {
|
||||
self.selected_icon = icon.into();
|
||||
self
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use gpui::{div, prelude::*, ElementId, IntoElement, Styled, WindowContext};
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::{Color, Icon, IconElement, Selection};
|
||||
use crate::{Color, Icon, IconName, Selection};
|
||||
|
||||
pub type CheckHandler = Box<dyn Fn(&Selection, &mut WindowContext) + 'static>;
|
||||
|
||||
|
@ -47,7 +47,7 @@ impl RenderOnce for Checkbox {
|
|||
let group_id = format!("checkbox_group_{:?}", self.id);
|
||||
|
||||
let icon = match self.checked {
|
||||
Selection::Selected => Some(IconElement::new(Icon::Check).size(IconSize::Small).color(
|
||||
Selection::Selected => Some(Icon::new(IconName::Check).size(IconSize::Small).color(
|
||||
if self.disabled {
|
||||
Color::Disabled
|
||||
} else {
|
||||
|
@ -55,7 +55,7 @@ impl RenderOnce for Checkbox {
|
|||
},
|
||||
)),
|
||||
Selection::Indeterminate => Some(
|
||||
IconElement::new(Icon::Dash)
|
||||
Icon::new(IconName::Dash)
|
||||
.size(IconSize::Small)
|
||||
.color(if self.disabled {
|
||||
Color::Disabled
|
||||
|
@ -73,7 +73,7 @@ impl RenderOnce for Checkbox {
|
|||
// - a previously agreed to license that has been updated
|
||||
//
|
||||
// For the sake of styles we treat the indeterminate state as selected,
|
||||
// but it's icon will be different.
|
||||
// but its icon will be different.
|
||||
let selected =
|
||||
self.checked == Selection::Selected || self.checked == Selection::Indeterminate;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
h_stack, prelude::*, v_stack, Icon, IconElement, KeyBinding, Label, List, ListItem,
|
||||
ListSeparator, ListSubHeader,
|
||||
h_stack, prelude::*, v_stack, Icon, IconName, KeyBinding, Label, List, ListItem, ListSeparator,
|
||||
ListSubHeader,
|
||||
};
|
||||
use gpui::{
|
||||
px, Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView,
|
||||
|
@ -14,7 +14,7 @@ enum ContextMenuItem {
|
|||
Header(SharedString),
|
||||
Entry {
|
||||
label: SharedString,
|
||||
icon: Option<Icon>,
|
||||
icon: Option<IconName>,
|
||||
handler: Rc<dyn Fn(&mut WindowContext)>,
|
||||
action: Option<Box<dyn Action>>,
|
||||
},
|
||||
|
@ -117,7 +117,7 @@ impl ContextMenu {
|
|||
label: label.into(),
|
||||
action: Some(action.boxed_clone()),
|
||||
handler: Rc::new(move |cx| cx.dispatch_action(action.boxed_clone())),
|
||||
icon: Some(Icon::Link),
|
||||
icon: Some(IconName::Link),
|
||||
});
|
||||
self
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ impl Render for ContextMenu {
|
|||
h_stack()
|
||||
.gap_1()
|
||||
.child(Label::new(label.clone()))
|
||||
.child(IconElement::new(*icon))
|
||||
.child(Icon::new(*icon))
|
||||
.into_any_element()
|
||||
} else {
|
||||
Label::new(label.clone()).into_any_element()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use gpui::ClickEvent;
|
||||
|
||||
use crate::{prelude::*, Color, Icon, IconButton, IconSize};
|
||||
use crate::{prelude::*, Color, IconButton, IconName, IconSize};
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct Disclosure {
|
||||
|
@ -32,8 +32,8 @@ impl RenderOnce for Disclosure {
|
|||
IconButton::new(
|
||||
self.id,
|
||||
match self.is_open {
|
||||
true => Icon::ChevronDown,
|
||||
false => Icon::ChevronRight,
|
||||
true => IconName::ChevronDown,
|
||||
false => IconName::ChevronRight,
|
||||
},
|
||||
)
|
||||
.icon_color(Color::Muted)
|
||||
|
|
|
@ -7,6 +7,7 @@ enum DividerDirection {
|
|||
Vertical,
|
||||
}
|
||||
|
||||
/// The color of a [`Divider`].
|
||||
#[derive(Default)]
|
||||
pub enum DividerColor {
|
||||
Border,
|
||||
|
|
|
@ -22,7 +22,7 @@ impl IconSize {
|
|||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone, EnumIter)]
|
||||
pub enum Icon {
|
||||
pub enum IconName {
|
||||
Ai,
|
||||
ArrowDown,
|
||||
ArrowLeft,
|
||||
|
@ -111,118 +111,108 @@ pub enum Icon {
|
|||
ZedXCopilot,
|
||||
}
|
||||
|
||||
impl Icon {
|
||||
impl IconName {
|
||||
pub fn path(self) -> &'static str {
|
||||
match self {
|
||||
Icon::Ai => "icons/ai.svg",
|
||||
Icon::ArrowDown => "icons/arrow_down.svg",
|
||||
Icon::ArrowLeft => "icons/arrow_left.svg",
|
||||
Icon::ArrowRight => "icons/arrow_right.svg",
|
||||
Icon::ArrowUp => "icons/arrow_up.svg",
|
||||
Icon::ArrowUpRight => "icons/arrow_up_right.svg",
|
||||
Icon::ArrowCircle => "icons/arrow_circle.svg",
|
||||
Icon::AtSign => "icons/at_sign.svg",
|
||||
Icon::AudioOff => "icons/speaker_off.svg",
|
||||
Icon::AudioOn => "icons/speaker_loud.svg",
|
||||
Icon::Backspace => "icons/backspace.svg",
|
||||
Icon::Bell => "icons/bell.svg",
|
||||
Icon::BellOff => "icons/bell_off.svg",
|
||||
Icon::BellRing => "icons/bell_ring.svg",
|
||||
Icon::Bolt => "icons/bolt.svg",
|
||||
Icon::CaseSensitive => "icons/case_insensitive.svg",
|
||||
Icon::Check => "icons/check.svg",
|
||||
Icon::ChevronDown => "icons/chevron_down.svg",
|
||||
Icon::ChevronLeft => "icons/chevron_left.svg",
|
||||
Icon::ChevronRight => "icons/chevron_right.svg",
|
||||
Icon::ChevronUp => "icons/chevron_up.svg",
|
||||
Icon::Close => "icons/x.svg",
|
||||
Icon::Collab => "icons/user_group_16.svg",
|
||||
Icon::Command => "icons/command.svg",
|
||||
Icon::Control => "icons/control.svg",
|
||||
Icon::Copilot => "icons/copilot.svg",
|
||||
Icon::CopilotDisabled => "icons/copilot_disabled.svg",
|
||||
Icon::CopilotError => "icons/copilot_error.svg",
|
||||
Icon::CopilotInit => "icons/copilot_init.svg",
|
||||
Icon::Copy => "icons/copy.svg",
|
||||
Icon::Dash => "icons/dash.svg",
|
||||
Icon::Delete => "icons/delete.svg",
|
||||
Icon::Disconnected => "icons/disconnected.svg",
|
||||
Icon::Ellipsis => "icons/ellipsis.svg",
|
||||
Icon::Envelope => "icons/feedback.svg",
|
||||
Icon::Escape => "icons/escape.svg",
|
||||
Icon::ExclamationTriangle => "icons/warning.svg",
|
||||
Icon::Exit => "icons/exit.svg",
|
||||
Icon::ExternalLink => "icons/external_link.svg",
|
||||
Icon::File => "icons/file.svg",
|
||||
Icon::FileDoc => "icons/file_icons/book.svg",
|
||||
Icon::FileGeneric => "icons/file_icons/file.svg",
|
||||
Icon::FileGit => "icons/file_icons/git.svg",
|
||||
Icon::FileLock => "icons/file_icons/lock.svg",
|
||||
Icon::FileRust => "icons/file_icons/rust.svg",
|
||||
Icon::FileToml => "icons/file_icons/toml.svg",
|
||||
Icon::FileTree => "icons/project.svg",
|
||||
Icon::Filter => "icons/filter.svg",
|
||||
Icon::Folder => "icons/file_icons/folder.svg",
|
||||
Icon::FolderOpen => "icons/file_icons/folder_open.svg",
|
||||
Icon::FolderX => "icons/stop_sharing.svg",
|
||||
Icon::Github => "icons/github.svg",
|
||||
Icon::Hash => "icons/hash.svg",
|
||||
Icon::InlayHint => "icons/inlay_hint.svg",
|
||||
Icon::Link => "icons/link.svg",
|
||||
Icon::MagicWand => "icons/magic_wand.svg",
|
||||
Icon::MagnifyingGlass => "icons/magnifying_glass.svg",
|
||||
Icon::MailOpen => "icons/mail_open.svg",
|
||||
Icon::Maximize => "icons/maximize.svg",
|
||||
Icon::Menu => "icons/menu.svg",
|
||||
Icon::MessageBubbles => "icons/conversations.svg",
|
||||
Icon::Mic => "icons/mic.svg",
|
||||
Icon::MicMute => "icons/mic_mute.svg",
|
||||
Icon::Minimize => "icons/minimize.svg",
|
||||
Icon::Option => "icons/option.svg",
|
||||
Icon::PageDown => "icons/page_down.svg",
|
||||
Icon::PageUp => "icons/page_up.svg",
|
||||
Icon::Plus => "icons/plus.svg",
|
||||
Icon::Public => "icons/public.svg",
|
||||
Icon::Quote => "icons/quote.svg",
|
||||
Icon::Replace => "icons/replace.svg",
|
||||
Icon::ReplaceAll => "icons/replace_all.svg",
|
||||
Icon::ReplaceNext => "icons/replace_next.svg",
|
||||
Icon::Return => "icons/return.svg",
|
||||
Icon::Screen => "icons/desktop.svg",
|
||||
Icon::SelectAll => "icons/select_all.svg",
|
||||
Icon::Shift => "icons/shift.svg",
|
||||
Icon::Snip => "icons/snip.svg",
|
||||
Icon::Space => "icons/space.svg",
|
||||
Icon::Split => "icons/split.svg",
|
||||
Icon::Tab => "icons/tab.svg",
|
||||
Icon::Terminal => "icons/terminal.svg",
|
||||
Icon::Update => "icons/update.svg",
|
||||
Icon::WholeWord => "icons/word_search.svg",
|
||||
Icon::XCircle => "icons/error.svg",
|
||||
Icon::ZedXCopilot => "icons/zed_x_copilot.svg",
|
||||
IconName::Ai => "icons/ai.svg",
|
||||
IconName::ArrowDown => "icons/arrow_down.svg",
|
||||
IconName::ArrowLeft => "icons/arrow_left.svg",
|
||||
IconName::ArrowRight => "icons/arrow_right.svg",
|
||||
IconName::ArrowUp => "icons/arrow_up.svg",
|
||||
IconName::ArrowUpRight => "icons/arrow_up_right.svg",
|
||||
IconName::ArrowCircle => "icons/arrow_circle.svg",
|
||||
IconName::AtSign => "icons/at_sign.svg",
|
||||
IconName::AudioOff => "icons/speaker_off.svg",
|
||||
IconName::AudioOn => "icons/speaker_loud.svg",
|
||||
IconName::Backspace => "icons/backspace.svg",
|
||||
IconName::Bell => "icons/bell.svg",
|
||||
IconName::BellOff => "icons/bell_off.svg",
|
||||
IconName::BellRing => "icons/bell_ring.svg",
|
||||
IconName::Bolt => "icons/bolt.svg",
|
||||
IconName::CaseSensitive => "icons/case_insensitive.svg",
|
||||
IconName::Check => "icons/check.svg",
|
||||
IconName::ChevronDown => "icons/chevron_down.svg",
|
||||
IconName::ChevronLeft => "icons/chevron_left.svg",
|
||||
IconName::ChevronRight => "icons/chevron_right.svg",
|
||||
IconName::ChevronUp => "icons/chevron_up.svg",
|
||||
IconName::Close => "icons/x.svg",
|
||||
IconName::Collab => "icons/user_group_16.svg",
|
||||
IconName::Command => "icons/command.svg",
|
||||
IconName::Control => "icons/control.svg",
|
||||
IconName::Copilot => "icons/copilot.svg",
|
||||
IconName::CopilotDisabled => "icons/copilot_disabled.svg",
|
||||
IconName::CopilotError => "icons/copilot_error.svg",
|
||||
IconName::CopilotInit => "icons/copilot_init.svg",
|
||||
IconName::Copy => "icons/copy.svg",
|
||||
IconName::Dash => "icons/dash.svg",
|
||||
IconName::Delete => "icons/delete.svg",
|
||||
IconName::Disconnected => "icons/disconnected.svg",
|
||||
IconName::Ellipsis => "icons/ellipsis.svg",
|
||||
IconName::Envelope => "icons/feedback.svg",
|
||||
IconName::Escape => "icons/escape.svg",
|
||||
IconName::ExclamationTriangle => "icons/warning.svg",
|
||||
IconName::Exit => "icons/exit.svg",
|
||||
IconName::ExternalLink => "icons/external_link.svg",
|
||||
IconName::File => "icons/file.svg",
|
||||
IconName::FileDoc => "icons/file_icons/book.svg",
|
||||
IconName::FileGeneric => "icons/file_icons/file.svg",
|
||||
IconName::FileGit => "icons/file_icons/git.svg",
|
||||
IconName::FileLock => "icons/file_icons/lock.svg",
|
||||
IconName::FileRust => "icons/file_icons/rust.svg",
|
||||
IconName::FileToml => "icons/file_icons/toml.svg",
|
||||
IconName::FileTree => "icons/project.svg",
|
||||
IconName::Filter => "icons/filter.svg",
|
||||
IconName::Folder => "icons/file_icons/folder.svg",
|
||||
IconName::FolderOpen => "icons/file_icons/folder_open.svg",
|
||||
IconName::FolderX => "icons/stop_sharing.svg",
|
||||
IconName::Github => "icons/github.svg",
|
||||
IconName::Hash => "icons/hash.svg",
|
||||
IconName::InlayHint => "icons/inlay_hint.svg",
|
||||
IconName::Link => "icons/link.svg",
|
||||
IconName::MagicWand => "icons/magic_wand.svg",
|
||||
IconName::MagnifyingGlass => "icons/magnifying_glass.svg",
|
||||
IconName::MailOpen => "icons/mail_open.svg",
|
||||
IconName::Maximize => "icons/maximize.svg",
|
||||
IconName::Menu => "icons/menu.svg",
|
||||
IconName::MessageBubbles => "icons/conversations.svg",
|
||||
IconName::Mic => "icons/mic.svg",
|
||||
IconName::MicMute => "icons/mic_mute.svg",
|
||||
IconName::Minimize => "icons/minimize.svg",
|
||||
IconName::Option => "icons/option.svg",
|
||||
IconName::PageDown => "icons/page_down.svg",
|
||||
IconName::PageUp => "icons/page_up.svg",
|
||||
IconName::Plus => "icons/plus.svg",
|
||||
IconName::Public => "icons/public.svg",
|
||||
IconName::Quote => "icons/quote.svg",
|
||||
IconName::Replace => "icons/replace.svg",
|
||||
IconName::ReplaceAll => "icons/replace_all.svg",
|
||||
IconName::ReplaceNext => "icons/replace_next.svg",
|
||||
IconName::Return => "icons/return.svg",
|
||||
IconName::Screen => "icons/desktop.svg",
|
||||
IconName::SelectAll => "icons/select_all.svg",
|
||||
IconName::Shift => "icons/shift.svg",
|
||||
IconName::Snip => "icons/snip.svg",
|
||||
IconName::Space => "icons/space.svg",
|
||||
IconName::Split => "icons/split.svg",
|
||||
IconName::Tab => "icons/tab.svg",
|
||||
IconName::Terminal => "icons/terminal.svg",
|
||||
IconName::Update => "icons/update.svg",
|
||||
IconName::WholeWord => "icons/word_search.svg",
|
||||
IconName::XCircle => "icons/error.svg",
|
||||
IconName::ZedXCopilot => "icons/zed_x_copilot.svg",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct IconElement {
|
||||
pub struct Icon {
|
||||
path: SharedString,
|
||||
color: Color,
|
||||
size: IconSize,
|
||||
}
|
||||
|
||||
impl RenderOnce for IconElement {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
svg()
|
||||
.size(self.size.rems())
|
||||
.flex_none()
|
||||
.path(self.path)
|
||||
.text_color(self.color.color(cx))
|
||||
}
|
||||
}
|
||||
|
||||
impl IconElement {
|
||||
pub fn new(icon: Icon) -> Self {
|
||||
impl Icon {
|
||||
pub fn new(icon: IconName) -> Self {
|
||||
Self {
|
||||
path: icon.path().into(),
|
||||
color: Color::default(),
|
||||
|
@ -248,3 +238,13 @@ impl IconElement {
|
|||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for Icon {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
svg()
|
||||
.size(self.size.rems())
|
||||
.flex_none()
|
||||
.path(self.path)
|
||||
.text_color(self.color.color(cx))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{h_stack, prelude::*, Icon, IconElement, IconSize};
|
||||
use crate::{h_stack, prelude::*, Icon, IconName, IconSize};
|
||||
use gpui::{relative, rems, Action, FocusHandle, IntoElement, Keystroke};
|
||||
|
||||
#[derive(IntoElement, Clone)]
|
||||
|
@ -26,16 +26,16 @@ impl RenderOnce for KeyBinding {
|
|||
.text_color(cx.theme().colors().text_muted)
|
||||
.when(keystroke.modifiers.function, |el| el.child(Key::new("fn")))
|
||||
.when(keystroke.modifiers.control, |el| {
|
||||
el.child(KeyIcon::new(Icon::Control))
|
||||
el.child(KeyIcon::new(IconName::Control))
|
||||
})
|
||||
.when(keystroke.modifiers.alt, |el| {
|
||||
el.child(KeyIcon::new(Icon::Option))
|
||||
el.child(KeyIcon::new(IconName::Option))
|
||||
})
|
||||
.when(keystroke.modifiers.command, |el| {
|
||||
el.child(KeyIcon::new(Icon::Command))
|
||||
el.child(KeyIcon::new(IconName::Command))
|
||||
})
|
||||
.when(keystroke.modifiers.shift, |el| {
|
||||
el.child(KeyIcon::new(Icon::Shift))
|
||||
el.child(KeyIcon::new(IconName::Shift))
|
||||
})
|
||||
.when_some(key_icon, |el, icon| el.child(KeyIcon::new(icon)))
|
||||
.when(key_icon.is_none(), |el| {
|
||||
|
@ -62,21 +62,21 @@ impl KeyBinding {
|
|||
Some(Self::new(key_binding))
|
||||
}
|
||||
|
||||
fn icon_for_key(keystroke: &Keystroke) -> Option<Icon> {
|
||||
fn icon_for_key(keystroke: &Keystroke) -> Option<IconName> {
|
||||
match keystroke.key.as_str() {
|
||||
"left" => Some(Icon::ArrowLeft),
|
||||
"right" => Some(Icon::ArrowRight),
|
||||
"up" => Some(Icon::ArrowUp),
|
||||
"down" => Some(Icon::ArrowDown),
|
||||
"backspace" => Some(Icon::Backspace),
|
||||
"delete" => Some(Icon::Delete),
|
||||
"return" => Some(Icon::Return),
|
||||
"enter" => Some(Icon::Return),
|
||||
"tab" => Some(Icon::Tab),
|
||||
"space" => Some(Icon::Space),
|
||||
"escape" => Some(Icon::Escape),
|
||||
"pagedown" => Some(Icon::PageDown),
|
||||
"pageup" => Some(Icon::PageUp),
|
||||
"left" => Some(IconName::ArrowLeft),
|
||||
"right" => Some(IconName::ArrowRight),
|
||||
"up" => Some(IconName::ArrowUp),
|
||||
"down" => Some(IconName::ArrowDown),
|
||||
"backspace" => Some(IconName::Backspace),
|
||||
"delete" => Some(IconName::Delete),
|
||||
"return" => Some(IconName::Return),
|
||||
"enter" => Some(IconName::Return),
|
||||
"tab" => Some(IconName::Tab),
|
||||
"space" => Some(IconName::Space),
|
||||
"escape" => Some(IconName::Escape),
|
||||
"pagedown" => Some(IconName::PageDown),
|
||||
"pageup" => Some(IconName::PageUp),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -120,13 +120,13 @@ impl Key {
|
|||
|
||||
#[derive(IntoElement)]
|
||||
pub struct KeyIcon {
|
||||
icon: Icon,
|
||||
icon: IconName,
|
||||
}
|
||||
|
||||
impl RenderOnce for KeyIcon {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
div().w(rems(14. / 16.)).child(
|
||||
IconElement::new(self.icon)
|
||||
Icon::new(self.icon)
|
||||
.size(IconSize::Small)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
|
@ -134,7 +134,7 @@ impl RenderOnce for KeyIcon {
|
|||
}
|
||||
|
||||
impl KeyIcon {
|
||||
pub fn new(icon: Icon) -> Self {
|
||||
pub fn new(icon: IconName) -> Self {
|
||||
Self { icon }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,34 @@ use gpui::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,
|
||||
|
@ -9,6 +37,15 @@ pub struct Label {
|
|||
}
|
||||
|
||||
impl Label {
|
||||
/// Create 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(),
|
||||
|
@ -18,21 +55,57 @@ impl Label {
|
|||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
|
|
@ -19,10 +19,18 @@ pub enum LineHeightStyle {
|
|||
UiLabel,
|
||||
}
|
||||
|
||||
/// A common set of traits all labels must implement.
|
||||
pub trait LabelCommon {
|
||||
/// Sets the size of the label using a [`LabelSize`].
|
||||
fn size(self, size: LabelSize) -> Self;
|
||||
|
||||
/// Sets the line height style of the label using a [`LineHeightStyle`].
|
||||
fn line_height_style(self, line_height_style: LineHeightStyle) -> Self;
|
||||
|
||||
/// Sets the color of the label using a [`Color`].
|
||||
fn color(self, color: Color) -> Self;
|
||||
|
||||
/// Sets the strikethrough property of the label.
|
||||
fn strikethrough(self, strikethrough: bool) -> Self;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use crate::prelude::*;
|
||||
use crate::{h_stack, Icon, IconElement, IconSize, Label};
|
||||
use crate::{h_stack, Icon, IconName, IconSize, Label};
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct ListSubHeader {
|
||||
label: SharedString,
|
||||
start_slot: Option<Icon>,
|
||||
start_slot: Option<IconName>,
|
||||
inset: bool,
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ impl ListSubHeader {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn left_icon(mut self, left_icon: Option<Icon>) -> Self {
|
||||
pub fn left_icon(mut self, left_icon: Option<IconName>) -> Self {
|
||||
self.start_slot = left_icon;
|
||||
self
|
||||
}
|
||||
|
@ -40,11 +40,10 @@ impl RenderOnce for ListSubHeader {
|
|||
.flex()
|
||||
.gap_1()
|
||||
.items_center()
|
||||
.children(self.start_slot.map(|i| {
|
||||
IconElement::new(i)
|
||||
.color(Color::Muted)
|
||||
.size(IconSize::Small)
|
||||
}))
|
||||
.children(
|
||||
self.start_slot
|
||||
.map(|i| Icon::new(i).color(Color::Muted).size(IconSize::Small)),
|
||||
)
|
||||
.child(Label::new(self.label.clone()).color(Color::Muted)),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -108,6 +108,7 @@ impl<M: ManagedView> PopoverMenu<M> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a [`PopoverMenu`]
|
||||
pub fn popover_menu<M: ManagedView>(id: impl Into<ElementId>) -> PopoverMenu<M> {
|
||||
PopoverMenu {
|
||||
id: id.into(),
|
||||
|
|
|
@ -39,6 +39,7 @@ impl<M: ManagedView> RightClickMenu<M> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a [`RightClickMenu`]
|
||||
pub fn right_click_menu<M: ManagedView>(id: impl Into<ElementId>) -> RightClickMenu<M> {
|
||||
RightClickMenu {
|
||||
id: id.into(),
|
||||
|
|
|
@ -2,17 +2,13 @@ use gpui::{div, Div};
|
|||
|
||||
use crate::StyledExt;
|
||||
|
||||
/// Horizontally stacks elements.
|
||||
///
|
||||
/// Sets `flex()`, `flex_row()`, `items_center()`
|
||||
/// Horizontally stacks elements. Sets `flex()`, `flex_row()`, `items_center()`
|
||||
#[track_caller]
|
||||
pub fn h_stack() -> Div {
|
||||
div().h_flex()
|
||||
}
|
||||
|
||||
/// Vertically stacks elements.
|
||||
///
|
||||
/// Sets `flex()`, `flex_col()`
|
||||
/// Vertically stacks elements. Sets `flex()`, `flex_col()`
|
||||
#[track_caller]
|
||||
pub fn v_stack() -> Div {
|
||||
div().v_flex()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use gpui::Render;
|
||||
use story::Story;
|
||||
|
||||
use crate::{prelude::*, Icon};
|
||||
use crate::{prelude::*, IconName};
|
||||
use crate::{Button, ButtonStyle};
|
||||
|
||||
pub struct ButtonStory;
|
||||
|
@ -23,12 +23,12 @@ impl Render for ButtonStory {
|
|||
.child(Story::label("With `label_color`"))
|
||||
.child(Button::new("filled_with_label_color", "Click me").color(Color::Created))
|
||||
.child(Story::label("With `icon`"))
|
||||
.child(Button::new("filled_with_icon", "Click me").icon(Icon::FileGit))
|
||||
.child(Button::new("filled_with_icon", "Click me").icon(IconName::FileGit))
|
||||
.child(Story::label("Selected with `icon`"))
|
||||
.child(
|
||||
Button::new("filled_and_selected_with_icon", "Click me")
|
||||
.selected(true)
|
||||
.icon(Icon::FileGit),
|
||||
.icon(IconName::FileGit),
|
||||
)
|
||||
.child(Story::label("Default (Subtle)"))
|
||||
.child(Button::new("default_subtle", "Click me").style(ButtonStyle::Subtle))
|
||||
|
|
|
@ -3,17 +3,17 @@ use story::Story;
|
|||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::{Icon, IconElement};
|
||||
use crate::{Icon, IconName};
|
||||
|
||||
pub struct IconStory;
|
||||
|
||||
impl Render for IconStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let icons = Icon::iter();
|
||||
let icons = IconName::iter();
|
||||
|
||||
Story::container()
|
||||
.child(Story::title_for::<IconElement>())
|
||||
.child(Story::title_for::<Icon>())
|
||||
.child(Story::label("All Icons"))
|
||||
.child(div().flex().gap_3().children(icons.map(IconElement::new)))
|
||||
.child(div().flex().gap_3().children(icons.map(Icon::new)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use gpui::Render;
|
|||
use story::{StoryContainer, StoryItem, StorySection};
|
||||
|
||||
use crate::{prelude::*, Tooltip};
|
||||
use crate::{Icon, IconButton};
|
||||
use crate::{IconButton, IconName};
|
||||
|
||||
pub struct IconButtonStory;
|
||||
|
||||
|
@ -10,7 +10,7 @@ impl Render for IconButtonStory {
|
|||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let default_button = StoryItem::new(
|
||||
"Default",
|
||||
IconButton::new("default_icon_button", Icon::Hash),
|
||||
IconButton::new("default_icon_button", IconName::Hash),
|
||||
)
|
||||
.description("Displays an icon button.")
|
||||
.usage(
|
||||
|
@ -21,7 +21,7 @@ impl Render for IconButtonStory {
|
|||
|
||||
let selected_button = StoryItem::new(
|
||||
"Selected",
|
||||
IconButton::new("selected_icon_button", Icon::Hash).selected(true),
|
||||
IconButton::new("selected_icon_button", IconName::Hash).selected(true),
|
||||
)
|
||||
.description("Displays an icon button that is selected.")
|
||||
.usage(
|
||||
|
@ -32,9 +32,9 @@ impl Render for IconButtonStory {
|
|||
|
||||
let selected_with_selected_icon = StoryItem::new(
|
||||
"Selected with `selected_icon`",
|
||||
IconButton::new("selected_with_selected_icon_button", Icon::AudioOn)
|
||||
IconButton::new("selected_with_selected_icon_button", IconName::AudioOn)
|
||||
.selected(true)
|
||||
.selected_icon(Icon::AudioOff),
|
||||
.selected_icon(IconName::AudioOff),
|
||||
)
|
||||
.description(
|
||||
"Displays an icon button that is selected and shows a different icon when selected.",
|
||||
|
@ -49,7 +49,7 @@ impl Render for IconButtonStory {
|
|||
|
||||
let disabled_button = StoryItem::new(
|
||||
"Disabled",
|
||||
IconButton::new("disabled_icon_button", Icon::Hash).disabled(true),
|
||||
IconButton::new("disabled_icon_button", IconName::Hash).disabled(true),
|
||||
)
|
||||
.description("Displays an icon button that is disabled.")
|
||||
.usage(
|
||||
|
@ -60,7 +60,7 @@ impl Render for IconButtonStory {
|
|||
|
||||
let with_on_click_button = StoryItem::new(
|
||||
"With `on_click`",
|
||||
IconButton::new("with_on_click_button", Icon::Ai).on_click(|_event, _cx| {
|
||||
IconButton::new("with_on_click_button", IconName::Ai).on_click(|_event, _cx| {
|
||||
println!("Clicked!");
|
||||
}),
|
||||
)
|
||||
|
@ -75,7 +75,7 @@ impl Render for IconButtonStory {
|
|||
|
||||
let with_tooltip_button = StoryItem::new(
|
||||
"With `tooltip`",
|
||||
IconButton::new("with_tooltip_button", Icon::MessageBubbles)
|
||||
IconButton::new("with_tooltip_button", IconName::MessageBubbles)
|
||||
.tooltip(|cx| Tooltip::text("Open messages", cx)),
|
||||
)
|
||||
.description("Displays an icon button that has a tooltip when hovered.")
|
||||
|
@ -88,7 +88,7 @@ impl Render for IconButtonStory {
|
|||
|
||||
let selected_with_tooltip_button = StoryItem::new(
|
||||
"Selected with `tooltip`",
|
||||
IconButton::new("selected_with_tooltip_button", Icon::InlayHint)
|
||||
IconButton::new("selected_with_tooltip_button", IconName::InlayHint)
|
||||
.selected(true)
|
||||
.tooltip(|cx| Tooltip::text("Toggle inlay hints", cx)),
|
||||
)
|
||||
|
|
|
@ -2,7 +2,7 @@ use gpui::Render;
|
|||
use story::Story;
|
||||
|
||||
use crate::{prelude::*, IconButton};
|
||||
use crate::{Icon, ListHeader};
|
||||
use crate::{IconName, ListHeader};
|
||||
|
||||
pub struct ListHeaderStory;
|
||||
|
||||
|
@ -13,19 +13,19 @@ impl Render for ListHeaderStory {
|
|||
.child(Story::label("Default"))
|
||||
.child(ListHeader::new("Section 1"))
|
||||
.child(Story::label("With left icon"))
|
||||
.child(ListHeader::new("Section 2").start_slot(IconElement::new(Icon::Bell)))
|
||||
.child(ListHeader::new("Section 2").start_slot(Icon::new(IconName::Bell)))
|
||||
.child(Story::label("With left icon and meta"))
|
||||
.child(
|
||||
ListHeader::new("Section 3")
|
||||
.start_slot(IconElement::new(Icon::BellOff))
|
||||
.end_slot(IconButton::new("action_1", Icon::Bolt)),
|
||||
.start_slot(Icon::new(IconName::BellOff))
|
||||
.end_slot(IconButton::new("action_1", IconName::Bolt)),
|
||||
)
|
||||
.child(Story::label("With multiple meta"))
|
||||
.child(
|
||||
ListHeader::new("Section 4")
|
||||
.end_slot(IconButton::new("action_1", Icon::Bolt))
|
||||
.end_slot(IconButton::new("action_2", Icon::ExclamationTriangle))
|
||||
.end_slot(IconButton::new("action_3", Icon::Plus)),
|
||||
.end_slot(IconButton::new("action_1", IconName::Bolt))
|
||||
.end_slot(IconButton::new("action_2", IconName::ExclamationTriangle))
|
||||
.end_slot(IconButton::new("action_3", IconName::Plus)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use gpui::Render;
|
||||
use gpui::{Render, SharedUrl};
|
||||
use story::Story;
|
||||
|
||||
use crate::{prelude::*, Avatar};
|
||||
use crate::{Icon, ListItem};
|
||||
use crate::{IconName, ListItem};
|
||||
|
||||
pub struct ListItemStory;
|
||||
|
||||
|
@ -18,13 +18,13 @@ impl Render for ListItemStory {
|
|||
ListItem::new("inset_list_item")
|
||||
.inset(true)
|
||||
.start_slot(
|
||||
IconElement::new(Icon::Bell)
|
||||
Icon::new(IconName::Bell)
|
||||
.size(IconSize::Small)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
.child("Hello, world!")
|
||||
.end_slot(
|
||||
IconElement::new(Icon::Bell)
|
||||
Icon::new(IconName::Bell)
|
||||
.size(IconSize::Small)
|
||||
.color(Color::Muted),
|
||||
),
|
||||
|
@ -34,7 +34,7 @@ impl Render for ListItemStory {
|
|||
ListItem::new("with start slot_icon")
|
||||
.child("Hello, world!")
|
||||
.start_slot(
|
||||
IconElement::new(Icon::Bell)
|
||||
Icon::new(IconName::Bell)
|
||||
.size(IconSize::Small)
|
||||
.color(Color::Muted),
|
||||
),
|
||||
|
@ -43,7 +43,7 @@ impl Render for ListItemStory {
|
|||
.child(
|
||||
ListItem::new("with_start slot avatar")
|
||||
.child("Hello, world!")
|
||||
.start_slot(Avatar::new(SharedString::from(
|
||||
.start_slot(Avatar::new(SharedUrl::from(
|
||||
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
||||
))),
|
||||
)
|
||||
|
@ -51,7 +51,7 @@ impl Render for ListItemStory {
|
|||
.child(
|
||||
ListItem::new("with_left_avatar")
|
||||
.child("Hello, world!")
|
||||
.end_slot(Avatar::new(SharedString::from(
|
||||
.end_slot(Avatar::new(SharedUrl::from(
|
||||
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
||||
))),
|
||||
)
|
||||
|
@ -62,23 +62,23 @@ impl Render for ListItemStory {
|
|||
.end_slot(
|
||||
h_stack()
|
||||
.gap_2()
|
||||
.child(Avatar::new(SharedString::from(
|
||||
.child(Avatar::new(SharedUrl::from(
|
||||
"https://avatars.githubusercontent.com/u/1789?v=4",
|
||||
)))
|
||||
.child(Avatar::new(SharedString::from(
|
||||
.child(Avatar::new(SharedUrl::from(
|
||||
"https://avatars.githubusercontent.com/u/1789?v=4",
|
||||
)))
|
||||
.child(Avatar::new(SharedString::from(
|
||||
.child(Avatar::new(SharedUrl::from(
|
||||
"https://avatars.githubusercontent.com/u/1789?v=4",
|
||||
)))
|
||||
.child(Avatar::new(SharedString::from(
|
||||
.child(Avatar::new(SharedUrl::from(
|
||||
"https://avatars.githubusercontent.com/u/1789?v=4",
|
||||
)))
|
||||
.child(Avatar::new(SharedString::from(
|
||||
.child(Avatar::new(SharedUrl::from(
|
||||
"https://avatars.githubusercontent.com/u/1789?v=4",
|
||||
))),
|
||||
)
|
||||
.end_hover_slot(Avatar::new(SharedString::from(
|
||||
.end_hover_slot(Avatar::new(SharedUrl::from(
|
||||
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
||||
))),
|
||||
)
|
||||
|
|
|
@ -27,7 +27,7 @@ impl Render for TabStory {
|
|||
h_stack().child(
|
||||
Tab::new("tab_1")
|
||||
.end_slot(
|
||||
IconButton::new("close_button", Icon::Close)
|
||||
IconButton::new("close_button", IconName::Close)
|
||||
.icon_color(Color::Muted)
|
||||
.size(ButtonSize::None)
|
||||
.icon_size(IconSize::XSmall),
|
||||
|
|
|
@ -38,16 +38,19 @@ impl Render for TabBarStory {
|
|||
h_stack().child(
|
||||
TabBar::new("tab_bar_1")
|
||||
.start_child(
|
||||
IconButton::new("navigate_backward", Icon::ArrowLeft)
|
||||
IconButton::new("navigate_backward", IconName::ArrowLeft)
|
||||
.icon_size(IconSize::Small),
|
||||
)
|
||||
.start_child(
|
||||
IconButton::new("navigate_forward", Icon::ArrowRight)
|
||||
IconButton::new("navigate_forward", IconName::ArrowRight)
|
||||
.icon_size(IconSize::Small),
|
||||
)
|
||||
.end_child(IconButton::new("new", Icon::Plus).icon_size(IconSize::Small))
|
||||
.end_child(
|
||||
IconButton::new("split_pane", Icon::Split).icon_size(IconSize::Small),
|
||||
IconButton::new("new", IconName::Plus).icon_size(IconSize::Small),
|
||||
)
|
||||
.end_child(
|
||||
IconButton::new("split_pane", IconName::Split)
|
||||
.icon_size(IconSize::Small),
|
||||
)
|
||||
.children(tabs),
|
||||
),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue