Fix .active()
interaction state
Co-Authored-By: Nathan Sobo <1789+nathansobo@users.noreply.github.com>
This commit is contained in:
parent
a316e25034
commit
fd10b49742
11 changed files with 175 additions and 145 deletions
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
ViewContext,
|
ViewContext,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use gpui::{geometry::vector::Vector2F, platform::MouseButtonEvent, LayoutId};
|
use gpui::{color::Color, geometry::vector::Vector2F, platform::MouseButtonEvent, LayoutId};
|
||||||
use refineable::{CascadeSlot, Refineable, RefinementCascade};
|
use refineable::{CascadeSlot, Refineable, RefinementCascade};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{cell::Cell, rc::Rc};
|
use std::{cell::Cell, rc::Rc};
|
||||||
|
@ -73,11 +73,16 @@ impl<V: 'static, E: Element<V> + Styleable> Element<V> for Pressable<E> {
|
||||||
if bounds.contains_point(event.position) {
|
if bounds.contains_point(event.position) {
|
||||||
pressed.set(true);
|
pressed.set(true);
|
||||||
cx.repaint();
|
cx.repaint();
|
||||||
|
} else {
|
||||||
|
cx.bubble_event();
|
||||||
}
|
}
|
||||||
} else if pressed.get() {
|
} else {
|
||||||
|
if pressed.get() {
|
||||||
pressed.set(false);
|
pressed.set(false);
|
||||||
cx.repaint();
|
cx.repaint();
|
||||||
}
|
}
|
||||||
|
cx.bubble_event();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.child
|
self.child
|
||||||
|
|
|
@ -12,7 +12,6 @@ mod tool_divider;
|
||||||
pub use avatar::avatar;
|
pub use avatar::avatar;
|
||||||
pub use avatar::Avatar;
|
pub use avatar::Avatar;
|
||||||
pub use icon_button::icon_button;
|
pub use icon_button::icon_button;
|
||||||
pub use icon_button::IconButton;
|
|
||||||
pub use tab::tab;
|
pub use tab::tab;
|
||||||
pub use tab::Tab;
|
pub use tab::Tab;
|
||||||
pub use tool_divider::tool_divider;
|
pub use tool_divider::tool_divider;
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub struct IconButton {
|
||||||
state: InteractionState,
|
state: InteractionState,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn icon_button<V: 'static>(path: &'static str) -> IconButton {
|
pub fn icon_button(path: &'static str) -> IconButton {
|
||||||
IconButton {
|
IconButton {
|
||||||
path,
|
path,
|
||||||
variant: ButtonVariant::default(),
|
variant: ButtonVariant::default(),
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
// use crate::prelude::{ButtonVariant, UIState};
|
|
||||||
// use crate::theme::theme;
|
|
||||||
// use gpui2::elements::svg;
|
|
||||||
// use gpui2::style::{StyleHelpers, Styleable};
|
|
||||||
// use gpui2::{elements::div, IntoElement};
|
|
||||||
// use gpui2::{Element, ParentElement, ViewContext};
|
|
||||||
|
|
||||||
// #[derive(Element)]
|
|
||||||
// pub(crate) struct IconButton {
|
|
||||||
// path: &'static str,
|
|
||||||
// variant: ButtonVariant,
|
|
||||||
// state: UIState,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn icon_button<V: 'static>(path: &'static str) -> IconButton {
|
|
||||||
// IconButton {
|
|
||||||
// path,
|
|
||||||
// variant: ButtonVariant::Filled,
|
|
||||||
// state: UIState::Default,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl IconButton {
|
|
||||||
// fn variant(mut self, variant: ButtonVariant) -> Self {
|
|
||||||
// self.variant = variant;
|
|
||||||
|
|
||||||
// // Example of more interesting setter behavior
|
|
||||||
// // FilledButtons must be disabled
|
|
||||||
// if self.variant == ButtonVariant::Filled {
|
|
||||||
// self.state = UIState::Disabled;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// self
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn state(mut self, state: UIState) -> Self {
|
|
||||||
// // Example of more interesting setter behavior:
|
|
||||||
// // GhostButtons Cannot be disabled
|
|
||||||
// // Debug asserts are compiled out when we make a new release.
|
|
||||||
// // Useful for making sure developers develop correctly without breaking
|
|
||||||
// // everything
|
|
||||||
// debug_assert!(self.variant != ButtonVariant::Ghost && state != UIState::Disabled);
|
|
||||||
|
|
||||||
// self.state = state;
|
|
||||||
// self
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // const state = {
|
|
||||||
// // foo: "foo",
|
|
||||||
// // bar: "bar"
|
|
||||||
// // } as const
|
|
||||||
// //
|
|
||||||
// // type State = typeof state[keyof typeof something]
|
|
||||||
// //
|
|
||||||
// // type Button {
|
|
||||||
// // style: State
|
|
||||||
// // }
|
|
||||||
// //
|
|
||||||
// // <Button style="foo" /> State['foo']
|
|
||||||
|
|
||||||
// fn render_warning<V: 'static>(&mut self) -> impl IntoElement<V> {
|
|
||||||
// div()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
|
||||||
// let theme = theme(cx);
|
|
||||||
|
|
||||||
// let icon_color;
|
|
||||||
|
|
||||||
// enum Severity {
|
|
||||||
// Low,
|
|
||||||
// Medium,
|
|
||||||
// High,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Enum declaration and match statement example
|
|
||||||
// enum Style {
|
|
||||||
// Error,
|
|
||||||
// Warning(Severity),
|
|
||||||
// Foo,
|
|
||||||
// Bar,
|
|
||||||
// Baz,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let style = Style::Warning(Severity::High);
|
|
||||||
|
|
||||||
// match style {
|
|
||||||
// Error => return self.render_warning(),
|
|
||||||
// Warning(severity) => match severity {
|
|
||||||
// Low => {}
|
|
||||||
// Medium => {}
|
|
||||||
// High => {}
|
|
||||||
// },
|
|
||||||
// Foo => {}
|
|
||||||
// Bar => {}
|
|
||||||
// Baz => {}
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if self.state == UIState::Disabled {
|
|
||||||
// icon_color = theme.highest.base.disabled.foreground;
|
|
||||||
// } else {
|
|
||||||
// icon_color = theme.highest.base.default.foreground;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let mut div = div();
|
|
||||||
|
|
||||||
// if self.variant == ButtonVariant::Filled {
|
|
||||||
// div = div.fill(theme.highest.on.default.background);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// div.w_7()
|
|
||||||
// .h_6()
|
|
||||||
// .flex()
|
|
||||||
// .items_center()
|
|
||||||
// .justify_center()
|
|
||||||
// .rounded_md()
|
|
||||||
// .hover()
|
|
||||||
// .fill(theme.highest.base.hovered.background)
|
|
||||||
// .active()
|
|
||||||
// .fill(theme.highest.base.pressed.background)
|
|
||||||
// .child(svg().path(self.path).w_4().h_4().fill(icon_color))
|
|
||||||
// }
|
|
||||||
// }
|
|
|
@ -1,7 +1,10 @@
|
||||||
mod chat_panel;
|
mod chat_panel;
|
||||||
|
mod status_bar;
|
||||||
mod tab_bar;
|
mod tab_bar;
|
||||||
mod title_bar;
|
mod title_bar;
|
||||||
|
|
||||||
pub(crate) use chat_panel::chat_panel;
|
pub(crate) use chat_panel::chat_panel;
|
||||||
|
pub use status_bar::status_bar;
|
||||||
|
pub use status_bar::StatusBar;
|
||||||
pub(crate) use tab_bar::tab_bar;
|
pub(crate) use tab_bar::tab_bar;
|
||||||
pub(crate) use title_bar::title_bar;
|
pub(crate) use title_bar::title_bar;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::components::{icon_button, IconButton};
|
use crate::components::icon_button;
|
||||||
use crate::theme::theme;
|
use crate::theme::theme;
|
||||||
use gpui2::elements::div::ScrollState;
|
use gpui2::elements::div::ScrollState;
|
||||||
use gpui2::style::StyleHelpers;
|
use gpui2::style::StyleHelpers;
|
||||||
|
@ -57,8 +57,8 @@ impl<V: 'static> ChatPanel<V> {
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_px()
|
.gap_px()
|
||||||
.child(icon_button::<IconButton>("icons/plus.svg"))
|
.child(icon_button("icons/plus.svg"))
|
||||||
.child(icon_button::<IconButton>("icons/split.svg")),
|
.child(icon_button("icons/split.svg")),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
109
crates/storybook/src/modules/status_bar.rs
Normal file
109
crates/storybook/src/modules/status_bar.rs
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use crate::components::icon_button;
|
||||||
|
use crate::theme::{theme, Theme};
|
||||||
|
use gpui2::style::StyleHelpers;
|
||||||
|
use gpui2::{elements::div, IntoElement};
|
||||||
|
use gpui2::{Element, ParentElement, ViewContext};
|
||||||
|
|
||||||
|
#[derive(Default, PartialEq)]
|
||||||
|
pub enum Tool {
|
||||||
|
#[default]
|
||||||
|
ProjectPanel,
|
||||||
|
CollaborationPanel,
|
||||||
|
Terminal,
|
||||||
|
Assistant,
|
||||||
|
Feedback,
|
||||||
|
Diagnostics,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ToolGroup {
|
||||||
|
active_index: Option<usize>,
|
||||||
|
tools: Vec<Tool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ToolGroup {
|
||||||
|
fn default() -> Self {
|
||||||
|
ToolGroup {
|
||||||
|
active_index: None,
|
||||||
|
tools: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Element)]
|
||||||
|
pub struct StatusBar<V: 'static> {
|
||||||
|
view_type: PhantomData<V>,
|
||||||
|
left_tools: Option<ToolGroup>,
|
||||||
|
right_tools: Option<ToolGroup>,
|
||||||
|
bottom_tools: Option<ToolGroup>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn status_bar<V: 'static>() -> StatusBar<V> {
|
||||||
|
StatusBar {
|
||||||
|
view_type: PhantomData,
|
||||||
|
left_tools: None,
|
||||||
|
right_tools: None,
|
||||||
|
bottom_tools: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: 'static> StatusBar<V> {
|
||||||
|
pub fn left_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
|
||||||
|
self.left_tools = {
|
||||||
|
let mut tools = vec![tool];
|
||||||
|
tools.extend(self.left_tools.take().unwrap_or_default().tools);
|
||||||
|
Some(ToolGroup {
|
||||||
|
active_index,
|
||||||
|
tools,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn right_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
|
||||||
|
self.right_tools = {
|
||||||
|
let mut tools = vec![tool];
|
||||||
|
tools.extend(self.left_tools.take().unwrap_or_default().tools);
|
||||||
|
Some(ToolGroup {
|
||||||
|
active_index,
|
||||||
|
tools,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bottom_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
|
||||||
|
self.bottom_tools = {
|
||||||
|
let mut tools = vec![tool];
|
||||||
|
tools.extend(self.left_tools.take().unwrap_or_default().tools);
|
||||||
|
Some(ToolGroup {
|
||||||
|
active_index,
|
||||||
|
tools,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||||
|
let theme = theme(cx);
|
||||||
|
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.justify_between()
|
||||||
|
.w_full()
|
||||||
|
.fill(theme.lowest.base.default.background)
|
||||||
|
.child(self.left_tools(theme))
|
||||||
|
.child(div())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn left_tools(&self, theme: &Theme) -> impl Element<V> {
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.gap_px()
|
||||||
|
.child(icon_button("icons/folder_tree_16.svg"))
|
||||||
|
.child(icon_button("icons/bolt_16.svg"))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::components::{icon_button, tab, IconButton};
|
use crate::components::{icon_button, tab};
|
||||||
use crate::prelude::InteractionState;
|
use crate::prelude::InteractionState;
|
||||||
use crate::theme::theme;
|
use crate::theme::theme;
|
||||||
use gpui2::elements::div::ScrollState;
|
use gpui2::elements::div::ScrollState;
|
||||||
|
@ -43,11 +43,11 @@ impl<V: 'static> TabBar<V> {
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_px()
|
.gap_px()
|
||||||
.child(
|
.child(
|
||||||
icon_button::<IconButton>("icons/arrow_left.svg")
|
icon_button("icons/arrow_left.svg")
|
||||||
.state(InteractionState::Enabled.if_enabled(can_navigate_back)),
|
.state(InteractionState::Enabled.if_enabled(can_navigate_back)),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
icon_button::<IconButton>("icons/arrow_right.svg").state(
|
icon_button("icons/arrow_right.svg").state(
|
||||||
InteractionState::Enabled.if_enabled(can_navigate_forward),
|
InteractionState::Enabled.if_enabled(can_navigate_forward),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -83,8 +83,8 @@ impl<V: 'static> TabBar<V> {
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_px()
|
.gap_px()
|
||||||
.child(icon_button::<IconButton>("icons/plus.svg"))
|
.child(icon_button("icons/plus.svg"))
|
||||||
.child(icon_button::<IconButton>("icons/split.svg")),
|
.child(icon_button("icons/split.svg")),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::components::{avatar, icon_button, tool_divider, Avatar, IconButton};
|
use crate::components::{avatar, icon_button, tool_divider, Avatar};
|
||||||
use crate::prelude::Shape;
|
use crate::prelude::Shape;
|
||||||
use crate::theme::theme;
|
use crate::theme::theme;
|
||||||
use gpui2::style::{StyleHelpers, Styleable};
|
use gpui2::style::{StyleHelpers, Styleable};
|
||||||
|
@ -29,6 +29,37 @@ impl<V: 'static> TitleBar<V> {
|
||||||
.w_full()
|
.w_full()
|
||||||
.h_8()
|
.h_8()
|
||||||
.fill(theme.lowest.base.default.background)
|
.fill(theme.lowest.base.default.background)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.px_2()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.gap_1()
|
||||||
|
.child(icon_button("icons/stop_sharing.svg"))
|
||||||
|
.child(icon_button("icons/exit.svg")),
|
||||||
|
)
|
||||||
|
.child(tool_divider())
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.px_2()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.gap_1()
|
||||||
|
.child(icon_button("icons/radix/mic.svg"))
|
||||||
|
.child(icon_button("icons/radix/speaker-loud.svg"))
|
||||||
|
.child(icon_button("icons/radix/desktop.svg")),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div().px_2().flex().items_center().child(
|
||||||
|
avatar::<Avatar>("https://avatars.githubusercontent.com/u/1714999?v=4")
|
||||||
|
.shape(Shape::RoundedRectangle),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
|
@ -111,8 +142,8 @@ impl<V: 'static> TitleBar<V> {
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.child(icon_button::<IconButton>("icons/stop_sharing.svg"))
|
.child(icon_button("icons/stop_sharing.svg"))
|
||||||
.child(icon_button::<IconButton>("icons/exit.svg")),
|
.child(icon_button("icons/exit.svg")),
|
||||||
)
|
)
|
||||||
.child(tool_divider())
|
.child(tool_divider())
|
||||||
.child(
|
.child(
|
||||||
|
@ -121,9 +152,9 @@ impl<V: 'static> TitleBar<V> {
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.child(icon_button::<IconButton>("icons/radix/mic.svg"))
|
.child(icon_button("icons/radix/mic.svg"))
|
||||||
.child(icon_button::<IconButton>("icons/radix/speaker-loud.svg"))
|
.child(icon_button("icons/radix/speaker-loud.svg"))
|
||||||
.child(icon_button::<IconButton>("icons/radix/desktop.svg")),
|
.child(icon_button("icons/radix/desktop.svg")),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
div().px_2().flex().items_center().child(
|
div().px_2().flex().items_center().child(
|
||||||
|
|
|
@ -2,10 +2,15 @@
|
||||||
|
|
||||||
use crate::theme::Theme;
|
use crate::theme::Theme;
|
||||||
use ::theme as legacy_theme;
|
use ::theme as legacy_theme;
|
||||||
|
use components::icon_button;
|
||||||
use element_ext::ElementExt;
|
use element_ext::ElementExt;
|
||||||
use gpui2::{serde_json, vec2f, view, Element, RectF, ViewContext, WindowBounds};
|
use gpui2::{
|
||||||
|
elements::div, serde_json, style::StyleHelpers, vec2f, view, Element, ParentElement, RectF,
|
||||||
|
ViewContext, WindowBounds,
|
||||||
|
};
|
||||||
use legacy_theme::ThemeSettings;
|
use legacy_theme::ThemeSettings;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
|
use modules::title_bar;
|
||||||
use settings::{default_settings, SettingsStore};
|
use settings::{default_settings, SettingsStore};
|
||||||
use simplelog::SimpleLogger;
|
use simplelog::SimpleLogger;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
collab_panel::collab_panel,
|
collab_panel::collab_panel,
|
||||||
modules::{chat_panel, tab_bar, title_bar},
|
modules::{chat_panel, status_bar, tab_bar, title_bar},
|
||||||
theme::theme,
|
theme::theme,
|
||||||
};
|
};
|
||||||
use gpui2::{
|
use gpui2::{
|
||||||
|
@ -59,6 +59,7 @@ impl WorkspaceElement {
|
||||||
.child(chat_panel(self.right_scroll_state.clone())),
|
.child(chat_panel(self.right_scroll_state.clone())),
|
||||||
)
|
)
|
||||||
.child(statusbar())
|
.child(statusbar())
|
||||||
|
.child(status_bar())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue