Detailed changes
@@ -1,4 +1,4 @@
-use crate::prelude::{ButtonVariant, UIState};
+use crate::prelude::{ButtonVariant, InteractionState};
use crate::theme::theme;
use gpui2::elements::svg;
use gpui2::style::{StyleHelpers, Styleable};
@@ -6,31 +6,37 @@ use gpui2::{elements::div, IntoElement};
use gpui2::{Element, ParentElement, ViewContext};
#[derive(Element)]
-pub(crate) struct IconButton {
+pub struct IconButton {
path: &'static str,
variant: ButtonVariant,
- state: UIState,
+ state: InteractionState,
}
-pub fn icon_button<V: 'static>(
- path: &'static str,
- variant: ButtonVariant,
- state: UIState,
-) -> impl Element<V> {
+pub fn icon_button<V: 'static>(path: &'static str) -> IconButton {
IconButton {
path,
- variant,
- state,
+ variant: ButtonVariant::default(),
+ state: InteractionState::default(),
}
}
impl IconButton {
+ pub fn variant(mut self, variant: ButtonVariant) -> Self {
+ self.variant = variant;
+ self
+ }
+
+ pub fn state(mut self, state: InteractionState) -> Self {
+ self.state = state;
+ self
+ }
+
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
let theme = theme(cx);
let icon_color;
- if self.state == UIState::Disabled {
+ if self.state == InteractionState::Disabled {
icon_color = theme.highest.base.disabled.foreground;
} else {
icon_color = theme.highest.base.default.foreground;
@@ -1,12 +1,12 @@
use std::marker::PhantomData;
use crate::components::icon_button;
-use crate::prelude::{ButtonVariant, UIState};
use crate::theme::theme;
use gpui2::elements::div::ScrollState;
use gpui2::style::StyleHelpers;
use gpui2::{elements::div, IntoElement};
use gpui2::{Element, ParentElement, ViewContext};
+use theme::IconButton;
#[derive(Element)]
pub struct ChatPanel<V: 'static> {
@@ -58,16 +58,8 @@ impl<V: 'static> ChatPanel<V> {
.flex()
.items_center()
.gap_px()
- .child(icon_button(
- "icons/plus.svg",
- ButtonVariant::Ghost,
- UIState::Default,
- ))
- .child(icon_button(
- "icons/split.svg",
- ButtonVariant::Ghost,
- UIState::Default,
- )),
+ .child(icon_button::<IconButton>("icons/plus.svg"))
+ .child(icon_button::<IconButton>("icons/split.svg")),
),
)
}
@@ -1,12 +1,13 @@
use std::marker::PhantomData;
use crate::components::{icon_button, tab};
-use crate::prelude::{ButtonVariant, UIState};
+use crate::prelude::InteractionState;
use crate::theme::theme;
use gpui2::elements::div::ScrollState;
use gpui2::style::StyleHelpers;
use gpui2::{elements::div, IntoElement};
use gpui2::{Element, ParentElement, ViewContext};
+use theme::IconButton;
#[derive(Element)]
pub struct TabBar<V: 'static> {
@@ -24,7 +25,8 @@ pub fn tab_bar<V: 'static>(scroll_state: ScrollState) -> TabBar<V> {
impl<V: 'static> TabBar<V> {
fn render(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
let theme = theme(cx);
-
+ let can_navigate_back = true;
+ let can_navigate_forward = false;
div()
.w_full()
.flex()
@@ -41,16 +43,15 @@ impl<V: 'static> TabBar<V> {
.flex()
.items_center()
.gap_px()
- .child(icon_button(
- "icons/arrow_left.svg",
- ButtonVariant::Ghost,
- UIState::Default,
- ))
- .child(icon_button(
- "icons/arrow_right.svg",
- ButtonVariant::Ghost,
- UIState::Disabled,
- )),
+ .child(
+ icon_button::<IconButton>("icons/arrow_left.svg")
+ .state(InteractionState::Enabled.if_enabled(can_navigate_back)),
+ )
+ .child(
+ icon_button::<IconButton>("icons/arrow_right.svg").state(
+ InteractionState::Enabled.if_enabled(can_navigate_forward),
+ ),
+ ),
),
)
.child(
@@ -83,16 +84,8 @@ impl<V: 'static> TabBar<V> {
.flex()
.items_center()
.gap_px()
- .child(icon_button(
- "icons/plus.svg",
- ButtonVariant::Ghost,
- UIState::Default,
- ))
- .child(icon_button(
- "icons/split.svg",
- ButtonVariant::Ghost,
- UIState::Default,
- )),
+ .child(icon_button::<IconButton>("icons/plus.svg"))
+ .child(icon_button::<IconButton>("icons/split.svg")),
),
)
}
@@ -1,11 +1,12 @@
use std::marker::PhantomData;
use crate::components::{avatar, icon_button, tool_divider};
-use crate::prelude::{ButtonVariant, Shape, UIState};
+use crate::prelude::Shape;
use crate::theme::theme;
use gpui2::style::{StyleHelpers, Styleable};
use gpui2::{elements::div, IntoElement};
use gpui2::{Element, ParentElement, ViewContext};
+use theme::IconButton;
#[derive(Element)]
pub struct TitleBar<V: 'static> {
@@ -111,16 +112,8 @@ impl<V: 'static> TitleBar<V> {
.flex()
.items_center()
.gap_1()
- .child(icon_button(
- "icons/stop_sharing.svg",
- ButtonVariant::Ghost,
- UIState::Default,
- ))
- .child(icon_button(
- "icons/exit.svg",
- ButtonVariant::Ghost,
- UIState::Default,
- )),
+ .child(icon_button::<IconButton>("icons/stop_sharing.svg"))
+ .child(icon_button::<IconButton>("icons/exit.svg")),
)
.child(tool_divider())
.child(
@@ -129,21 +122,9 @@ impl<V: 'static> TitleBar<V> {
.flex()
.items_center()
.gap_1()
- .child(icon_button(
- "icons/radix/mic.svg",
- ButtonVariant::Ghost,
- UIState::Default,
- ))
- .child(icon_button(
- "icons/radix/speaker-loud.svg",
- ButtonVariant::Ghost,
- UIState::Default,
- ))
- .child(icon_button(
- "icons/radix/desktop.svg",
- ButtonVariant::Ghost,
- UIState::Default,
- )),
+ .child(icon_button::<IconButton>("icons/radix/mic.svg"))
+ .child(icon_button::<IconButton>("icons/radix/speaker-loud.svg"))
+ .child(icon_button::<IconButton>("icons/radix/desktop.svg")),
)
.child(div().px_2().flex().items_center().child(avatar(
"https://avatars.githubusercontent.com/u/1714999?v=4",
@@ -1,26 +1,42 @@
-#[derive(PartialEq)]
+#[derive(Default, PartialEq)]
pub enum ButtonVariant {
+ #[default]
Ghost,
Filled,
}
-#[derive(PartialEq)]
+#[derive(Default, PartialEq)]
pub enum Shape {
+ #[default]
Circle,
RoundedRectangle,
}
-#[derive(PartialEq)]
-pub enum UIState {
- Default,
+#[derive(Default, PartialEq, Clone, Copy)]
+pub enum InteractionState {
+ #[default]
+ Enabled,
Hovered,
Active,
Focused,
+ Dragged,
Disabled,
}
-#[derive(PartialEq)]
-pub enum UIToggleState {
- Default,
- Enabled,
+impl InteractionState {
+ pub fn if_enabled(&self, enabled: bool) -> Self {
+ if enabled {
+ *self
+ } else {
+ InteractionState::Disabled
+ }
+ }
+}
+
+#[derive(Default, PartialEq)]
+pub enum SelectedState {
+ #[default]
+ Unselected,
+ PartiallySelected,
+ Selected,
}
@@ -0,0 +1,43 @@
+## Interaction State
+
+**Enabled**
+
+An enabled state communicates an interactive component or element.
+
+**Disabled**
+
+A disabled state communicates a inoperable component or element.
+
+**Hover**
+
+A hover state communicates when a user has placed a cursor above an interactive element.
+
+**Focused**
+
+A focused state communicates when a user has highlighted an element, using an input method such as a keyboard or voice.
+
+**Activated**
+
+An activated state communicates a highlighted destination, whether initiated by the user or by default.
+
+**Pressed**
+
+A pressed state communicates a user tap.
+
+**Dragged**
+
+A dragged state communicates when a user presses and moves an element.
+
+## Selected State
+
+**Unselected**
+
+dfa
+
+**Partially Selected**
+
+daf
+
+**Selected**
+
+dfa