component: Add component and component_preview crates to power UI components (#24456)

This PR formalizes design components with the Component and
ComponentPreview traits.

You can open the preview UI with `workspace: open component preview`.

Component previews no longer need to return `Self` allowing for more
complex previews, and previews of components like `ui::Tooltip` that
supplement other components rather than are rendered by default.

`cargo-machete` incorrectly identifies `linkme` as an unused dep on
crates that have components deriving `IntoComponent`, so you may need to
add this to that crate's `Cargo.toml`:

```toml
# cargo-machete doesn't understand that linkme is used in the component macro
[package.metadata.cargo-machete]
ignored = ["linkme"]
```

Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
This commit is contained in:
Nate Butler 2025-02-09 13:25:03 -05:00 committed by GitHub
parent 56cfc60875
commit 8f1ff189cc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 1582 additions and 976 deletions

View file

@ -1,5 +1,7 @@
use crate::prelude::*;
use gpui::{
div, rems, App, IntoElement, ParentElement, Rems, RenderOnce, SharedString, Styled, Window,
div, rems, AnyElement, App, IntoElement, ParentElement, Rems, RenderOnce, SharedString, Styled,
Window,
};
use settings::Settings;
use theme::{ActiveTheme, ThemeSettings};
@ -188,7 +190,7 @@ impl HeadlineSize {
/// A headline element, used to emphasize some text and
/// create a visual hierarchy.
#[derive(IntoElement)]
#[derive(IntoElement, IntoComponent)]
pub struct Headline {
size: HeadlineSize,
text: SharedString,
@ -230,3 +232,44 @@ impl Headline {
self
}
}
impl ComponentPreview for Headline {
fn preview(_window: &mut Window, _cx: &App) -> AnyElement {
v_flex()
.gap_6()
.children(vec![example_group_with_title(
"Headline Sizes",
vec![
single_example(
"XLarge",
Headline::new("XLarge Headline")
.size(HeadlineSize::XLarge)
.into_any_element(),
),
single_example(
"Large",
Headline::new("Large Headline")
.size(HeadlineSize::Large)
.into_any_element(),
),
single_example(
"Medium (Default)",
Headline::new("Medium Headline").into_any_element(),
),
single_example(
"Small",
Headline::new("Small Headline")
.size(HeadlineSize::Small)
.into_any_element(),
),
single_example(
"XSmall",
Headline::new("XSmall Headline")
.size(HeadlineSize::XSmall)
.into_any_element(),
),
],
)])
.into_any_element()
}
}