Remove old ui
and storybook
crates (#3125)
This PR deletes the old `ui` and `storybook` crates in favor of their newer variants that we'll be landing to `main` in the near future. ### Motivation These crates are based off the old version of GPUI 2 (the `gpui2` crate). At this point we have since transitioned to the new version of GPUI 2 (the `gpui3` crate, currently still on the `gpui2` branch). Having both copies around is confusing, so the old ones are going the way of the dinosaurs. Release Notes: - N/A
This commit is contained in:
parent
bac43ae38e
commit
45f3a98359
91 changed files with 0 additions and 10580 deletions
2919
crates/storybook/Cargo.lock
generated
2919
crates/storybook/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,30 +0,0 @@
|
|||
[package]
|
||||
name = "storybook"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[[bin]]
|
||||
name = "storybook"
|
||||
path = "src/storybook.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
clap = { version = "4.4", features = ["derive", "string"] }
|
||||
chrono = "0.4"
|
||||
fs = { path = "../fs" }
|
||||
futures.workspace = true
|
||||
gpui2 = { path = "../gpui2" }
|
||||
itertools = "0.11.0"
|
||||
log.workspace = true
|
||||
rust-embed.workspace = true
|
||||
serde.workspace = true
|
||||
settings = { path = "../settings" }
|
||||
simplelog = "0.9"
|
||||
strum = { version = "0.25.0", features = ["derive"] }
|
||||
theme = { path = "../theme" }
|
||||
ui = { path = "../ui" }
|
||||
util = { path = "../util" }
|
||||
|
||||
[dev-dependencies]
|
||||
gpui2 = { path = "../gpui2", features = ["test-support"] }
|
|
@ -1,72 +0,0 @@
|
|||
Much of element styling is now handled by an external engine.
|
||||
|
||||
|
||||
How do I make an element hover.
|
||||
|
||||
There's a hover style.
|
||||
|
||||
Hoverable needs to wrap another element. That element can be styled.
|
||||
|
||||
```rs
|
||||
struct Hoverable<E: Element> {
|
||||
|
||||
}
|
||||
|
||||
impl<V> Element<V> for Hoverable {
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
```rs
|
||||
#[derive(Styled, Interactive)]
|
||||
pub struct Div {
|
||||
declared_style: StyleRefinement,
|
||||
interactions: Interactions
|
||||
}
|
||||
|
||||
pub trait Styled {
|
||||
fn declared_style(&mut self) -> &mut StyleRefinement;
|
||||
fn compute_style(&mut self) -> Style {
|
||||
Style::default().refine(self.declared_style())
|
||||
}
|
||||
|
||||
// All the tailwind classes, modifying self.declared_style()
|
||||
}
|
||||
|
||||
impl Style {
|
||||
pub fn paint_background<V>(layout: Layout, cx: &mut PaintContext<V>);
|
||||
pub fn paint_foreground<V>(layout: Layout, cx: &mut PaintContext<V>);
|
||||
}
|
||||
|
||||
pub trait Interactive<V> {
|
||||
fn interactions(&mut self) -> &mut Interactions<V>;
|
||||
|
||||
fn on_click(self, )
|
||||
}
|
||||
|
||||
struct Interactions<V> {
|
||||
click: SmallVec<[<Rc<dyn Fn(&mut V, &dyn Any, )>; 1]>,
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
```rs
|
||||
|
||||
|
||||
trait Stylable {
|
||||
type Style;
|
||||
|
||||
fn with_style(self, style: Self::Style) -> Self;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
|
@ -1,3 +0,0 @@
|
|||
pub mod components;
|
||||
pub mod elements;
|
||||
pub mod kitchen_sink;
|
|
@ -1,22 +0,0 @@
|
|||
pub mod assistant_panel;
|
||||
pub mod breadcrumb;
|
||||
pub mod buffer;
|
||||
pub mod chat_panel;
|
||||
pub mod collab_panel;
|
||||
pub mod context_menu;
|
||||
pub mod facepile;
|
||||
pub mod keybinding;
|
||||
pub mod language_selector;
|
||||
pub mod multi_buffer;
|
||||
pub mod palette;
|
||||
pub mod panel;
|
||||
pub mod project_panel;
|
||||
pub mod recent_projects;
|
||||
pub mod status_bar;
|
||||
pub mod tab;
|
||||
pub mod tab_bar;
|
||||
pub mod terminal;
|
||||
pub mod theme_selector;
|
||||
pub mod title_bar;
|
||||
pub mod toolbar;
|
||||
pub mod traffic_lights;
|
|
@ -1,16 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::AssistantPanel;
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct AssistantPanelStory {}
|
||||
|
||||
impl AssistantPanelStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, AssistantPanel<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(AssistantPanel::new())
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
use ui::prelude::*;
|
||||
use ui::{Breadcrumb, HighlightedText, Symbol};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct BreadcrumbStory {}
|
||||
|
||||
impl BreadcrumbStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let theme = theme(cx);
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Breadcrumb>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Breadcrumb::new(
|
||||
PathBuf::from_str("crates/ui/src/components/toolbar.rs").unwrap(),
|
||||
vec![
|
||||
Symbol(vec![
|
||||
HighlightedText {
|
||||
text: "impl ".to_string(),
|
||||
color: HighlightColor::Keyword.hsla(&theme),
|
||||
},
|
||||
HighlightedText {
|
||||
text: "BreadcrumbStory".to_string(),
|
||||
color: HighlightColor::Function.hsla(&theme),
|
||||
},
|
||||
]),
|
||||
Symbol(vec![
|
||||
HighlightedText {
|
||||
text: "fn ".to_string(),
|
||||
color: HighlightColor::Keyword.hsla(&theme),
|
||||
},
|
||||
HighlightedText {
|
||||
text: "render".to_string(),
|
||||
color: HighlightColor::Function.hsla(&theme),
|
||||
},
|
||||
]),
|
||||
],
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
use gpui2::geometry::rems;
|
||||
use ui::prelude::*;
|
||||
use ui::{
|
||||
empty_buffer_example, hello_world_rust_buffer_example,
|
||||
hello_world_rust_buffer_with_status_example, Buffer,
|
||||
};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct BufferStory {}
|
||||
|
||||
impl BufferStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let theme = theme(cx);
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Buffer>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(div().w(rems(64.)).h_96().child(empty_buffer_example()))
|
||||
.child(Story::label(cx, "Hello World (Rust)"))
|
||||
.child(
|
||||
div()
|
||||
.w(rems(64.))
|
||||
.h_96()
|
||||
.child(hello_world_rust_buffer_example(&theme)),
|
||||
)
|
||||
.child(Story::label(cx, "Hello World (Rust) with Status"))
|
||||
.child(
|
||||
div()
|
||||
.w(rems(64.))
|
||||
.h_96()
|
||||
.child(hello_world_rust_buffer_with_status_example(&theme)),
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
use chrono::DateTime;
|
||||
use ui::prelude::*;
|
||||
use ui::{ChatMessage, ChatPanel, Panel};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct ChatPanelStory {}
|
||||
|
||||
impl ChatPanelStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, ChatPanel<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Panel::new(
|
||||
ScrollState::default(),
|
||||
|_, _| vec![ChatPanel::new(ScrollState::default()).into_any()],
|
||||
Box::new(()),
|
||||
))
|
||||
.child(Story::label(cx, "With Mesages"))
|
||||
.child(Panel::new(
|
||||
ScrollState::default(),
|
||||
|_, _| {
|
||||
vec![ChatPanel::new(ScrollState::default())
|
||||
.with_messages(vec![
|
||||
ChatMessage::new(
|
||||
"osiewicz".to_string(),
|
||||
"is this thing on?".to_string(),
|
||||
DateTime::parse_from_rfc3339("2023-09-27T15:40:52.707Z")
|
||||
.unwrap()
|
||||
.naive_local(),
|
||||
),
|
||||
ChatMessage::new(
|
||||
"maxdeviant".to_string(),
|
||||
"Reading you loud and clear!".to_string(),
|
||||
DateTime::parse_from_rfc3339("2023-09-28T15:40:52.707Z")
|
||||
.unwrap()
|
||||
.naive_local(),
|
||||
),
|
||||
])
|
||||
.into_any()]
|
||||
},
|
||||
Box::new(()),
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::CollabPanel;
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct CollabPanelStory {}
|
||||
|
||||
impl CollabPanelStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, CollabPanel<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(CollabPanel::new(ScrollState::default()))
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::{ContextMenu, ContextMenuItem, Label};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct ContextMenuStory {}
|
||||
|
||||
impl ContextMenuStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
//.fill(theme.middle.base.default.background)
|
||||
.child(Story::title_for::<_, ContextMenu>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(ContextMenu::new([
|
||||
ContextMenuItem::header("Section header"),
|
||||
ContextMenuItem::Separator,
|
||||
ContextMenuItem::entry(Label::new("Some entry")),
|
||||
]))
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::{static_players, Facepile};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct FacepileStory {}
|
||||
|
||||
impl FacepileStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let players = static_players();
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Facepile>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.gap_3()
|
||||
.child(Facepile::new(players.clone().into_iter().take(1)))
|
||||
.child(Facepile::new(players.clone().into_iter().take(2)))
|
||||
.child(Facepile::new(players.clone().into_iter().take(3))),
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
use itertools::Itertools;
|
||||
use strum::IntoEnumIterator;
|
||||
use ui::prelude::*;
|
||||
use ui::{Keybinding, ModifierKey, ModifierKeys};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct KeybindingStory {}
|
||||
|
||||
impl KeybindingStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let all_modifier_permutations = ModifierKey::iter().permutations(2);
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Keybinding>(cx))
|
||||
.child(Story::label(cx, "Single Key"))
|
||||
.child(Keybinding::new("Z".to_string(), ModifierKeys::new()))
|
||||
.child(Story::label(cx, "Single Key with Modifier"))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.gap_3()
|
||||
.children(ModifierKey::iter().map(|modifier| {
|
||||
Keybinding::new("C".to_string(), ModifierKeys::new().add(modifier))
|
||||
})),
|
||||
)
|
||||
.child(Story::label(cx, "Single Key with Modifier (Permuted)"))
|
||||
.child(
|
||||
div().flex().flex_col().children(
|
||||
all_modifier_permutations
|
||||
.chunks(4)
|
||||
.into_iter()
|
||||
.map(|chunk| {
|
||||
div()
|
||||
.flex()
|
||||
.gap_4()
|
||||
.py_3()
|
||||
.children(chunk.map(|permutation| {
|
||||
let mut modifiers = ModifierKeys::new();
|
||||
|
||||
for modifier in permutation {
|
||||
modifiers = modifiers.add(modifier);
|
||||
}
|
||||
|
||||
Keybinding::new("X".to_string(), modifiers)
|
||||
}))
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(Story::label(cx, "Single Key with All Modifiers"))
|
||||
.child(Keybinding::new("Z".to_string(), ModifierKeys::all()))
|
||||
.child(Story::label(cx, "Chord"))
|
||||
.child(Keybinding::new_chord(
|
||||
("A".to_string(), ModifierKeys::new()),
|
||||
("Z".to_string(), ModifierKeys::new()),
|
||||
))
|
||||
.child(Story::label(cx, "Chord with Modifier"))
|
||||
.child(Keybinding::new_chord(
|
||||
("A".to_string(), ModifierKeys::new().control(true)),
|
||||
("Z".to_string(), ModifierKeys::new().shift(true)),
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::LanguageSelector;
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct LanguageSelectorStory {}
|
||||
|
||||
impl LanguageSelectorStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, LanguageSelector>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(LanguageSelector::new())
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::{hello_world_rust_buffer_example, MultiBuffer};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct MultiBufferStory {}
|
||||
|
||||
impl MultiBufferStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let theme = theme(cx);
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, MultiBuffer<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(MultiBuffer::new(vec![
|
||||
hello_world_rust_buffer_example(&theme),
|
||||
hello_world_rust_buffer_example(&theme),
|
||||
hello_world_rust_buffer_example(&theme),
|
||||
hello_world_rust_buffer_example(&theme),
|
||||
hello_world_rust_buffer_example(&theme),
|
||||
]))
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::{Keybinding, ModifierKeys, Palette, PaletteItem};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct PaletteStory {}
|
||||
|
||||
impl PaletteStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Palette<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Palette::new(ScrollState::default()))
|
||||
.child(Story::label(cx, "With Items"))
|
||||
.child(
|
||||
Palette::new(ScrollState::default())
|
||||
.placeholder("Execute a command...")
|
||||
.items(vec![
|
||||
PaletteItem::new("theme selector: toggle").keybinding(
|
||||
Keybinding::new_chord(
|
||||
("k".to_string(), ModifierKeys::new().command(true)),
|
||||
("t".to_string(), ModifierKeys::new().command(true)),
|
||||
),
|
||||
),
|
||||
PaletteItem::new("assistant: inline assist").keybinding(Keybinding::new(
|
||||
"enter".to_string(),
|
||||
ModifierKeys::new().command(true),
|
||||
)),
|
||||
PaletteItem::new("assistant: quote selection").keybinding(Keybinding::new(
|
||||
">".to_string(),
|
||||
ModifierKeys::new().command(true),
|
||||
)),
|
||||
PaletteItem::new("assistant: toggle focus").keybinding(Keybinding::new(
|
||||
"?".to_string(),
|
||||
ModifierKeys::new().command(true),
|
||||
)),
|
||||
PaletteItem::new("auto update: check"),
|
||||
PaletteItem::new("auto update: view release notes"),
|
||||
PaletteItem::new("branches: open recent").keybinding(Keybinding::new(
|
||||
"b".to_string(),
|
||||
ModifierKeys::new().command(true).alt(true),
|
||||
)),
|
||||
PaletteItem::new("chat panel: toggle focus"),
|
||||
PaletteItem::new("cli: install"),
|
||||
PaletteItem::new("client: sign in"),
|
||||
PaletteItem::new("client: sign out"),
|
||||
PaletteItem::new("editor: cancel")
|
||||
.keybinding(Keybinding::new("escape".to_string(), ModifierKeys::new())),
|
||||
]),
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::{Label, Panel};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct PanelStory {}
|
||||
|
||||
impl PanelStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Panel<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Panel::new(
|
||||
ScrollState::default(),
|
||||
|_, _| {
|
||||
vec![div()
|
||||
.overflow_y_scroll(ScrollState::default())
|
||||
.children((0..100).map(|ix| Label::new(format!("Item {}", ix + 1))))
|
||||
.into_any()]
|
||||
},
|
||||
Box::new(()),
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::{Panel, ProjectPanel};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct ProjectPanelStory {}
|
||||
|
||||
impl ProjectPanelStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, ProjectPanel<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Panel::new(
|
||||
ScrollState::default(),
|
||||
|_, _| vec![ProjectPanel::new(ScrollState::default()).into_any()],
|
||||
Box::new(()),
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::RecentProjects;
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct RecentProjectsStory {}
|
||||
|
||||
impl RecentProjectsStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, RecentProjects>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(RecentProjects::new())
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::StatusBar;
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct StatusBarStory {}
|
||||
|
||||
impl StatusBarStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, StatusBar<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(StatusBar::new())
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
use strum::IntoEnumIterator;
|
||||
use ui::prelude::*;
|
||||
use ui::{h_stack, v_stack, Tab};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct TabStory {}
|
||||
|
||||
impl TabStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let git_statuses = GitStatus::iter();
|
||||
let fs_statuses = FileSystemStatus::iter();
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Tab>(cx))
|
||||
.child(
|
||||
h_stack().child(
|
||||
v_stack()
|
||||
.gap_2()
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Tab::new()),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_stack().child(
|
||||
v_stack().gap_2().child(Story::label(cx, "Current")).child(
|
||||
h_stack()
|
||||
.gap_4()
|
||||
.child(Tab::new().title("Current".to_string()).current(true))
|
||||
.child(Tab::new().title("Not Current".to_string()).current(false)),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_stack().child(
|
||||
v_stack()
|
||||
.gap_2()
|
||||
.child(Story::label(cx, "Titled"))
|
||||
.child(Tab::new().title("label".to_string())),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_stack().child(
|
||||
v_stack()
|
||||
.gap_2()
|
||||
.child(Story::label(cx, "With Icon"))
|
||||
.child(
|
||||
Tab::new()
|
||||
.title("label".to_string())
|
||||
.icon(Some(ui::Icon::Envelope)),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_stack().child(
|
||||
v_stack()
|
||||
.gap_2()
|
||||
.child(Story::label(cx, "Close Side"))
|
||||
.child(
|
||||
h_stack()
|
||||
.gap_4()
|
||||
.child(
|
||||
Tab::new()
|
||||
.title("Left".to_string())
|
||||
.close_side(IconSide::Left),
|
||||
)
|
||||
.child(Tab::new().title("Right".to_string())),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
v_stack()
|
||||
.gap_2()
|
||||
.child(Story::label(cx, "Git Status"))
|
||||
.child(h_stack().gap_4().children(git_statuses.map(|git_status| {
|
||||
Tab::new()
|
||||
.title(git_status.to_string())
|
||||
.git_status(git_status)
|
||||
}))),
|
||||
)
|
||||
.child(
|
||||
v_stack()
|
||||
.gap_2()
|
||||
.child(Story::label(cx, "File System Status"))
|
||||
.child(h_stack().gap_4().children(fs_statuses.map(|fs_status| {
|
||||
Tab::new().title(fs_status.to_string()).fs_status(fs_status)
|
||||
}))),
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::{Tab, TabBar};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct TabBarStory {}
|
||||
|
||||
impl TabBarStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, TabBar<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(TabBar::new(vec![
|
||||
Tab::new()
|
||||
.title("Cargo.toml".to_string())
|
||||
.current(false)
|
||||
.git_status(GitStatus::Modified),
|
||||
Tab::new()
|
||||
.title("Channels Panel".to_string())
|
||||
.current(false),
|
||||
Tab::new()
|
||||
.title("channels_panel.rs".to_string())
|
||||
.current(true)
|
||||
.git_status(GitStatus::Modified),
|
||||
Tab::new()
|
||||
.title("workspace.rs".to_string())
|
||||
.current(false)
|
||||
.git_status(GitStatus::Modified),
|
||||
Tab::new()
|
||||
.title("icon_button.rs".to_string())
|
||||
.current(false),
|
||||
Tab::new()
|
||||
.title("storybook.rs".to_string())
|
||||
.current(false)
|
||||
.git_status(GitStatus::Created),
|
||||
Tab::new().title("theme.rs".to_string()).current(false),
|
||||
Tab::new()
|
||||
.title("theme_registry.rs".to_string())
|
||||
.current(false),
|
||||
Tab::new()
|
||||
.title("styleable_helpers.rs".to_string())
|
||||
.current(false),
|
||||
]))
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::Terminal;
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct TerminalStory {}
|
||||
|
||||
impl TerminalStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Terminal>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Terminal::new())
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::ThemeSelector;
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct ThemeSelectorStory {}
|
||||
|
||||
impl ThemeSelectorStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, ThemeSelector>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(ThemeSelector::new())
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::TitleBar;
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct TitleBarStory {}
|
||||
|
||||
impl TitleBarStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, TitleBar<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(TitleBar::new(cx))
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ui::prelude::*;
|
||||
use ui::{theme, Breadcrumb, HighlightColor, HighlightedText, Icon, IconButton, Symbol, Toolbar};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct ToolbarStory {}
|
||||
|
||||
impl ToolbarStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let theme = theme(cx);
|
||||
|
||||
struct LeftItemsPayload {
|
||||
pub theme: Arc<Theme>,
|
||||
}
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Toolbar<V>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Toolbar::new(
|
||||
|_, payload| {
|
||||
let payload = payload.downcast_ref::<LeftItemsPayload>().unwrap();
|
||||
|
||||
let theme = payload.theme.clone();
|
||||
|
||||
vec![Breadcrumb::new(
|
||||
PathBuf::from_str("crates/ui/src/components/toolbar.rs").unwrap(),
|
||||
vec![
|
||||
Symbol(vec![
|
||||
HighlightedText {
|
||||
text: "impl ".to_string(),
|
||||
color: HighlightColor::Keyword.hsla(&theme),
|
||||
},
|
||||
HighlightedText {
|
||||
text: "ToolbarStory".to_string(),
|
||||
color: HighlightColor::Function.hsla(&theme),
|
||||
},
|
||||
]),
|
||||
Symbol(vec![
|
||||
HighlightedText {
|
||||
text: "fn ".to_string(),
|
||||
color: HighlightColor::Keyword.hsla(&theme),
|
||||
},
|
||||
HighlightedText {
|
||||
text: "render".to_string(),
|
||||
color: HighlightColor::Function.hsla(&theme),
|
||||
},
|
||||
]),
|
||||
],
|
||||
)
|
||||
.into_any()]
|
||||
},
|
||||
Box::new(LeftItemsPayload {
|
||||
theme: theme.clone(),
|
||||
}),
|
||||
|_, _| {
|
||||
vec![
|
||||
IconButton::new(Icon::InlayHint).into_any(),
|
||||
IconButton::new(Icon::MagnifyingGlass).into_any(),
|
||||
IconButton::new(Icon::MagicWand).into_any(),
|
||||
]
|
||||
},
|
||||
Box::new(()),
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::TrafficLights;
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct TrafficLightsStory {}
|
||||
|
||||
impl TrafficLightsStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, TrafficLights>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(TrafficLights::new())
|
||||
.child(Story::label(cx, "Unfocused"))
|
||||
.child(TrafficLights::new().window_has_focus(false))
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
pub mod avatar;
|
||||
pub mod button;
|
||||
pub mod icon;
|
||||
pub mod input;
|
||||
pub mod label;
|
|
@ -1,23 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::Avatar;
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct AvatarStory {}
|
||||
|
||||
impl AvatarStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Avatar>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Avatar::new(
|
||||
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
||||
))
|
||||
.child(Story::label(cx, "Rounded rectangle"))
|
||||
.child(
|
||||
Avatar::new("https://avatars.githubusercontent.com/u/1714999?v=4")
|
||||
.shape(Shape::RoundedRectangle),
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,192 +0,0 @@
|
|||
use gpui2::elements::div;
|
||||
use gpui2::geometry::rems;
|
||||
use gpui2::{Element, IntoElement, ViewContext};
|
||||
use strum::IntoEnumIterator;
|
||||
use ui::prelude::*;
|
||||
use ui::{h_stack, v_stack, Button, Icon, IconPosition, Label};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct ButtonStory {}
|
||||
|
||||
impl ButtonStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let states = InteractionState::iter();
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Button<V>>(cx))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.gap_8()
|
||||
.child(
|
||||
div()
|
||||
.child(Story::label(cx, "Ghost (Default)"))
|
||||
.child(h_stack().gap_2().children(states.clone().map(|state| {
|
||||
v_stack()
|
||||
.gap_1()
|
||||
.child(
|
||||
Label::new(state.to_string())
|
||||
.color(ui::LabelColor::Muted)
|
||||
.size(ui::LabelSize::Small),
|
||||
)
|
||||
.child(
|
||||
Button::new("Label")
|
||||
.variant(ButtonVariant::Ghost)
|
||||
.state(state),
|
||||
)
|
||||
})))
|
||||
.child(Story::label(cx, "Ghost – Left Icon"))
|
||||
.child(h_stack().gap_2().children(states.clone().map(|state| {
|
||||
v_stack()
|
||||
.gap_1()
|
||||
.child(
|
||||
Label::new(state.to_string())
|
||||
.color(ui::LabelColor::Muted)
|
||||
.size(ui::LabelSize::Small),
|
||||
)
|
||||
.child(
|
||||
Button::new("Label")
|
||||
.variant(ButtonVariant::Ghost)
|
||||
.icon(Icon::Plus)
|
||||
.icon_position(IconPosition::Left)
|
||||
.state(state),
|
||||
)
|
||||
})))
|
||||
.child(Story::label(cx, "Ghost – Right Icon"))
|
||||
.child(h_stack().gap_2().children(states.clone().map(|state| {
|
||||
v_stack()
|
||||
.gap_1()
|
||||
.child(
|
||||
Label::new(state.to_string())
|
||||
.color(ui::LabelColor::Muted)
|
||||
.size(ui::LabelSize::Small),
|
||||
)
|
||||
.child(
|
||||
Button::new("Label")
|
||||
.variant(ButtonVariant::Ghost)
|
||||
.icon(Icon::Plus)
|
||||
.icon_position(IconPosition::Right)
|
||||
.state(state),
|
||||
)
|
||||
}))),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.child(Story::label(cx, "Filled"))
|
||||
.child(h_stack().gap_2().children(states.clone().map(|state| {
|
||||
v_stack()
|
||||
.gap_1()
|
||||
.child(
|
||||
Label::new(state.to_string())
|
||||
.color(ui::LabelColor::Muted)
|
||||
.size(ui::LabelSize::Small),
|
||||
)
|
||||
.child(
|
||||
Button::new("Label")
|
||||
.variant(ButtonVariant::Filled)
|
||||
.state(state),
|
||||
)
|
||||
})))
|
||||
.child(Story::label(cx, "Filled – Left Button"))
|
||||
.child(h_stack().gap_2().children(states.clone().map(|state| {
|
||||
v_stack()
|
||||
.gap_1()
|
||||
.child(
|
||||
Label::new(state.to_string())
|
||||
.color(ui::LabelColor::Muted)
|
||||
.size(ui::LabelSize::Small),
|
||||
)
|
||||
.child(
|
||||
Button::new("Label")
|
||||
.variant(ButtonVariant::Filled)
|
||||
.icon(Icon::Plus)
|
||||
.icon_position(IconPosition::Left)
|
||||
.state(state),
|
||||
)
|
||||
})))
|
||||
.child(Story::label(cx, "Filled – Right Button"))
|
||||
.child(h_stack().gap_2().children(states.clone().map(|state| {
|
||||
v_stack()
|
||||
.gap_1()
|
||||
.child(
|
||||
Label::new(state.to_string())
|
||||
.color(ui::LabelColor::Muted)
|
||||
.size(ui::LabelSize::Small),
|
||||
)
|
||||
.child(
|
||||
Button::new("Label")
|
||||
.variant(ButtonVariant::Filled)
|
||||
.icon(Icon::Plus)
|
||||
.icon_position(IconPosition::Right)
|
||||
.state(state),
|
||||
)
|
||||
}))),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.child(Story::label(cx, "Fixed With"))
|
||||
.child(h_stack().gap_2().children(states.clone().map(|state| {
|
||||
v_stack()
|
||||
.gap_1()
|
||||
.child(
|
||||
Label::new(state.to_string())
|
||||
.color(ui::LabelColor::Muted)
|
||||
.size(ui::LabelSize::Small),
|
||||
)
|
||||
.child(
|
||||
Button::new("Label")
|
||||
.variant(ButtonVariant::Filled)
|
||||
.state(state)
|
||||
.width(Some(rems(6.).into())),
|
||||
)
|
||||
})))
|
||||
.child(Story::label(cx, "Fixed With – Left Icon"))
|
||||
.child(h_stack().gap_2().children(states.clone().map(|state| {
|
||||
v_stack()
|
||||
.gap_1()
|
||||
.child(
|
||||
Label::new(state.to_string())
|
||||
.color(ui::LabelColor::Muted)
|
||||
.size(ui::LabelSize::Small),
|
||||
)
|
||||
.child(
|
||||
Button::new("Label")
|
||||
.variant(ButtonVariant::Filled)
|
||||
.state(state)
|
||||
.icon(Icon::Plus)
|
||||
.icon_position(IconPosition::Left)
|
||||
.width(Some(rems(6.).into())),
|
||||
)
|
||||
})))
|
||||
.child(Story::label(cx, "Fixed With – Right Icon"))
|
||||
.child(h_stack().gap_2().children(states.clone().map(|state| {
|
||||
v_stack()
|
||||
.gap_1()
|
||||
.child(
|
||||
Label::new(state.to_string())
|
||||
.color(ui::LabelColor::Muted)
|
||||
.size(ui::LabelSize::Small),
|
||||
)
|
||||
.child(
|
||||
Button::new("Label")
|
||||
.variant(ButtonVariant::Filled)
|
||||
.state(state)
|
||||
.icon(Icon::Plus)
|
||||
.icon_position(IconPosition::Right)
|
||||
.width(Some(rems(6.).into())),
|
||||
)
|
||||
}))),
|
||||
),
|
||||
)
|
||||
.child(Story::label(cx, "Button with `on_click`"))
|
||||
.child(
|
||||
Button::new("Label")
|
||||
.variant(ButtonVariant::Ghost)
|
||||
// NOTE: There currently appears to be a bug in GPUI2 where only the last event handler will fire.
|
||||
// So adding additional buttons with `on_click`s after this one will cause this `on_click` to not fire.
|
||||
.on_click(|_view, _cx| println!("Button clicked.")),
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
use strum::IntoEnumIterator;
|
||||
use ui::prelude::*;
|
||||
use ui::{Icon, IconElement};
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct IconStory {}
|
||||
|
||||
impl IconStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let icons = Icon::iter();
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, IconElement>(cx))
|
||||
.child(Story::label(cx, "All Icons"))
|
||||
.child(div().flex().gap_3().children(icons.map(IconElement::new)))
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::Input;
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct InputStory {}
|
||||
|
||||
impl InputStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Input>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(div().flex().child(Input::new("Search")))
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
use ui::prelude::*;
|
||||
use ui::Label;
|
||||
|
||||
use crate::story::Story;
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct LabelStory {}
|
||||
|
||||
impl LabelStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Label>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(Label::new("Hello, world!"))
|
||||
.child(Story::label(cx, "Highlighted"))
|
||||
.child(Label::new("Hello, world!").with_highlights(vec![0, 1, 2, 7, 8, 12]))
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
use strum::IntoEnumIterator;
|
||||
use ui::prelude::*;
|
||||
|
||||
use crate::story::Story;
|
||||
use crate::story_selector::{ComponentStory, ElementStory};
|
||||
|
||||
#[derive(Element, Default)]
|
||||
pub struct KitchenSinkStory {}
|
||||
|
||||
impl KitchenSinkStory {
|
||||
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||
let element_stories = ElementStory::iter().map(|selector| selector.story());
|
||||
let component_stories = ComponentStory::iter().map(|selector| selector.story());
|
||||
|
||||
Story::container(cx)
|
||||
.overflow_y_scroll(ScrollState::default())
|
||||
.child(Story::title(cx, "Kitchen Sink"))
|
||||
.child(Story::label(cx, "Elements"))
|
||||
.child(div().flex().flex_col().children_any(element_stories))
|
||||
.child(Story::label(cx, "Components"))
|
||||
.child(div().flex().flex_col().children_any(component_stories))
|
||||
// Add a bit of space at the bottom of the kitchen sink so elements
|
||||
// don't end up squished right up against the bottom of the screen.
|
||||
.child(div().p_4())
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
use gpui2::elements::div::Div;
|
||||
use ui::prelude::*;
|
||||
use ui::theme;
|
||||
|
||||
pub struct Story {}
|
||||
|
||||
impl Story {
|
||||
pub fn container<V: 'static>(cx: &mut ViewContext<V>) -> Div<V> {
|
||||
let theme = theme(cx);
|
||||
|
||||
div()
|
||||
.size_full()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.pt_2()
|
||||
.px_4()
|
||||
.font("Zed Mono Extended")
|
||||
.fill(theme.lowest.base.default.background)
|
||||
}
|
||||
|
||||
pub fn title<V: 'static>(cx: &mut ViewContext<V>, title: &str) -> impl Element<V> {
|
||||
let theme = theme(cx);
|
||||
|
||||
div()
|
||||
.text_xl()
|
||||
.text_color(theme.lowest.base.default.foreground)
|
||||
.child(title.to_owned())
|
||||
}
|
||||
|
||||
pub fn title_for<V: 'static, T>(cx: &mut ViewContext<V>) -> impl Element<V> {
|
||||
Self::title(cx, std::any::type_name::<T>())
|
||||
}
|
||||
|
||||
pub fn label<V: 'static>(cx: &mut ViewContext<V>, label: &str) -> impl Element<V> {
|
||||
let theme = theme(cx);
|
||||
|
||||
div()
|
||||
.mt_4()
|
||||
.mb_2()
|
||||
.text_xs()
|
||||
.text_color(theme.lowest.base.default.foreground)
|
||||
.child(label.to_owned())
|
||||
}
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
use std::str::FromStr;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use anyhow::{anyhow, Context};
|
||||
use clap::builder::PossibleValue;
|
||||
use clap::ValueEnum;
|
||||
use gpui2::{AnyElement, Element};
|
||||
use strum::{EnumIter, EnumString, IntoEnumIterator};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, strum::Display, EnumString, EnumIter)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum ElementStory {
|
||||
Avatar,
|
||||
Button,
|
||||
Icon,
|
||||
Input,
|
||||
Label,
|
||||
}
|
||||
|
||||
impl ElementStory {
|
||||
pub fn story<V: 'static>(&self) -> AnyElement<V> {
|
||||
use crate::stories::elements;
|
||||
|
||||
match self {
|
||||
Self::Avatar => elements::avatar::AvatarStory::default().into_any(),
|
||||
Self::Button => elements::button::ButtonStory::default().into_any(),
|
||||
Self::Icon => elements::icon::IconStory::default().into_any(),
|
||||
Self::Input => elements::input::InputStory::default().into_any(),
|
||||
Self::Label => elements::label::LabelStory::default().into_any(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, strum::Display, EnumString, EnumIter)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum ComponentStory {
|
||||
AssistantPanel,
|
||||
Breadcrumb,
|
||||
Buffer,
|
||||
ContextMenu,
|
||||
ChatPanel,
|
||||
CollabPanel,
|
||||
Facepile,
|
||||
Keybinding,
|
||||
LanguageSelector,
|
||||
MultiBuffer,
|
||||
Palette,
|
||||
Panel,
|
||||
ProjectPanel,
|
||||
RecentProjects,
|
||||
StatusBar,
|
||||
Tab,
|
||||
TabBar,
|
||||
Terminal,
|
||||
ThemeSelector,
|
||||
TitleBar,
|
||||
Toolbar,
|
||||
TrafficLights,
|
||||
}
|
||||
|
||||
impl ComponentStory {
|
||||
pub fn story<V: 'static>(&self) -> AnyElement<V> {
|
||||
use crate::stories::components;
|
||||
|
||||
match self {
|
||||
Self::AssistantPanel => {
|
||||
components::assistant_panel::AssistantPanelStory::default().into_any()
|
||||
}
|
||||
Self::Breadcrumb => components::breadcrumb::BreadcrumbStory::default().into_any(),
|
||||
Self::Buffer => components::buffer::BufferStory::default().into_any(),
|
||||
Self::ContextMenu => components::context_menu::ContextMenuStory::default().into_any(),
|
||||
Self::ChatPanel => components::chat_panel::ChatPanelStory::default().into_any(),
|
||||
Self::CollabPanel => components::collab_panel::CollabPanelStory::default().into_any(),
|
||||
Self::Facepile => components::facepile::FacepileStory::default().into_any(),
|
||||
Self::Keybinding => components::keybinding::KeybindingStory::default().into_any(),
|
||||
Self::LanguageSelector => {
|
||||
components::language_selector::LanguageSelectorStory::default().into_any()
|
||||
}
|
||||
Self::MultiBuffer => components::multi_buffer::MultiBufferStory::default().into_any(),
|
||||
Self::Palette => components::palette::PaletteStory::default().into_any(),
|
||||
Self::Panel => components::panel::PanelStory::default().into_any(),
|
||||
Self::ProjectPanel => {
|
||||
components::project_panel::ProjectPanelStory::default().into_any()
|
||||
}
|
||||
Self::RecentProjects => {
|
||||
components::recent_projects::RecentProjectsStory::default().into_any()
|
||||
}
|
||||
Self::StatusBar => components::status_bar::StatusBarStory::default().into_any(),
|
||||
Self::Tab => components::tab::TabStory::default().into_any(),
|
||||
Self::TabBar => components::tab_bar::TabBarStory::default().into_any(),
|
||||
Self::Terminal => components::terminal::TerminalStory::default().into_any(),
|
||||
Self::ThemeSelector => {
|
||||
components::theme_selector::ThemeSelectorStory::default().into_any()
|
||||
}
|
||||
Self::TitleBar => components::title_bar::TitleBarStory::default().into_any(),
|
||||
Self::Toolbar => components::toolbar::ToolbarStory::default().into_any(),
|
||||
Self::TrafficLights => {
|
||||
components::traffic_lights::TrafficLightsStory::default().into_any()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum StorySelector {
|
||||
Element(ElementStory),
|
||||
Component(ComponentStory),
|
||||
KitchenSink,
|
||||
}
|
||||
|
||||
impl FromStr for StorySelector {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(raw_story_name: &str) -> std::result::Result<Self, Self::Err> {
|
||||
let story = raw_story_name.to_ascii_lowercase();
|
||||
|
||||
if story == "kitchen_sink" {
|
||||
return Ok(Self::KitchenSink);
|
||||
}
|
||||
|
||||
if let Some((_, story)) = story.split_once("elements/") {
|
||||
let element_story = ElementStory::from_str(story)
|
||||
.with_context(|| format!("story not found for element '{story}'"))?;
|
||||
|
||||
return Ok(Self::Element(element_story));
|
||||
}
|
||||
|
||||
if let Some((_, story)) = story.split_once("components/") {
|
||||
let component_story = ComponentStory::from_str(story)
|
||||
.with_context(|| format!("story not found for component '{story}'"))?;
|
||||
|
||||
return Ok(Self::Component(component_story));
|
||||
}
|
||||
|
||||
Err(anyhow!("story not found for '{raw_story_name}'"))
|
||||
}
|
||||
}
|
||||
|
||||
impl StorySelector {
|
||||
pub fn story<V: 'static>(&self) -> AnyElement<V> {
|
||||
match self {
|
||||
Self::Element(element_story) => element_story.story(),
|
||||
Self::Component(component_story) => component_story.story(),
|
||||
Self::KitchenSink => {
|
||||
crate::stories::kitchen_sink::KitchenSinkStory::default().into_any()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The list of all stories available in the storybook.
|
||||
static ALL_STORY_SELECTORS: OnceLock<Vec<StorySelector>> = OnceLock::new();
|
||||
|
||||
impl ValueEnum for StorySelector {
|
||||
fn value_variants<'a>() -> &'a [Self] {
|
||||
let stories = ALL_STORY_SELECTORS.get_or_init(|| {
|
||||
let element_stories = ElementStory::iter().map(StorySelector::Element);
|
||||
let component_stories = ComponentStory::iter().map(StorySelector::Component);
|
||||
|
||||
element_stories
|
||||
.chain(component_stories)
|
||||
.chain(std::iter::once(StorySelector::KitchenSink))
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
stories
|
||||
}
|
||||
|
||||
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
|
||||
let value = match self {
|
||||
Self::Element(story) => format!("elements/{story}"),
|
||||
Self::Component(story) => format!("components/{story}"),
|
||||
Self::KitchenSink => "kitchen_sink".to_string(),
|
||||
};
|
||||
|
||||
Some(PossibleValue::new(value))
|
||||
}
|
||||
}
|
|
@ -1,198 +0,0 @@
|
|||
#![allow(dead_code, unused_variables)]
|
||||
|
||||
mod stories;
|
||||
mod story;
|
||||
mod story_selector;
|
||||
|
||||
use std::{process::Command, sync::Arc};
|
||||
|
||||
use ::theme as legacy_theme;
|
||||
use clap::Parser;
|
||||
use gpui2::{
|
||||
serde_json, vec2f, view, Element, IntoElement, ParentElement, RectF, ViewContext, WindowBounds,
|
||||
};
|
||||
use legacy_theme::{ThemeRegistry, ThemeSettings};
|
||||
use log::LevelFilter;
|
||||
use settings::{default_settings, SettingsStore};
|
||||
use simplelog::SimpleLogger;
|
||||
use ui::prelude::*;
|
||||
use ui::{ElementExt, Theme, WorkspaceElement};
|
||||
|
||||
use crate::story_selector::StorySelector;
|
||||
|
||||
gpui2::actions! {
|
||||
storybook,
|
||||
[ToggleInspector]
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
#[arg(value_enum)]
|
||||
story: Option<StorySelector>,
|
||||
|
||||
/// The name of the theme to use in the storybook.
|
||||
///
|
||||
/// If not provided, the default theme will be used.
|
||||
#[arg(long)]
|
||||
theme: Option<String>,
|
||||
}
|
||||
|
||||
async fn watch_zed_changes(fs: Arc<dyn fs::Fs>) -> Option<()> {
|
||||
if std::env::var("ZED_HOT_RELOAD").is_err() {
|
||||
return None;
|
||||
}
|
||||
use futures::StreamExt;
|
||||
let mut events = fs
|
||||
.watch(".".as_ref(), std::time::Duration::from_millis(100))
|
||||
.await;
|
||||
let mut current_child: Option<std::process::Child> = None;
|
||||
while let Some(events) = events.next().await {
|
||||
if !events.iter().any(|event| {
|
||||
event
|
||||
.path
|
||||
.to_str()
|
||||
.map(|path| path.contains("/crates/"))
|
||||
.unwrap_or_default()
|
||||
}) {
|
||||
continue;
|
||||
}
|
||||
let child = current_child.take().map(|mut child| child.kill());
|
||||
log::info!("Storybook changed, rebuilding...");
|
||||
current_child = Some(
|
||||
Command::new("cargo")
|
||||
.args(["run", "-p", "storybook"])
|
||||
.spawn()
|
||||
.ok()?,
|
||||
);
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
||||
|
||||
let args = Args::parse();
|
||||
|
||||
let fs = Arc::new(fs::RealFs);
|
||||
|
||||
gpui2::App::new(Assets).unwrap().run(move |cx| {
|
||||
let mut store = SettingsStore::default();
|
||||
store
|
||||
.set_default_settings(default_settings().as_ref(), cx)
|
||||
.unwrap();
|
||||
cx.set_global(store);
|
||||
legacy_theme::init(Assets, cx);
|
||||
// load_embedded_fonts(cx.platform().as_ref());
|
||||
|
||||
let theme_registry = cx.global::<Arc<ThemeRegistry>>();
|
||||
|
||||
let theme_override = args
|
||||
.theme
|
||||
.and_then(|theme| {
|
||||
theme_registry
|
||||
.list_names(true)
|
||||
.find(|known_theme| theme == *known_theme)
|
||||
})
|
||||
.and_then(|theme_name| theme_registry.get(&theme_name).ok());
|
||||
|
||||
cx.spawn(|_| async move {
|
||||
watch_zed_changes(fs).await;
|
||||
})
|
||||
.detach();
|
||||
cx.add_window(
|
||||
gpui2::WindowOptions {
|
||||
bounds: WindowBounds::Fixed(RectF::new(vec2f(0., 0.), vec2f(1700., 980.))),
|
||||
center: true,
|
||||
..Default::default()
|
||||
},
|
||||
|cx| match args.story {
|
||||
Some(selector) => view(move |cx| {
|
||||
render_story(
|
||||
&mut ViewContext::new(cx),
|
||||
theme_override.clone(),
|
||||
div().flex().flex_col().h_full().child_any(selector.story()),
|
||||
)
|
||||
}),
|
||||
None => view(move |cx| {
|
||||
render_story(
|
||||
&mut ViewContext::new(cx),
|
||||
theme_override.clone(),
|
||||
WorkspaceElement::default(),
|
||||
)
|
||||
}),
|
||||
},
|
||||
);
|
||||
cx.platform().activate(true);
|
||||
});
|
||||
}
|
||||
|
||||
fn render_story<V: 'static, S: IntoElement<V>>(
|
||||
cx: &mut ViewContext<V>,
|
||||
theme_override: Option<Arc<legacy_theme::Theme>>,
|
||||
story: S,
|
||||
) -> impl Element<V> {
|
||||
let theme = current_theme(cx, theme_override);
|
||||
|
||||
story.into_element().themed(theme)
|
||||
}
|
||||
|
||||
fn current_theme<V: 'static>(
|
||||
cx: &mut ViewContext<V>,
|
||||
theme_override: Option<Arc<legacy_theme::Theme>>,
|
||||
) -> Theme {
|
||||
let legacy_theme =
|
||||
theme_override.unwrap_or_else(|| settings::get::<ThemeSettings>(cx).theme.clone());
|
||||
|
||||
let new_theme: Theme = serde_json::from_value(legacy_theme.base_theme.clone()).unwrap();
|
||||
|
||||
add_base_theme_to_legacy_theme(&legacy_theme, new_theme)
|
||||
}
|
||||
|
||||
// Nathan: During the transition to gpui2, we will include the base theme on the legacy Theme struct.
|
||||
fn add_base_theme_to_legacy_theme(legacy_theme: &legacy_theme::Theme, new_theme: Theme) -> Theme {
|
||||
legacy_theme
|
||||
.deserialized_base_theme
|
||||
.lock()
|
||||
.get_or_insert_with(|| Box::new(new_theme))
|
||||
.downcast_ref::<Theme>()
|
||||
.unwrap()
|
||||
.clone()
|
||||
}
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use gpui2::AssetSource;
|
||||
use rust_embed::RustEmbed;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "../../assets"]
|
||||
#[include = "themes/**/*"]
|
||||
#[include = "fonts/**/*"]
|
||||
#[include = "icons/**/*"]
|
||||
#[exclude = "*.DS_Store"]
|
||||
pub struct Assets;
|
||||
|
||||
impl AssetSource for Assets {
|
||||
fn load(&self, path: &str) -> Result<std::borrow::Cow<[u8]>> {
|
||||
Self::get(path)
|
||||
.map(|f| f.data)
|
||||
.ok_or_else(|| anyhow!("could not find asset at path \"{}\"", path))
|
||||
}
|
||||
|
||||
fn list(&self, path: &str) -> Vec<std::borrow::Cow<'static, str>> {
|
||||
Self::iter().filter(|p| p.starts_with(path)).collect()
|
||||
}
|
||||
}
|
||||
|
||||
// fn load_embedded_fonts(platform: &dyn gpui2::Platform) {
|
||||
// let font_paths = Assets.list("fonts");
|
||||
// let mut embedded_fonts = Vec::new();
|
||||
// for font_path in &font_paths {
|
||||
// if font_path.ends_with(".ttf") {
|
||||
// let font_path = &*font_path;
|
||||
// let font_bytes = Assets.load(font_path).unwrap().to_vec();
|
||||
// embedded_fonts.push(Arc::from(font_bytes));
|
||||
// }
|
||||
// }
|
||||
// platform.fonts().add_fonts(&embedded_fonts).unwrap();
|
||||
// }
|
Loading…
Add table
Add a link
Reference in a new issue