1import { text, border, background, foreground, TextStyle } from "./components"
2import { Interactive, interactive, toggleable } from "../element"
3import { tab_bar_button } from "../component/tab_bar_button"
4import { StyleSets, useTheme } from "../theme"
5
6type RoleCycleButton = TextStyle & {
7 background?: string
8}
9// TODO: Replace these with zed types
10type RemainingTokens = TextStyle & {
11 background: string
12 margin: { top: number; right: number }
13 padding: {
14 right: number
15 left: number
16 top: number
17 bottom: number
18 }
19 corner_radius: number
20}
21
22export default function assistant(): any {
23 const theme = useTheme()
24
25 const interactive_role = (
26 color: StyleSets,
27 ): Interactive<RoleCycleButton> => {
28 return interactive({
29 base: {
30 ...text(theme.highest, "sans", color, { size: "sm" }),
31 },
32 state: {
33 hovered: {
34 ...text(theme.highest, "sans", color, { size: "sm" }),
35 background: background(theme.highest, color, "hovered"),
36 },
37 clicked: {
38 ...text(theme.highest, "sans", color, { size: "sm" }),
39 background: background(theme.highest, color, "pressed"),
40 },
41 },
42 })
43 }
44
45 const tokens_remaining = (color: StyleSets): RemainingTokens => {
46 return {
47 ...text(theme.highest, "mono", color, { size: "xs" }),
48 background: background(theme.highest, "on", "default"),
49 margin: { top: 12, right: 20 },
50 padding: { right: 4, left: 4, top: 1, bottom: 1 },
51 corner_radius: 6,
52 }
53 }
54
55 return {
56 container: {
57 background: background(theme.highest),
58 padding: { left: 12 },
59 },
60 inline: {
61 background: background(theme.highest),
62 margin: { top: 3, bottom: 3 },
63 border: border(theme.lowest, "on", {
64 top: true,
65 bottom: true,
66 overlay: true,
67 }),
68 editor: {
69 text: text(theme.highest, "mono", "default", { size: "sm" }),
70 placeholder_text: text(theme.highest, "sans", "on", "disabled"),
71 selection: theme.players[0],
72 },
73 disabled_editor: {
74 text: text(theme.highest, "mono", "disabled", { size: "sm" }),
75 placeholder_text: text(theme.highest, "sans", "on", "disabled"),
76 selection: {
77 cursor: text(theme.highest, "mono", "disabled").color,
78 selection: theme.players[0].selection,
79 },
80 },
81 pending_edit_background: background(theme.highest, "positive"),
82 context_status: {
83 error_icon: {
84 margin: { left: 8, right: 18 },
85 color: foreground(theme.highest, "negative"),
86 width: 12,
87 },
88 in_progress_icon: {
89 margin: { left: 8, right: 18 },
90 color: foreground(theme.highest, "positive"),
91 width: 12,
92 },
93 complete_icon: {
94 margin: { left: 8, right: 18 },
95 color: foreground(theme.highest, "positive"),
96 width: 12,
97 },
98 },
99 retrieve_context: toggleable({
100 base: interactive({
101 base: {
102 icon_size: 12,
103 color: foreground(theme.highest, "variant"),
104
105 button_width: 12,
106 background: background(theme.highest, "on"),
107 corner_radius: 2,
108 border: {
109 width: 1,
110 color: background(theme.highest, "on"),
111 },
112 margin: { left: 2 },
113 padding: {
114 left: 4,
115 right: 4,
116 top: 4,
117 bottom: 4,
118 },
119 },
120 state: {
121 hovered: {
122 ...text(
123 theme.highest,
124 "mono",
125 "variant",
126 "hovered",
127 ),
128 background: background(
129 theme.highest,
130 "on",
131 "hovered",
132 ),
133 border: {
134 width: 1,
135 color: background(
136 theme.highest,
137 "on",
138 "hovered",
139 ),
140 },
141 },
142 clicked: {
143 ...text(
144 theme.highest,
145 "mono",
146 "variant",
147 "pressed",
148 ),
149 background: background(
150 theme.highest,
151 "on",
152 "pressed",
153 ),
154 border: {
155 width: 1,
156 color: background(
157 theme.highest,
158 "on",
159 "pressed",
160 ),
161 },
162 },
163 },
164 }),
165 state: {
166 active: {
167 default: {
168 icon_size: 12,
169 button_width: 12,
170 color: foreground(theme.highest, "variant"),
171 background: background(theme.highest, "accent"),
172 border: border(theme.highest, "accent"),
173 },
174 hovered: {
175 background: background(
176 theme.highest,
177 "accent",
178 "hovered",
179 ),
180 border: border(theme.highest, "accent", "hovered"),
181 },
182 clicked: {
183 background: background(
184 theme.highest,
185 "accent",
186 "pressed",
187 ),
188 border: border(theme.highest, "accent", "pressed"),
189 },
190 },
191 },
192 }),
193 include_conversation: toggleable({
194 base: interactive({
195 base: {
196 icon_size: 12,
197 color: foreground(theme.highest, "variant"),
198
199 button_width: 12,
200 background: background(theme.highest, "on"),
201 corner_radius: 2,
202 border: {
203 width: 1,
204 color: background(theme.highest, "on"),
205 },
206 padding: {
207 left: 4,
208 right: 4,
209 top: 4,
210 bottom: 4,
211 },
212 },
213 state: {
214 hovered: {
215 ...text(
216 theme.highest,
217 "mono",
218 "variant",
219 "hovered",
220 ),
221 background: background(
222 theme.highest,
223 "on",
224 "hovered",
225 ),
226 border: {
227 width: 1,
228 color: background(
229 theme.highest,
230 "on",
231 "hovered",
232 ),
233 },
234 },
235 clicked: {
236 ...text(
237 theme.highest,
238 "mono",
239 "variant",
240 "pressed",
241 ),
242 background: background(
243 theme.highest,
244 "on",
245 "pressed",
246 ),
247 border: {
248 width: 1,
249 color: background(
250 theme.highest,
251 "on",
252 "pressed",
253 ),
254 },
255 },
256 },
257 }),
258 state: {
259 active: {
260 default: {
261 icon_size: 12,
262 button_width: 12,
263 color: foreground(theme.highest, "variant"),
264 background: background(theme.highest, "accent"),
265 border: border(theme.highest, "accent"),
266 },
267 hovered: {
268 background: background(
269 theme.highest,
270 "accent",
271 "hovered",
272 ),
273 border: border(theme.highest, "accent", "hovered"),
274 },
275 clicked: {
276 background: background(
277 theme.highest,
278 "accent",
279 "pressed",
280 ),
281 border: border(theme.highest, "accent", "pressed"),
282 },
283 },
284 },
285 }),
286 },
287 message_header: {
288 margin: { bottom: 4, top: 4 },
289 background: background(theme.highest),
290 },
291 hamburger_button: tab_bar_button(theme, {
292 icon: "icons/menu.svg",
293 }),
294
295 split_button: tab_bar_button(theme, {
296 icon: "icons/split_message.svg",
297 }),
298 quote_button: tab_bar_button(theme, {
299 icon: "icons/quote.svg",
300 }),
301 assist_button: tab_bar_button(theme, {
302 icon: "icons/magic-wand.svg",
303 }),
304 zoom_in_button: tab_bar_button(theme, {
305 icon: "icons/maximize.svg",
306 }),
307 zoom_out_button: tab_bar_button(theme, {
308 icon: "icons/minimize.svg",
309 }),
310 plus_button: tab_bar_button(theme, {
311 icon: "icons/plus.svg",
312 }),
313 title: {
314 ...text(theme.highest, "sans", "default", { size: "xs" }),
315 },
316 saved_conversation: {
317 container: interactive({
318 base: {
319 background: background(theme.middle),
320 padding: { top: 4, bottom: 4 },
321 border: border(theme.middle, "default", {
322 top: true,
323 overlay: true,
324 }),
325 },
326 state: {
327 hovered: {
328 background: background(theme.middle, "hovered"),
329 },
330 clicked: {
331 background: background(theme.middle, "pressed"),
332 },
333 },
334 }),
335 saved_at: {
336 margin: { left: 8 },
337 ...text(theme.highest, "sans", "variant", { size: "xs" }),
338 },
339 title: {
340 margin: { left: 12 },
341 ...text(theme.highest, "sans", "default", {
342 size: "sm",
343 weight: "bold",
344 }),
345 },
346 },
347 user_sender: interactive_role("base"),
348 assistant_sender: interactive_role("accent"),
349 system_sender: interactive_role("warning"),
350 sent_at: {
351 margin: { top: 2, left: 8 },
352 ...text(theme.highest, "sans", "variant", { size: "2xs" }),
353 },
354 model: interactive({
355 base: {
356 background: background(theme.highest),
357 margin: { left: 12, right: 4, top: 12 },
358 padding: { right: 4, left: 4, top: 1, bottom: 1 },
359 corner_radius: 4,
360 ...text(theme.highest, "sans", "default", { size: "xs" }),
361 },
362 state: {
363 hovered: {
364 background: background(theme.highest, "on", "hovered"),
365 border: border(theme.highest, "on", { overlay: true }),
366 },
367 },
368 }),
369 remaining_tokens: tokens_remaining("positive"),
370 low_remaining_tokens: tokens_remaining("warning"),
371 no_remaining_tokens: tokens_remaining("negative"),
372 error_icon: {
373 margin: { left: 8 },
374 color: foreground(theme.highest, "negative"),
375 width: 12,
376 },
377 api_key_editor: {
378 background: background(theme.highest, "on"),
379 corner_radius: 4,
380 text: text(theme.highest, "mono", "on"),
381 placeholder_text: text(theme.highest, "mono", "on", "disabled", {
382 size: "xs",
383 }),
384 selection: theme.players[0],
385 border: border(theme.highest, "on"),
386 padding: {
387 bottom: 4,
388 left: 8,
389 right: 8,
390 top: 4,
391 },
392 },
393 api_key_prompt: {
394 padding: 10,
395 ...text(theme.highest, "sans", "default", { size: "xs" }),
396 },
397 }
398}