Checkpoint
This commit is contained in:
parent
bbc4673f17
commit
f54f2c52e9
6 changed files with 110 additions and 79 deletions
|
@ -1,4 +1,4 @@
|
||||||
use crate::prelude::{ButtonVariant, UIState};
|
use crate::prelude::{ButtonVariant, InteractionState};
|
||||||
use crate::theme::theme;
|
use crate::theme::theme;
|
||||||
use gpui2::elements::svg;
|
use gpui2::elements::svg;
|
||||||
use gpui2::style::{StyleHelpers, Styleable};
|
use gpui2::style::{StyleHelpers, Styleable};
|
||||||
|
@ -6,31 +6,37 @@ use gpui2::{elements::div, IntoElement};
|
||||||
use gpui2::{Element, ParentElement, ViewContext};
|
use gpui2::{Element, ParentElement, ViewContext};
|
||||||
|
|
||||||
#[derive(Element)]
|
#[derive(Element)]
|
||||||
pub(crate) struct IconButton {
|
pub struct IconButton {
|
||||||
path: &'static str,
|
path: &'static str,
|
||||||
variant: ButtonVariant,
|
variant: ButtonVariant,
|
||||||
state: UIState,
|
state: InteractionState,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn icon_button<V: 'static>(
|
pub fn icon_button<V: 'static>(path: &'static str) -> IconButton {
|
||||||
path: &'static str,
|
|
||||||
variant: ButtonVariant,
|
|
||||||
state: UIState,
|
|
||||||
) -> impl Element<V> {
|
|
||||||
IconButton {
|
IconButton {
|
||||||
path,
|
path,
|
||||||
variant,
|
variant: ButtonVariant::default(),
|
||||||
state,
|
state: InteractionState::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IconButton {
|
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> {
|
fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||||
let theme = theme(cx);
|
let theme = theme(cx);
|
||||||
|
|
||||||
let icon_color;
|
let icon_color;
|
||||||
|
|
||||||
if self.state == UIState::Disabled {
|
if self.state == InteractionState::Disabled {
|
||||||
icon_color = theme.highest.base.disabled.foreground;
|
icon_color = theme.highest.base.disabled.foreground;
|
||||||
} else {
|
} else {
|
||||||
icon_color = theme.highest.base.default.foreground;
|
icon_color = theme.highest.base.default.foreground;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::components::icon_button;
|
use crate::components::icon_button;
|
||||||
use crate::prelude::{ButtonVariant, UIState};
|
|
||||||
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;
|
||||||
use gpui2::{elements::div, IntoElement};
|
use gpui2::{elements::div, IntoElement};
|
||||||
use gpui2::{Element, ParentElement, ViewContext};
|
use gpui2::{Element, ParentElement, ViewContext};
|
||||||
|
use theme::IconButton;
|
||||||
|
|
||||||
#[derive(Element)]
|
#[derive(Element)]
|
||||||
pub struct ChatPanel<V: 'static> {
|
pub struct ChatPanel<V: 'static> {
|
||||||
|
@ -58,16 +58,8 @@ impl<V: 'static> ChatPanel<V> {
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_px()
|
.gap_px()
|
||||||
.child(icon_button(
|
.child(icon_button::<IconButton>("icons/plus.svg"))
|
||||||
"icons/plus.svg",
|
.child(icon_button::<IconButton>("icons/split.svg")),
|
||||||
ButtonVariant::Ghost,
|
|
||||||
UIState::Default,
|
|
||||||
))
|
|
||||||
.child(icon_button(
|
|
||||||
"icons/split.svg",
|
|
||||||
ButtonVariant::Ghost,
|
|
||||||
UIState::Default,
|
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::components::{icon_button, tab};
|
use crate::components::{icon_button, tab};
|
||||||
use crate::prelude::{ButtonVariant, UIState};
|
use crate::prelude::InteractionState;
|
||||||
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;
|
||||||
use gpui2::{elements::div, IntoElement};
|
use gpui2::{elements::div, IntoElement};
|
||||||
use gpui2::{Element, ParentElement, ViewContext};
|
use gpui2::{Element, ParentElement, ViewContext};
|
||||||
|
use theme::IconButton;
|
||||||
|
|
||||||
#[derive(Element)]
|
#[derive(Element)]
|
||||||
pub struct TabBar<V: 'static> {
|
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> {
|
impl<V: 'static> TabBar<V> {
|
||||||
fn render(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
fn render(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
|
||||||
let theme = theme(cx);
|
let theme = theme(cx);
|
||||||
|
let can_navigate_back = true;
|
||||||
|
let can_navigate_forward = false;
|
||||||
div()
|
div()
|
||||||
.w_full()
|
.w_full()
|
||||||
.flex()
|
.flex()
|
||||||
|
@ -41,16 +43,15 @@ impl<V: 'static> TabBar<V> {
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_px()
|
.gap_px()
|
||||||
.child(icon_button(
|
.child(
|
||||||
"icons/arrow_left.svg",
|
icon_button::<IconButton>("icons/arrow_left.svg")
|
||||||
ButtonVariant::Ghost,
|
.state(InteractionState::Enabled.if_enabled(can_navigate_back)),
|
||||||
UIState::Default,
|
)
|
||||||
))
|
.child(
|
||||||
.child(icon_button(
|
icon_button::<IconButton>("icons/arrow_right.svg").state(
|
||||||
"icons/arrow_right.svg",
|
InteractionState::Enabled.if_enabled(can_navigate_forward),
|
||||||
ButtonVariant::Ghost,
|
),
|
||||||
UIState::Disabled,
|
),
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
|
@ -83,16 +84,8 @@ impl<V: 'static> TabBar<V> {
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_px()
|
.gap_px()
|
||||||
.child(icon_button(
|
.child(icon_button::<IconButton>("icons/plus.svg"))
|
||||||
"icons/plus.svg",
|
.child(icon_button::<IconButton>("icons/split.svg")),
|
||||||
ButtonVariant::Ghost,
|
|
||||||
UIState::Default,
|
|
||||||
))
|
|
||||||
.child(icon_button(
|
|
||||||
"icons/split.svg",
|
|
||||||
ButtonVariant::Ghost,
|
|
||||||
UIState::Default,
|
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::components::{avatar, icon_button, tool_divider};
|
use crate::components::{avatar, icon_button, tool_divider};
|
||||||
use crate::prelude::{ButtonVariant, Shape, UIState};
|
use crate::prelude::Shape;
|
||||||
use crate::theme::theme;
|
use crate::theme::theme;
|
||||||
use gpui2::style::{StyleHelpers, Styleable};
|
use gpui2::style::{StyleHelpers, Styleable};
|
||||||
use gpui2::{elements::div, IntoElement};
|
use gpui2::{elements::div, IntoElement};
|
||||||
use gpui2::{Element, ParentElement, ViewContext};
|
use gpui2::{Element, ParentElement, ViewContext};
|
||||||
|
use theme::IconButton;
|
||||||
|
|
||||||
#[derive(Element)]
|
#[derive(Element)]
|
||||||
pub struct TitleBar<V: 'static> {
|
pub struct TitleBar<V: 'static> {
|
||||||
|
@ -111,16 +112,8 @@ impl<V: 'static> TitleBar<V> {
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.child(icon_button(
|
.child(icon_button::<IconButton>("icons/stop_sharing.svg"))
|
||||||
"icons/stop_sharing.svg",
|
.child(icon_button::<IconButton>("icons/exit.svg")),
|
||||||
ButtonVariant::Ghost,
|
|
||||||
UIState::Default,
|
|
||||||
))
|
|
||||||
.child(icon_button(
|
|
||||||
"icons/exit.svg",
|
|
||||||
ButtonVariant::Ghost,
|
|
||||||
UIState::Default,
|
|
||||||
)),
|
|
||||||
)
|
)
|
||||||
.child(tool_divider())
|
.child(tool_divider())
|
||||||
.child(
|
.child(
|
||||||
|
@ -129,21 +122,9 @@ impl<V: 'static> TitleBar<V> {
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.child(icon_button(
|
.child(icon_button::<IconButton>("icons/radix/mic.svg"))
|
||||||
"icons/radix/mic.svg",
|
.child(icon_button::<IconButton>("icons/radix/speaker-loud.svg"))
|
||||||
ButtonVariant::Ghost,
|
.child(icon_button::<IconButton>("icons/radix/desktop.svg")),
|
||||||
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(div().px_2().flex().items_center().child(avatar(
|
.child(div().px_2().flex().items_center().child(avatar(
|
||||||
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
||||||
|
|
|
@ -1,26 +1,42 @@
|
||||||
#[derive(PartialEq)]
|
#[derive(Default, PartialEq)]
|
||||||
pub enum ButtonVariant {
|
pub enum ButtonVariant {
|
||||||
|
#[default]
|
||||||
Ghost,
|
Ghost,
|
||||||
Filled,
|
Filled,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(Default, PartialEq)]
|
||||||
pub enum Shape {
|
pub enum Shape {
|
||||||
|
#[default]
|
||||||
Circle,
|
Circle,
|
||||||
RoundedRectangle,
|
RoundedRectangle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(Default, PartialEq, Clone, Copy)]
|
||||||
pub enum UIState {
|
pub enum InteractionState {
|
||||||
Default,
|
#[default]
|
||||||
|
Enabled,
|
||||||
Hovered,
|
Hovered,
|
||||||
Active,
|
Active,
|
||||||
Focused,
|
Focused,
|
||||||
|
Dragged,
|
||||||
Disabled,
|
Disabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
impl InteractionState {
|
||||||
pub enum UIToggleState {
|
pub fn if_enabled(&self, enabled: bool) -> Self {
|
||||||
Default,
|
if enabled {
|
||||||
Enabled,
|
*self
|
||||||
|
} else {
|
||||||
|
InteractionState::Disabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, PartialEq)]
|
||||||
|
pub enum SelectedState {
|
||||||
|
#[default]
|
||||||
|
Unselected,
|
||||||
|
PartiallySelected,
|
||||||
|
Selected,
|
||||||
}
|
}
|
||||||
|
|
43
docs/ui/states.md
Normal file
43
docs/ui/states.md
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue