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:
Marshall Bowers 2023-10-12 17:40:20 -04:00 committed by GitHub
parent bac43ae38e
commit 45f3a98359
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
91 changed files with 0 additions and 10580 deletions

File diff suppressed because it is too large Load diff

View file

@ -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"] }

View file

@ -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;
}
```

View file

@ -1,3 +0,0 @@
pub mod components;
pub mod elements;
pub mod kitchen_sink;

View file

@ -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;

View file

@ -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())
}
}

View file

@ -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),
},
]),
],
))
}
}

View file

@ -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)),
)
}
}

View file

@ -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(()),
))
}
}

View file

@ -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()))
}
}

View file

@ -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")),
]))
}
}

View file

@ -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))),
)
}
}

View file

@ -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)),
))
}
}

View file

@ -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())
}
}

View file

@ -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),
]))
}
}

View file

@ -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())),
]),
)
}
}

View file

@ -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(()),
))
}
}

View file

@ -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(()),
))
}
}

View file

@ -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())
}
}

View file

@ -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())
}
}

View file

@ -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)
}))),
)
}
}

View file

@ -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),
]))
}
}

View file

@ -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())
}
}

View file

@ -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())
}
}

View file

@ -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))
}
}

View file

@ -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(()),
))
}
}

View file

@ -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))
}
}

View file

@ -1,5 +0,0 @@
pub mod avatar;
pub mod button;
pub mod icon;
pub mod input;
pub mod label;

View file

@ -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),
)
}
}

View file

@ -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.")),
)
}
}

View file

@ -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)))
}
}

View file

@ -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")))
}
}

View file

@ -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]))
}
}

View file

@ -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())
}
}

View file

@ -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())
}
}

View file

@ -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))
}
}

View file

@ -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();
// }