assistant.ts

  1import { ColorScheme, StyleSets } from "../theme/color_scheme"
  2import { text, border, background, foreground, TextStyle } from "./components"
  3import { Interactive, interactive } from "../element"
  4import { tab_bar_button } from "../component/tab_bar_button"
  5
  6interface ToolbarButtonOptions {
  7    icon: string
  8}
  9
 10type RoleCycleButton = TextStyle & {
 11    background?: string
 12}
 13// TODO: Replace these with zed types
 14type RemainingTokens = TextStyle & {
 15    background: string,
 16    margin: { top: number, right: number },
 17    padding: {
 18        right: number,
 19        left: number,
 20        top: number,
 21        bottom: number,
 22    },
 23    corner_radius: number,
 24}
 25
 26export default function assistant(theme: ColorScheme): any {
 27
 28    const interactive_role = (color: StyleSets): Interactive<RoleCycleButton> => {
 29        return (
 30            interactive({
 31                base: {
 32                    ...text(theme.highest, "sans", color, { size: "sm" }),
 33                },
 34                state: {
 35                    hovered: {
 36                        ...text(theme.highest, "sans", color, { size: "sm" }),
 37                        background: background(theme.highest, color, "hovered"),
 38                    },
 39                    clicked: {
 40                        ...text(theme.highest, "sans", color, { size: "sm" }),
 41                        background: background(theme.highest, color, "pressed"),
 42                    }
 43                },
 44            })
 45        )
 46    }
 47
 48    const tokens_remaining = (color: StyleSets): RemainingTokens => {
 49        return (
 50            {
 51                ...text(theme.highest, "mono", color, { size: "xs" }),
 52                background: background(theme.highest, "on", "default"),
 53                margin: { top: 12, right: 8 },
 54                padding: { right: 4, left: 4, top: 1, bottom: 1 },
 55                corner_radius: 6,
 56            }
 57        )
 58    }
 59
 60    return {
 61        container: {
 62            background: background(theme.highest),
 63            padding: { left: 12 },
 64        },
 65        message_header: {
 66            margin: { bottom: 4, top: 4 },
 67            background: background(theme.highest),
 68        },
 69        hamburger_button: tab_bar_button(theme, {
 70            icon: "icons/hamburger_15.svg",
 71        }),
 72
 73        split_button: tab_bar_button(theme, {
 74            icon: "icons/split_message_15.svg",
 75        }),
 76        quote_button: tab_bar_button(theme, {
 77            icon: "icons/radix/quote.svg",
 78        }),
 79        assist_button: tab_bar_button(theme, {
 80            icon: "icons/radix/magic-wand.svg",
 81        }),
 82        zoom_in_button: tab_bar_button(theme, {
 83            icon: "icons/radix/maximize.svg",
 84        }),
 85        zoom_out_button: tab_bar_button(theme, {
 86            icon: "icons/radix/minimize.svg",
 87        }),
 88        plus_button: tab_bar_button(theme, {
 89            icon: "icons/radix/plus.svg",
 90        }),
 91        title: {
 92            ...text(theme.highest, "sans", "default", { size: "xs" }),
 93        },
 94        saved_conversation: {
 95            container: interactive({
 96                base: {
 97                    background: background(theme.middle),
 98                    padding: { top: 4, bottom: 4 },
 99                    border: border(theme.middle, "default", { top: true, overlay: true }),
100                },
101                state: {
102                    hovered: {
103                        background: background(theme.middle, "hovered"),
104                    },
105                    clicked: {
106                        background: background(theme.middle, "pressed"),
107                    }
108                },
109            }),
110            saved_at: {
111                margin: { left: 8 },
112                ...text(theme.highest, "sans", "variant", { size: "xs" }),
113            },
114            title: {
115                margin: { left: 12 },
116                ...text(theme.highest, "sans", "default", {
117                    size: "sm",
118                    weight: "bold",
119                }),
120            },
121        },
122        user_sender: interactive_role("base"),
123        assistant_sender: interactive_role("accent"),
124        system_sender: interactive_role("warning"),
125        sent_at: {
126            margin: { top: 2, left: 8 },
127            ...text(theme.highest, "sans", "variant", { size: "2xs" }),
128        },
129        model: interactive({
130            base: {
131                background: background(theme.highest),
132                margin: { left: 12, right: 4, top: 12 },
133                padding: { right: 4, left: 4, top: 1, bottom: 1 },
134                corner_radius: 4,
135                ...text(theme.highest, "sans", "default", { size: "xs" }),
136            },
137            state: {
138                hovered: {
139                    background: background(theme.highest, "on", "hovered"),
140                    border: border(theme.highest, "on", { overlay: true }),
141                },
142            },
143        }),
144        remaining_tokens: tokens_remaining("positive"),
145        low_remaining_tokens: tokens_remaining("warning"),
146        no_remaining_tokens: tokens_remaining("negative"),
147        error_icon: {
148            margin: { left: 8 },
149            color: foreground(theme.highest, "negative"),
150            width: 12,
151        },
152        api_key_editor: {
153            background: background(theme.highest, "on"),
154            corner_radius: 4,
155            text: text(theme.highest, "mono", "on"),
156            placeholder_text: text(theme.highest, "mono", "on", "disabled", {
157                size: "xs",
158            }),
159            selection: theme.players[0],
160            border: border(theme.highest, "on"),
161            padding: {
162                bottom: 4,
163                left: 8,
164                right: 8,
165                top: 4,
166            },
167        },
168        api_key_prompt: {
169            padding: 10,
170            ...text(theme.highest, "sans", "default", { size: "xs" }),
171        },
172    }
173}