From 2678dfdc57208737bf712793ee489b770aae440d Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 29 Jun 2023 17:32:04 -0400 Subject: [PATCH 1/7] Update assistant styles --- styles/src/style_tree/assistant.ts | 319 +++++++++++------------------ 1 file changed, 120 insertions(+), 199 deletions(-) diff --git a/styles/src/style_tree/assistant.ts b/styles/src/style_tree/assistant.ts index bdde221aca..1b754b632c 100644 --- a/styles/src/style_tree/assistant.ts +++ b/styles/src/style_tree/assistant.ts @@ -1,232 +1,164 @@ -import { ColorScheme } from "../theme/color_scheme" -import { text, border, background, foreground } from "./components" -import { interactive } from "../element" +import { ColorScheme, StyleSets } from "../theme/color_scheme" +import { text, border, background, foreground, TextStyle } from "./components" +import { Interactive, interactive } from "../element" + +interface ToolbarButtonOptions { + icon: string +} + +type RoleCycleButton = TextStyle & { + background?: string +} +// TODO: Replace these with zed types +type RemainingTokens = TextStyle & { + background: string, + margin: { top: number, right: number }, + padding: { + right: number, + left: number, + top: number, + bottom: number, + }, + corner_radius: number, +} export default function assistant(theme: ColorScheme): any { + const TOOLBAR_SPACING = 8 + + const toolbar_button = ({ icon }: ToolbarButtonOptions) => { + return ( + interactive({ + base: { + icon: { + color: foreground(theme.highest, "variant"), + asset: icon, + dimensions: { + width: 15, + height: 15, + }, + }, + container: { + padding: { left: TOOLBAR_SPACING, right: TOOLBAR_SPACING }, + }, + }, + state: { + hovered: { + icon: { + color: foreground(theme.highest, "hovered"), + }, + }, + }, + }) + ) + } + + const interactive_role = (color: StyleSets): Interactive => { + return ( + interactive({ + base: { + ...text(theme.highest, "sans", color, { size: "sm" }), + }, + state: { + hovered: { + ...text(theme.highest, "sans", color, { size: "sm" }), + background: background(theme.highest, color, "hovered"), + }, + clicked: { + ...text(theme.highest, "sans", color, { size: "sm" }), + background: background(theme.highest, color, "pressed"), + } + }, + }) + ) + } + + const tokens_remaining = (color: StyleSets): RemainingTokens => { + return ( + { + ...text(theme.highest, "mono", color, { size: "xs" }), + background: background(theme.highest, "on", "default"), + margin: { top: 12, right: 8 }, + padding: { right: 4, left: 4, top: 1, bottom: 1 }, + corner_radius: 6, + } + ) + } + return { container: { background: background(theme.highest), padding: { left: 12 }, }, message_header: { - margin: { bottom: 6, top: 6 }, + margin: { bottom: 4, top: 4 }, background: background(theme.highest), }, - hamburger_button: interactive({ - base: { - icon: { - color: foreground(theme.highest, "variant"), - asset: "icons/hamburger_15.svg", - dimensions: { - width: 15, - height: 15, - }, - }, - container: { - padding: { left: 12, right: 8.5 }, - }, - }, - state: { - hovered: { - icon: { - color: foreground(theme.highest, "hovered"), - }, - }, - }, + hamburger_button: toolbar_button({ + icon: "icons/hamburger_15.svg", }), - split_button: interactive({ - base: { - icon: { - color: foreground(theme.highest, "variant"), - asset: "icons/split_message_15.svg", - dimensions: { - width: 15, - height: 15, - }, - }, - container: { - padding: { left: 8.5, right: 8.5 }, - }, - }, - state: { - hovered: { - icon: { - color: foreground(theme.highest, "hovered"), - }, - }, - }, + + split_button: toolbar_button({ + icon: "icons/split_message_15.svg", }), - quote_button: interactive({ - base: { - icon: { - color: foreground(theme.highest, "variant"), - asset: "icons/quote_15.svg", - dimensions: { - width: 15, - height: 15, - }, - }, - container: { - padding: { left: 8.5, right: 8.5 }, - }, - }, - state: { - hovered: { - icon: { - color: foreground(theme.highest, "hovered"), - }, - }, - }, + quote_button: toolbar_button({ + icon: "icons/radix/quote.svg", }), - assist_button: interactive({ - base: { - icon: { - color: foreground(theme.highest, "variant"), - asset: "icons/assist_15.svg", - dimensions: { - width: 15, - height: 15, - }, - }, - container: { - padding: { left: 8.5, right: 8.5 }, - }, - }, - state: { - hovered: { - icon: { - color: foreground(theme.highest, "hovered"), - }, - }, - }, + assist_button: toolbar_button({ + icon: "icons/radix/magic-wand.svg", }), - zoom_in_button: interactive({ - base: { - icon: { - color: foreground(theme.highest, "variant"), - asset: "icons/maximize_8.svg", - dimensions: { - width: 12, - height: 12, - }, - }, - container: { - padding: { left: 10, right: 10 }, - }, - }, - state: { - hovered: { - icon: { - color: foreground(theme.highest, "hovered"), - }, - }, - }, + zoom_in_button: toolbar_button({ + icon: "icons/radix/enter-full-screen.svg", }), - zoom_out_button: interactive({ - base: { - icon: { - color: foreground(theme.highest, "variant"), - asset: "icons/minimize_8.svg", - dimensions: { - width: 12, - height: 12, - }, - }, - container: { - padding: { left: 10, right: 10 }, - }, - }, - state: { - hovered: { - icon: { - color: foreground(theme.highest, "hovered"), - }, - }, - }, + zoom_out_button: toolbar_button({ + icon: "icons/radix/exit-full-screen.svg", }), - plus_button: interactive({ - base: { - icon: { - color: foreground(theme.highest, "variant"), - asset: "icons/plus_12.svg", - dimensions: { - width: 12, - height: 12, - }, - }, - container: { - padding: { left: 10, right: 10 }, - }, - }, - state: { - hovered: { - icon: { - color: foreground(theme.highest, "hovered"), - }, - }, - }, + plus_button: toolbar_button({ + icon: "icons/radix/plus.svg", }), title: { - ...text(theme.highest, "sans", "default", { size: "sm" }), + ...text(theme.highest, "sans", "default", { size: "xs" }), }, saved_conversation: { container: interactive({ base: { - background: background(theme.highest, "on"), + background: background(theme.middle), padding: { top: 4, bottom: 4 }, + border: border(theme.middle, "default", { top: true, overlay: true }), }, state: { hovered: { - background: background(theme.highest, "on", "hovered"), + background: background(theme.middle, "hovered"), }, + clicked: { + background: background(theme.middle, "pressed"), + } }, }), saved_at: { margin: { left: 8 }, - ...text(theme.highest, "sans", "default", { size: "xs" }), + ...text(theme.highest, "sans", "variant", { size: "xs" }), }, title: { - margin: { left: 16 }, + margin: { left: 12 }, ...text(theme.highest, "sans", "default", { size: "sm", weight: "bold", }), }, }, - user_sender: { - default: { - ...text(theme.highest, "sans", "default", { - size: "sm", - weight: "bold", - }), - }, - }, - assistant_sender: { - default: { - ...text(theme.highest, "sans", "accent", { - size: "sm", - weight: "bold", - }), - }, - }, - system_sender: { - default: { - ...text(theme.highest, "sans", "variant", { - size: "sm", - weight: "bold", - }), - }, - }, + user_sender: interactive_role("base"), + assistant_sender: interactive_role("accent"), + system_sender: interactive_role("warning"), sent_at: { margin: { top: 2, left: 8 }, - ...text(theme.highest, "sans", "default", { size: "2xs" }), + ...text(theme.highest, "sans", "variant", { size: "2xs" }), }, model: interactive({ base: { - background: background(theme.highest, "on"), - margin: { left: 12, right: 12, top: 12 }, - padding: 4, - corner_radius: 4, + background: background(theme.highest), + margin: { left: 12, right: 4, top: 12 }, + padding: { right: 4, left: 4, top: 1, bottom: 1 }, + corner_radius: 6, ...text(theme.highest, "sans", "default", { size: "xs" }), }, state: { @@ -236,20 +168,9 @@ export default function assistant(theme: ColorScheme): any { }, }, }), - remaining_tokens: { - background: background(theme.highest, "on"), - margin: { top: 12, right: 24 }, - padding: 4, - corner_radius: 4, - ...text(theme.highest, "sans", "positive", { size: "xs" }), - }, - no_remaining_tokens: { - background: background(theme.highest, "on"), - margin: { top: 12, right: 24 }, - padding: 4, - corner_radius: 4, - ...text(theme.highest, "sans", "negative", { size: "xs" }), - }, + remaining_tokens: tokens_remaining("positive"), + low_remaining_tokens: tokens_remaining("warning"), + no_remaining_tokens: tokens_remaining("negative"), error_icon: { margin: { left: 8 }, color: foreground(theme.highest, "negative"), From d6112e4a594ad64578d663547032ab3161d4304d Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 29 Jun 2023 17:32:19 -0400 Subject: [PATCH 2/7] Add doc comments for ColorScheme layer properties --- styles/src/theme/color_scheme.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/styles/src/theme/color_scheme.ts b/styles/src/theme/color_scheme.ts index 933c616053..c64be95184 100644 --- a/styles/src/theme/color_scheme.ts +++ b/styles/src/theme/color_scheme.ts @@ -12,8 +12,17 @@ export interface ColorScheme { name: string is_light: boolean + /** + * App background, other elements that should sit directly on top of the background. + */ lowest: Layer + /** + * Panels, tabs, other UI surfaces that sit on top of the background. + */ middle: Layer + /** + * Editors like code buffers, conversation editors, etc. + */ highest: Layer ramps: RampSet From 77b120323b9deb05d40904aaab26ccfc6342409f Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 29 Jun 2023 17:44:47 -0400 Subject: [PATCH 3/7] Add `low_tokens_remaining` case to the assistant --- crates/ai/src/assistant.rs | 2 ++ crates/theme/src/theme.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/crates/ai/src/assistant.rs b/crates/ai/src/assistant.rs index 9ca54e661a..6375c2fe4d 100644 --- a/crates/ai/src/assistant.rs +++ b/crates/ai/src/assistant.rs @@ -2060,6 +2060,8 @@ impl ConversationEditor { let remaining_tokens = self.conversation.read(cx).remaining_tokens()?; let remaining_tokens_style = if remaining_tokens <= 0 { &style.no_remaining_tokens + } else if remaining_tokens <= 500 { + &style.low_remaining_tokens } else { &style.remaining_tokens }; diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index e54dcdfd1e..01da555e1e 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -1027,6 +1027,7 @@ pub struct AssistantStyle { pub system_sender: Interactive, pub model: Interactive, pub remaining_tokens: ContainedText, + pub low_remaining_tokens: ContainedText, pub no_remaining_tokens: ContainedText, pub error_icon: Icon, pub api_key_editor: FieldEditor, From 530561e4ebb6db420f5759cc23ab48f5bf33a29b Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 29 Jun 2023 18:13:31 -0400 Subject: [PATCH 4/7] Extract assistant tool buttons into `tab_bar_button` --- styles/src/component/tab_bar_button.ts | 55 ++++++++++++++++++++++++++ styles/src/style_tree/assistant.ts | 47 +++++----------------- 2 files changed, 65 insertions(+), 37 deletions(-) create mode 100644 styles/src/component/tab_bar_button.ts diff --git a/styles/src/component/tab_bar_button.ts b/styles/src/component/tab_bar_button.ts new file mode 100644 index 0000000000..2b657e8b37 --- /dev/null +++ b/styles/src/component/tab_bar_button.ts @@ -0,0 +1,55 @@ +import { ColorScheme, StyleSets } from "../common" +import { interactive } from "../element" +import { InteractiveState } from "../element/interactive" +import { background, foreground } from "../style_tree/components" + +interface TabBarButtonOptions { + icon: string + color?: StyleSets +} + +type TabBarButtonProps = TabBarButtonOptions & { + state?: Partial>> +} + +export function tab_bar_button(theme: ColorScheme, { icon, color = "base" }: TabBarButtonProps) { + const button_spacing = 8 + + return ( + interactive({ + base: { + icon: { + color: foreground(theme.middle, color), + asset: icon, + dimensions: { + width: 15, + height: 15, + }, + }, + container: { + corner_radius: 4, + padding: { + top: 4, bottom: 4, left: 4, right: 4 + }, + margin: { + left: button_spacing / 2, + right: button_spacing / 2, + }, + }, + }, + state: { + hovered: { + container: { + background: background(theme.middle, color, "hovered"), + + } + }, + clicked: { + container: { + background: background(theme.middle, color, "pressed"), + } + }, + }, + }) + ) +} diff --git a/styles/src/style_tree/assistant.ts b/styles/src/style_tree/assistant.ts index 1b754b632c..802e4139cb 100644 --- a/styles/src/style_tree/assistant.ts +++ b/styles/src/style_tree/assistant.ts @@ -1,6 +1,7 @@ import { ColorScheme, StyleSets } from "../theme/color_scheme" import { text, border, background, foreground, TextStyle } from "./components" import { Interactive, interactive } from "../element" +import { tab_bar_button } from "../component/tab_bar_button" interface ToolbarButtonOptions { icon: string @@ -23,34 +24,6 @@ type RemainingTokens = TextStyle & { } export default function assistant(theme: ColorScheme): any { - const TOOLBAR_SPACING = 8 - - const toolbar_button = ({ icon }: ToolbarButtonOptions) => { - return ( - interactive({ - base: { - icon: { - color: foreground(theme.highest, "variant"), - asset: icon, - dimensions: { - width: 15, - height: 15, - }, - }, - container: { - padding: { left: TOOLBAR_SPACING, right: TOOLBAR_SPACING }, - }, - }, - state: { - hovered: { - icon: { - color: foreground(theme.highest, "hovered"), - }, - }, - }, - }) - ) - } const interactive_role = (color: StyleSets): Interactive => { return ( @@ -93,26 +66,26 @@ export default function assistant(theme: ColorScheme): any { margin: { bottom: 4, top: 4 }, background: background(theme.highest), }, - hamburger_button: toolbar_button({ + hamburger_button: tab_bar_button(theme, { icon: "icons/hamburger_15.svg", }), - split_button: toolbar_button({ + split_button: tab_bar_button(theme, { icon: "icons/split_message_15.svg", }), - quote_button: toolbar_button({ + quote_button: tab_bar_button(theme, { icon: "icons/radix/quote.svg", }), - assist_button: toolbar_button({ + assist_button: tab_bar_button(theme, { icon: "icons/radix/magic-wand.svg", }), - zoom_in_button: toolbar_button({ + zoom_in_button: tab_bar_button(theme, { icon: "icons/radix/enter-full-screen.svg", }), - zoom_out_button: toolbar_button({ + zoom_out_button: tab_bar_button(theme, { icon: "icons/radix/exit-full-screen.svg", }), - plus_button: toolbar_button({ + plus_button: tab_bar_button(theme, { icon: "icons/radix/plus.svg", }), title: { @@ -158,7 +131,7 @@ export default function assistant(theme: ColorScheme): any { background: background(theme.highest), margin: { left: 12, right: 4, top: 12 }, padding: { right: 4, left: 4, top: 1, bottom: 1 }, - corner_radius: 6, + corner_radius: 4, ...text(theme.highest, "sans", "default", { size: "xs" }), }, state: { @@ -178,7 +151,7 @@ export default function assistant(theme: ColorScheme): any { }, api_key_editor: { background: background(theme.highest, "on"), - corner_radius: 6, + corner_radius: 4, text: text(theme.highest, "mono", "on"), placeholder_text: text(theme.highest, "mono", "on", "disabled", { size: "xs", From f0cddeb478ee26892cd693c105c0ad874aac43be Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 10 Jul 2023 10:09:59 -0400 Subject: [PATCH 5/7] Update zoom icons --- assets/icons/radix/maximize.svg | 4 ++++ assets/icons/radix/minimize.svg | 4 ++++ styles/src/style_tree/assistant.ts | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 assets/icons/radix/maximize.svg create mode 100644 assets/icons/radix/minimize.svg diff --git a/assets/icons/radix/maximize.svg b/assets/icons/radix/maximize.svg new file mode 100644 index 0000000000..f37f6a2087 --- /dev/null +++ b/assets/icons/radix/maximize.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/radix/minimize.svg b/assets/icons/radix/minimize.svg new file mode 100644 index 0000000000..ec78f152e1 --- /dev/null +++ b/assets/icons/radix/minimize.svg @@ -0,0 +1,4 @@ + + + + diff --git a/styles/src/style_tree/assistant.ts b/styles/src/style_tree/assistant.ts index 802e4139cb..3205268f53 100644 --- a/styles/src/style_tree/assistant.ts +++ b/styles/src/style_tree/assistant.ts @@ -80,10 +80,10 @@ export default function assistant(theme: ColorScheme): any { icon: "icons/radix/magic-wand.svg", }), zoom_in_button: tab_bar_button(theme, { - icon: "icons/radix/enter-full-screen.svg", + icon: "icons/radix/maximize.svg", }), zoom_out_button: tab_bar_button(theme, { - icon: "icons/radix/exit-full-screen.svg", + icon: "icons/radix/minimize.svg", }), plus_button: tab_bar_button(theme, { icon: "icons/radix/plus.svg", From 9ffe220def57349e6655e95f1cdbe26bd0bbe153 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 10 Jul 2023 10:24:24 -0400 Subject: [PATCH 6/7] Update tab_bar_button.ts --- styles/src/component/tab_bar_button.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/styles/src/component/tab_bar_button.ts b/styles/src/component/tab_bar_button.ts index 2b657e8b37..0c43e7010e 100644 --- a/styles/src/component/tab_bar_button.ts +++ b/styles/src/component/tab_bar_button.ts @@ -1,4 +1,4 @@ -import { ColorScheme, StyleSets } from "../common" +import { Theme, StyleSets } from "../common" import { interactive } from "../element" import { InteractiveState } from "../element/interactive" import { background, foreground } from "../style_tree/components" @@ -12,7 +12,7 @@ type TabBarButtonProps = TabBarButtonOptions & { state?: Partial>> } -export function tab_bar_button(theme: ColorScheme, { icon, color = "base" }: TabBarButtonProps) { +export function tab_bar_button(theme: Theme, { icon, color = "base" }: TabBarButtonProps) { const button_spacing = 8 return ( From 273b9e1636bd63b6ec0ea113c6562afe05cceb0d Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 10 Jul 2023 10:44:39 -0400 Subject: [PATCH 7/7] Avoid overlapping the scrollbar --- styles/src/style_tree/assistant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/src/style_tree/assistant.ts b/styles/src/style_tree/assistant.ts index adec3dee62..cfc1f8d813 100644 --- a/styles/src/style_tree/assistant.ts +++ b/styles/src/style_tree/assistant.ts @@ -47,7 +47,7 @@ export default function assistant(): any { { ...text(theme.highest, "mono", color, { size: "xs" }), background: background(theme.highest, "on", "default"), - margin: { top: 12, right: 8 }, + margin: { top: 12, right: 20 }, padding: { right: 4, left: 4, top: 1, bottom: 1 }, corner_radius: 6, }