Add hover state to assistant buttons

This commit is contained in:
Antonio Scandurra 2023-06-26 17:48:43 +02:00
parent 723c8b98b3
commit e77abbf64f
3 changed files with 249 additions and 183 deletions

View File

@ -38,7 +38,7 @@ use std::{
sync::Arc,
time::Duration,
};
use theme::{ui::IconStyle, AssistantStyle};
use theme::AssistantStyle;
use util::{channel::ReleaseChannel, paths::CONVERSATIONS_DIR, post_inc, ResultExt, TryFutureExt};
use workspace::{
dock::{DockPosition, Panel},
@ -343,131 +343,140 @@ impl AssistantPanel {
self.editors.get(self.active_editor_index?)
}
fn render_hamburger_button(style: &IconStyle) -> impl Element<Self> {
fn render_hamburger_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
enum ListConversations {}
Svg::for_style(style.icon.clone())
.contained()
.with_style(style.container)
.mouse::<ListConversations>(0)
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, this: &mut Self, cx| {
if this.active_editor().is_some() {
this.set_active_editor_index(None, cx);
} else {
this.set_active_editor_index(this.prev_active_editor_index, cx);
}
})
let theme = theme::current(cx);
MouseEventHandler::<ListConversations, _>::new(0, cx, |state, _| {
let style = theme.assistant.hamburger_button.style_for(state);
Svg::for_style(style.icon.clone())
.contained()
.with_style(style.container)
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, this: &mut Self, cx| {
if this.active_editor().is_some() {
this.set_active_editor_index(None, cx);
} else {
this.set_active_editor_index(this.prev_active_editor_index, cx);
}
})
}
fn render_editor_tools(
&self,
style: &AssistantStyle,
cx: &mut ViewContext<Self>,
) -> Vec<AnyElement<Self>> {
fn render_editor_tools(&self, cx: &mut ViewContext<Self>) -> Vec<AnyElement<Self>> {
if self.active_editor().is_some() {
vec![
Self::render_split_button(&style.split_button, cx).into_any(),
Self::render_quote_button(&style.quote_button, cx).into_any(),
Self::render_assist_button(&style.assist_button, cx).into_any(),
Self::render_split_button(cx).into_any(),
Self::render_quote_button(cx).into_any(),
Self::render_assist_button(cx).into_any(),
]
} else {
Default::default()
}
}
fn render_split_button(style: &IconStyle, cx: &mut ViewContext<Self>) -> impl Element<Self> {
fn render_split_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
let theme = theme::current(cx);
let tooltip_style = theme::current(cx).tooltip.clone();
Svg::for_style(style.icon.clone())
.contained()
.with_style(style.container)
.mouse::<Split>(0)
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, this: &mut Self, cx| {
if let Some(active_editor) = this.active_editor() {
active_editor.update(cx, |editor, cx| editor.split(&Default::default(), cx));
}
})
.with_tooltip::<Split>(
1,
"Split Message".into(),
Some(Box::new(Split)),
tooltip_style,
cx,
)
MouseEventHandler::<Split, _>::new(0, cx, |state, _| {
let style = theme.assistant.split_button.style_for(state);
Svg::for_style(style.icon.clone())
.contained()
.with_style(style.container)
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, this: &mut Self, cx| {
if let Some(active_editor) = this.active_editor() {
active_editor.update(cx, |editor, cx| editor.split(&Default::default(), cx));
}
})
.with_tooltip::<Split>(
1,
"Split Message".into(),
Some(Box::new(Split)),
tooltip_style,
cx,
)
}
fn render_assist_button(style: &IconStyle, cx: &mut ViewContext<Self>) -> impl Element<Self> {
fn render_assist_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
let theme = theme::current(cx);
let tooltip_style = theme::current(cx).tooltip.clone();
Svg::for_style(style.icon.clone())
.contained()
.with_style(style.container)
.mouse::<Assist>(0)
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, this: &mut Self, cx| {
if let Some(active_editor) = this.active_editor() {
active_editor.update(cx, |editor, cx| editor.assist(&Default::default(), cx));
}
})
.with_tooltip::<Assist>(
1,
"Assist".into(),
Some(Box::new(Assist)),
tooltip_style,
cx,
)
MouseEventHandler::<Assist, _>::new(0, cx, |state, _| {
let style = theme.assistant.assist_button.style_for(state);
Svg::for_style(style.icon.clone())
.contained()
.with_style(style.container)
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, this: &mut Self, cx| {
if let Some(active_editor) = this.active_editor() {
active_editor.update(cx, |editor, cx| editor.assist(&Default::default(), cx));
}
})
.with_tooltip::<Assist>(
1,
"Assist".into(),
Some(Box::new(Assist)),
tooltip_style,
cx,
)
}
fn render_quote_button(style: &IconStyle, cx: &mut ViewContext<Self>) -> impl Element<Self> {
fn render_quote_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
let theme = theme::current(cx);
let tooltip_style = theme::current(cx).tooltip.clone();
Svg::for_style(style.icon.clone())
.contained()
.with_style(style.container)
.mouse::<QuoteSelection>(0)
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, this: &mut Self, cx| {
if let Some(workspace) = this.workspace.upgrade(cx) {
cx.window_context().defer(move |cx| {
workspace.update(cx, |workspace, cx| {
ConversationEditor::quote_selection(workspace, &Default::default(), cx)
});
MouseEventHandler::<QuoteSelection, _>::new(0, cx, |state, _| {
let style = theme.assistant.quote_button.style_for(state);
Svg::for_style(style.icon.clone())
.contained()
.with_style(style.container)
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, this: &mut Self, cx| {
if let Some(workspace) = this.workspace.upgrade(cx) {
cx.window_context().defer(move |cx| {
workspace.update(cx, |workspace, cx| {
ConversationEditor::quote_selection(workspace, &Default::default(), cx)
});
}
})
.with_tooltip::<QuoteSelection>(
1,
"Assist".into(),
Some(Box::new(QuoteSelection)),
tooltip_style,
cx,
)
});
}
})
.with_tooltip::<QuoteSelection>(
1,
"Assist".into(),
Some(Box::new(QuoteSelection)),
tooltip_style,
cx,
)
}
fn render_plus_button(style: &IconStyle) -> impl Element<Self> {
fn render_plus_button(cx: &mut ViewContext<Self>) -> impl Element<Self> {
enum AddConversation {}
Svg::for_style(style.icon.clone())
.contained()
.with_style(style.container)
.mouse::<AddConversation>(0)
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, this: &mut Self, cx| {
this.new_conversation(cx);
})
let theme = theme::current(cx);
MouseEventHandler::<AddConversation, _>::new(0, cx, |state, _| {
let style = theme.assistant.plus_button.style_for(state);
Svg::for_style(style.icon.clone())
.contained()
.with_style(style.container)
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, this: &mut Self, cx| {
this.new_conversation(cx);
})
}
fn render_zoom_button(
&self,
style: &AssistantStyle,
cx: &mut ViewContext<Self>,
) -> impl Element<Self> {
fn render_zoom_button(&self, cx: &mut ViewContext<Self>) -> impl Element<Self> {
enum ToggleZoomButton {}
let theme = theme::current(cx);
let style = if self.zoomed {
&style.zoom_out_button
&theme.assistant.zoom_out_button
} else {
&style.zoom_in_button
&theme.assistant.zoom_in_button
};
MouseEventHandler::<ToggleZoomButton, _>::new(0, cx, |_, _| {
MouseEventHandler::<ToggleZoomButton, _>::new(0, cx, |state, _| {
let style = style.style_for(state);
Svg::for_style(style.icon.clone())
.contained()
.with_style(style.container)
@ -605,21 +614,15 @@ impl View for AssistantPanel {
Flex::column()
.with_child(
Flex::row()
.with_child(
Self::render_hamburger_button(&style.hamburger_button).aligned(),
)
.with_child(Self::render_hamburger_button(cx).aligned())
.with_children(title)
.with_children(
self.render_editor_tools(&style, cx)
self.render_editor_tools(cx)
.into_iter()
.map(|tool| tool.aligned().flex_float()),
)
.with_child(
Self::render_plus_button(&style.plus_button)
.aligned()
.flex_float(),
)
.with_child(self.render_zoom_button(&style, cx).aligned())
.with_child(Self::render_plus_button(cx).aligned().flex_float())
.with_child(self.render_zoom_button(cx).aligned())
.contained()
.with_style(theme.workspace.tab_bar.container)
.expanded()

View File

@ -993,13 +993,13 @@ pub struct TerminalStyle {
#[derive(Clone, Deserialize, Default, JsonSchema)]
pub struct AssistantStyle {
pub container: ContainerStyle,
pub hamburger_button: IconStyle,
pub split_button: IconStyle,
pub assist_button: IconStyle,
pub quote_button: IconStyle,
pub zoom_in_button: IconStyle,
pub zoom_out_button: IconStyle,
pub plus_button: IconStyle,
pub hamburger_button: Interactive<IconStyle>,
pub split_button: Interactive<IconStyle>,
pub assist_button: Interactive<IconStyle>,
pub quote_button: Interactive<IconStyle>,
pub zoom_in_button: Interactive<IconStyle>,
pub zoom_out_button: Interactive<IconStyle>,
pub plus_button: Interactive<IconStyle>,
pub title: ContainedText,
pub message_header: ContainerStyle,
pub sent_at: ContainedText,

View File

@ -15,97 +15,160 @@ export default function assistant(colorScheme: ColorScheme) {
margin: { bottom: 6, top: 6 },
background: editor(colorScheme).background,
},
hamburgerButton: {
icon: {
color: text(layer, "sans", "default", { size: "sm" }).color,
asset: "icons/hamburger_15.svg",
dimensions: {
width: 15,
height: 15,
hamburgerButton: interactive({
base: {
icon: {
color: foreground(layer, "variant"),
asset: "icons/hamburger_15.svg",
dimensions: {
width: 15,
height: 15,
},
},
container: {
margin: { left: 12 },
}
},
container: {
margin: { left: 12 },
state: {
hovered: {
icon: {
color: foreground(layer, "hovered")
}
}
}
},
splitButton: {
icon: {
color: text(layer, "sans", "default", { size: "sm" }).color,
asset: "icons/split_message_15.svg",
dimensions: {
width: 15,
height: 15,
}),
splitButton: interactive({
base: {
icon: {
color: foreground(layer, "variant"),
asset: "icons/split_message_15.svg",
dimensions: {
width: 15,
height: 15,
},
},
container: {
margin: { left: 12 },
}
},
container: {
margin: { left: 12 },
state: {
hovered: {
icon: {
color: foreground(layer, "hovered")
}
}
}
},
quoteButton: {
icon: {
color: text(layer, "sans", "default", { size: "sm" }).color,
asset: "icons/quote_15.svg",
dimensions: {
width: 15,
height: 15,
}),
quoteButton: interactive({
base: {
icon: {
color: foreground(layer, "variant"),
asset: "icons/quote_15.svg",
dimensions: {
width: 15,
height: 15,
},
},
container: {
margin: { left: 12 },
}
},
container: {
margin: { left: 12 },
state: {
hovered: {
icon: {
color: foreground(layer, "hovered")
}
}
}
},
assistButton: {
icon: {
color: text(layer, "sans", "default", { size: "sm" }).color,
asset: "icons/assist_15.svg",
dimensions: {
width: 15,
height: 15,
}),
assistButton: interactive({
base: {
icon: {
color: foreground(layer, "variant"),
asset: "icons/assist_15.svg",
dimensions: {
width: 15,
height: 15,
},
},
container: {
margin: { left: 12, right: 24 },
}
},
container: {
margin: { left: 12, right: 24 },
state: {
hovered: {
icon: {
color: foreground(layer, "hovered")
}
}
}
},
zoomInButton: {
icon: {
color: text(layer, "sans", "default", { size: "sm" }).color,
asset: "icons/maximize_8.svg",
dimensions: {
width: 12,
height: 12,
}),
zoomInButton: interactive({
base: {
icon: {
color: foreground(layer, "variant"),
asset: "icons/maximize_8.svg",
dimensions: {
width: 12,
height: 12,
},
},
container: {
margin: { right: 12 },
}
},
container: {
margin: { right: 12 },
state: {
hovered: {
icon: {
color: foreground(layer, "hovered")
}
}
}
},
zoomOutButton: {
icon: {
color: text(layer, "sans", "default", { size: "sm" }).color,
asset: "icons/minimize_8.svg",
dimensions: {
width: 12,
height: 12,
}),
zoomOutButton: interactive({
base: {
icon: {
color: foreground(layer, "variant"),
asset: "icons/minimize_8.svg",
dimensions: {
width: 12,
height: 12,
},
},
container: {
margin: { right: 12 },
}
},
container: {
margin: { right: 12 },
state: {
hovered: {
icon: {
color: foreground(layer, "hovered")
}
}
}
},
plusButton: {
icon: {
color: text(layer, "sans", "default", { size: "sm" }).color,
asset: "icons/plus_12.svg",
dimensions: {
width: 12,
height: 12,
}),
plusButton: interactive({
base: {
icon: {
color: foreground(layer, "variant"),
asset: "icons/plus_12.svg",
dimensions: {
width: 12,
height: 12,
},
},
container: {
margin: { right: 12 },
}
},
container: {
margin: { right: 12 },
state: {
hovered: {
icon: {
color: foreground(layer, "hovered")
}
}
}
},
}),
title: {
margin: { left: 12 },
...text(layer, "sans", "default", { size: "sm" })