More previews (#20329)

Release Notes:

- N/A
This commit is contained in:
Nate Butler 2024-11-06 21:15:35 -05:00 committed by GitHub
parent b129e18396
commit 29c5ea0a50
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 217 additions and 4 deletions

View file

@ -1,7 +1,7 @@
#![allow(missing_docs)]
use gpui::{AnyView, DefiniteLength};
use crate::{prelude::*, ElevationIndex, IconPosition, KeyBinding, Spacing};
use crate::{prelude::*, ElevationIndex, IconPosition, KeyBinding, Spacing, TintColor};
use crate::{
ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, IconName, IconSize, Label, LineHeightStyle,
};
@ -437,3 +437,103 @@ impl RenderOnce for Button {
)
}
}
impl ComponentPreview for Button {
fn description() -> impl Into<Option<&'static str>> {
"A button allows users to take actions, and make choices, with a single tap."
}
fn examples() -> Vec<ComponentExampleGroup<Self>> {
vec![
example_group(
"Styles",
vec![
single_example("Default", Button::new("default", "Default")),
single_example(
"Filled",
Button::new("filled", "Filled").style(ButtonStyle::Filled),
),
single_example(
"Subtle",
Button::new("outline", "Subtle").style(ButtonStyle::Subtle),
),
single_example(
"Transparent",
Button::new("transparent", "Transparent").style(ButtonStyle::Transparent),
),
],
),
example_group(
"Tinted",
vec![
single_example(
"Accent",
Button::new("tinted_accent", "Accent")
.style(ButtonStyle::Tinted(TintColor::Accent)),
),
single_example(
"Negative",
Button::new("tinted_negative", "Negative")
.style(ButtonStyle::Tinted(TintColor::Negative)),
),
single_example(
"Warning",
Button::new("tinted_warning", "Warning")
.style(ButtonStyle::Tinted(TintColor::Warning)),
),
single_example(
"Positive",
Button::new("tinted_positive", "Positive")
.style(ButtonStyle::Tinted(TintColor::Positive)),
),
],
),
example_group(
"States",
vec![
single_example("Default", Button::new("default_state", "Default")),
single_example(
"Disabled",
Button::new("disabled", "Disabled").disabled(true),
),
single_example(
"Selected",
Button::new("selected", "Selected").selected(true),
),
],
),
example_group(
"With Icons",
vec![
single_example(
"Icon Start",
Button::new("icon_start", "Icon Start")
.icon(IconName::Check)
.icon_position(IconPosition::Start),
),
single_example(
"Icon End",
Button::new("icon_end", "Icon End")
.icon(IconName::Check)
.icon_position(IconPosition::End),
),
single_example(
"Icon Color",
Button::new("icon_color", "Icon Color")
.icon(IconName::Check)
.icon_color(Color::Accent),
),
single_example(
"Tinted Icons",
Button::new("icon_color", "Delete")
.style(ButtonStyle::Tinted(TintColor::Negative))
.color(Color::Error)
.icon_color(Color::Error)
.icon(IconName::Trash)
.icon_position(IconPosition::Start),
),
],
),
]
}
}

View file

@ -1,5 +1,4 @@
#![allow(missing_docs)]
use crate::prelude::*;
use crate::{prelude::*, Avatar};
use gpui::{AnyElement, StyleRefinement};
use smallvec::SmallVec;
@ -15,10 +14,12 @@ pub struct Facepile {
}
impl Facepile {
/// Creates a new empty facepile.
pub fn empty() -> Self {
Self::new(SmallVec::new())
}
/// Creates a new facepile with the given faces.
pub fn new(faces: SmallVec<[AnyElement; 2]>) -> Self {
Self { base: div(), faces }
}
@ -58,3 +59,61 @@ impl RenderOnce for Facepile {
)
}
}
impl ComponentPreview for Facepile {
fn description() -> impl Into<Option<&'static str>> {
"A facepile is a collection of faces stacked horizontally\
always with the leftmost face on top and descending in z-index.\
\n\nFacepiles are used to display a group of people or things,\
such as a list of participants in a collaboration session."
}
fn examples() -> Vec<ComponentExampleGroup<Self>> {
let few_faces: [&'static str; 3] = [
"https://avatars.githubusercontent.com/u/1714999?s=60&v=4",
"https://avatars.githubusercontent.com/u/67129314?s=60&v=4",
"https://avatars.githubusercontent.com/u/482957?s=60&v=4",
];
let many_faces: [&'static str; 6] = [
"https://avatars.githubusercontent.com/u/326587?s=60&v=4",
"https://avatars.githubusercontent.com/u/2280405?s=60&v=4",
"https://avatars.githubusercontent.com/u/1789?s=60&v=4",
"https://avatars.githubusercontent.com/u/67129314?s=60&v=4",
"https://avatars.githubusercontent.com/u/482957?s=60&v=4",
"https://avatars.githubusercontent.com/u/1714999?s=60&v=4",
];
vec![example_group(
"Examples",
vec![
single_example(
"Few Faces",
Facepile::new(
few_faces
.iter()
.map(|&url| Avatar::new(url).into_any_element())
.collect(),
),
),
single_example(
"Many Faces",
Facepile::new(
many_faces
.iter()
.map(|&url| Avatar::new(url).into_any_element())
.collect(),
),
),
single_example(
"Custom Size",
Facepile::new(
few_faces
.iter()
.map(|&url| Avatar::new(url).size(px(24.)).into_any_element())
.collect(),
),
),
],
)]
}
}

View file

@ -12,6 +12,7 @@ enum IndicatorKind {
#[derive(IntoElement)]
pub struct Indicator {
kind: IndicatorKind,
border_color: Option<Color>,
pub color: Color,
}
@ -19,6 +20,7 @@ impl Indicator {
pub fn dot() -> Self {
Self {
kind: IndicatorKind::Dot,
border_color: None,
color: Color::Default,
}
}
@ -26,6 +28,8 @@ impl Indicator {
pub fn bar() -> Self {
Self {
kind: IndicatorKind::Bar,
border_color: None,
color: Color::Default,
}
}
@ -33,6 +37,8 @@ impl Indicator {
pub fn icon(icon: impl Into<AnyIcon>) -> Self {
Self {
kind: IndicatorKind::Icon(icon.into()),
border_color: None,
color: Color::Default,
}
}
@ -41,11 +47,25 @@ impl Indicator {
self.color = color;
self
}
pub fn border_color(mut self, color: Color) -> Self {
self.border_color = Some(color);
self
}
}
impl RenderOnce for Indicator {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let container = div().flex_none();
let container = if let Some(border_color) = self.border_color {
if matches!(self.kind, IndicatorKind::Dot | IndicatorKind::Bar) {
container.border_1().border_color(border_color.color(cx))
} else {
container
}
} else {
container
};
match self.kind {
IndicatorKind::Icon(icon) => container
@ -63,3 +83,34 @@ impl RenderOnce for Indicator {
}
}
}
impl ComponentPreview for Indicator {
fn description() -> impl Into<Option<&'static str>> {
"An indicator visually represents a status or state."
}
fn examples() -> Vec<ComponentExampleGroup<Self>> {
vec![
example_group(
"Types",
vec![
single_example("Dot", Indicator::dot().color(Color::Info)),
single_example("Bar", Indicator::bar().color(Color::Player(2))),
single_example(
"Icon",
Indicator::icon(Icon::new(IconName::Check).color(Color::Success)),
),
],
),
example_group(
"Examples",
vec![
single_example("Info", Indicator::dot().color(Color::Info)),
single_example("Success", Indicator::dot().color(Color::Success)),
single_example("Warning", Indicator::dot().color(Color::Warning)),
single_example("Error", Indicator::dot().color(Color::Error)),
],
),
]
}
}

View file

@ -5,7 +5,7 @@ use theme::all_theme_colors;
use ui::{
prelude::*, utils::calculate_contrast_ratio, AudioStatus, Availability, Avatar,
AvatarAudioStatusIndicator, AvatarAvailabilityIndicator, ButtonLike, Checkbox, ElevationIndex,
Facepile, TintColor, Tooltip,
Facepile, Indicator, TintColor, Tooltip,
};
use crate::{Item, Workspace};
@ -510,6 +510,9 @@ impl ThemePreview {
.size_full()
.gap_2()
.child(Checkbox::render_component_previews(cx))
.child(Facepile::render_component_previews(cx))
.child(Button::render_component_previews(cx))
.child(Indicator::render_component_previews(cx))
.child(Icon::render_component_previews(cx))
.child(self.render_avatars(cx))
.child(self.render_buttons(layer, cx))