Add ui::ComponentPreview (#20319)

The `ComponentPreview` trait enables rendering storybook-like previews
of components inside of Zed.


![CleanShot 2024-11-06 at 16 32
25@2x](https://github.com/user-attachments/assets/6894663f-1bbc-4a40-b420-33882e9e239a)


This initial version will work for any component that doesn't return a
view.

Example impl:

```rust
impl ComponentPreview for Checkbox {
    fn description() -> impl Into<Option<&'static str>> {
        "A checkbox lets people choose between opposing..."
    }

    fn examples() -> Vec<ComponentExampleGroup<Self>> {
        vec![
            example_group(
                "Default",
                vec![
                    single_example(
                        "Unselected",
                        Checkbox::new("checkbox_unselected", Selection::Unselected),
                    ),
                    // ... more examples
                ],
            ),
            // ... more examples
        ]
    }
}
```

Example usage:

```rust
fn render_components_page(&self, cx: &ViewContext<Self>) -> impl IntoElement {
        v_flex()
            .gap_2()
            .child(Checkbox::render_component_previews(cx))
            .child(Icon::render_component_previews(cx))
    }
}
```

Release Notes:

- N/A
This commit is contained in:
Nate Butler 2024-11-06 16:54:18 -05:00 committed by GitHub
parent a409123342
commit f6fbf662b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 249 additions and 26 deletions

View file

@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize};
use strum::{EnumIter, EnumString, IntoStaticStr};
use ui_macros::DerivePathStr;
use crate::{prelude::*, Indicator};
use crate::{
prelude::*,
traits::component_preview::{example_group, ComponentExample, ComponentPreview},
Indicator,
};
#[derive(IntoElement)]
pub enum AnyIcon {
@ -494,3 +498,26 @@ impl RenderOnce for IconWithIndicator {
})
}
}
impl ComponentPreview for Icon {
fn examples() -> Vec<ComponentExampleGroup<Icon>> {
let arrow_icons = vec![
IconName::ArrowDown,
IconName::ArrowLeft,
IconName::ArrowRight,
IconName::ArrowUp,
IconName::ArrowCircle,
];
vec![example_group(
"Arrow Icons",
arrow_icons
.into_iter()
.map(|icon| {
let name = format!("{:?}", icon).to_string();
ComponentExample::new(name, Icon::new(icon))
})
.collect(),
)]
}
}