Skip to content

Commit 3b10dd4

Browse files
committed
Edit LLMPopover + dependent components
1 parent 6ea886f commit 3b10dd4

File tree

5 files changed

+71
-95
lines changed

5 files changed

+71
-95
lines changed
Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,20 @@
1-
import { getDisplayNameForModel, LlmDescriptor } from "@/lib/hooks";
1+
import { LlmDescriptor } from "@/lib/hooks";
22
import { parseLlmDescriptor } from "@/lib/llm/utils";
3-
import { useState } from "react";
4-
import { Hoverable } from "@/components/Hoverable";
5-
import { IconType } from "react-icons";
6-
import { FiRefreshCw } from "react-icons/fi";
73
import LLMPopover from "@/app/chat/components/input/LLMPopover";
84

95
export interface RegenerateOptionProps {
106
regenerate: (modelOverRide: LlmDescriptor) => Promise<void>;
117
overriddenModel?: string;
12-
onDropdownVisibleChange: (isVisible: boolean) => void;
138
}
149

1510
export default function RegenerateOption({
1611
regenerate,
1712
overriddenModel,
18-
onDropdownVisibleChange,
1913
}: RegenerateOptionProps) {
20-
const [isOpen, setIsOpen] = useState(false);
21-
const toggleDropdownVisible = (isVisible: boolean) => {
22-
setIsOpen(isVisible);
23-
onDropdownVisibleChange(isVisible);
24-
};
25-
2614
return (
2715
<LLMPopover
2816
requiresImageGeneration={false}
2917
currentModelName={overriddenModel}
30-
trigger={
31-
<div onClick={() => toggleDropdownVisible(!isOpen)}>
32-
{!overriddenModel ? (
33-
<Hoverable size={16} icon={FiRefreshCw as IconType} />
34-
) : (
35-
<Hoverable
36-
size={16}
37-
icon={FiRefreshCw as IconType}
38-
hoverText={getDisplayNameForModel(overriddenModel)}
39-
/>
40-
)}
41-
</div>
42-
}
4318
onSelect={(value) => {
4419
const { name, provider, modelName } = parseLlmDescriptor(
4520
value as string
@@ -50,7 +25,7 @@ export default function RegenerateOption({
5025
modelName: modelName,
5126
});
5227
}}
53-
align="start"
28+
compact
5429
/>
5530
);
5631
}

web/src/app/chat/components/input/ChatInputBar.tsx

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,14 @@ import React, {
77
} from "react";
88
import { FiPlus } from "react-icons/fi";
99
import { FiLoader } from "react-icons/fi";
10-
import { ChatInputOption } from "@/app/chat/components/input/ChatInputOption";
1110
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
1211
import LLMPopover from "@/app/chat/components/input/LLMPopover";
1312
import { InputPrompt } from "@/app/chat/interfaces";
1413

1514
import { FilterManager, LlmManager } from "@/lib/hooks";
1615
import { useChatContext } from "@/components-2/context/ChatContext";
1716
import { ChatFileType } from "@/app/chat/interfaces";
18-
import {
19-
DocumentIcon2,
20-
FileIcon,
21-
FileUploadIcon,
22-
SendIcon,
23-
StopGeneratingIcon,
24-
} from "@/components/icons/icons";
17+
import { DocumentIcon2, FileIcon } from "@/components/icons/icons";
2518
import { OnyxDocument } from "@/lib/search/interfaces";
2619
import { ChatState } from "@/app/chat/interfaces";
2720
import { useAssistantsContext } from "@/components/context/AssistantsContext";
@@ -38,7 +31,6 @@ import { DeepResearchToggle } from "@/app/chat/components/input/DeepResearchTogg
3831
import { ActionToggle } from "@/app/chat/components/input/ActionManagement";
3932
import { SelectedTool } from "@/app/chat/components/input/SelectedTool";
4033
import { IconButton } from "@/components-2/buttons/IconButton";
41-
import SvgFolderPlus from "@/icons/folder-plus";
4234
import SvgHourglass from "@/icons/hourglass";
4335
import SvgPlusCircle from "@/icons/plus-circle";
4436
import SvgSliders from "@/icons/sliders";

web/src/app/chat/components/input/LLMPopover.tsx

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,23 @@ import { FiAlertTriangle } from "react-icons/fi";
2121
import { Slider } from "@/components/ui/slider";
2222
import { useUser } from "@/components/user/UserProvider";
2323
import { TruncatedText } from "@/components/ui/truncatedText";
24-
import { ChatInputOption } from "@/app/chat/components/input/ChatInputOption";
2524
import { useAgentsContext } from "@/components-2/context/AgentsContext";
2625
import { useChatContext } from "@/components-2/context/ChatContext";
26+
import { SelectButton } from "@/components-2/buttons/SelectButton";
27+
import SvgRefreshCw from "@/icons/refresh-cw";
28+
import { IconButton } from "@/components-2/buttons/IconButton";
2729

2830
export interface LLMPopoverProps {
31+
compact?: boolean;
2932
requiresImageGeneration?: boolean;
30-
trigger?: React.ReactElement;
3133
onSelect?: (value: string) => void;
3234
currentModelName?: string;
3335
align?: "start" | "center" | "end";
3436
}
3537

3638
export default function LLMPopover({
39+
compact,
3740
requiresImageGeneration,
38-
trigger,
3941
onSelect,
4042
currentModelName,
4143
align,
@@ -48,7 +50,7 @@ export default function LLMPopover({
4850
currentChat || undefined,
4951
currentAgent || undefined
5052
);
51-
const [isOpen, setIsOpen] = useState(false);
53+
const [open, setOpen] = useState(false);
5254

5355
const [localTemperature, setLocalTemperature] = useState(
5456
llmManager.temperature ?? 0.5
@@ -78,24 +80,21 @@ export default function LLMPopover({
7880

7981
// Memoize trigger content to prevent rerendering
8082
const triggerContent = useMemo(
81-
trigger
82-
? () => trigger
83-
: () => (
84-
<button data-testid="llm-popover-trigger">
85-
<ChatInputOption
86-
minimize
87-
toggle
88-
flexPriority="stiff"
89-
name={getDisplayNameForModel(llmManager.currentLlm.modelName)}
90-
Icon={getProviderIcon(
91-
llmManager.currentLlm.provider,
92-
llmManager.currentLlm.modelName
93-
)}
94-
tooltipContent="Switch models"
95-
/>
96-
</button>
97-
),
98-
[llmManager.currentLlm]
83+
() =>
84+
compact ? (
85+
<IconButton icon={SvgRefreshCw} tertiary active={open} />
86+
) : (
87+
<SelectButton
88+
icon={getProviderIcon(
89+
llmManager.currentLlm.provider,
90+
llmManager.currentLlm.modelName
91+
)}
92+
active={open}
93+
>
94+
{getDisplayNameForModel(llmManager.currentLlm.modelName)}
95+
</SelectButton>
96+
),
97+
[llmManager.currentLlm, open]
9998
);
10099

101100
const llmOptionsToChooseFrom = useMemo(
@@ -121,16 +120,13 @@ export default function LLMPopover({
121120
);
122121

123122
return (
124-
<Popover open={isOpen} onOpenChange={setIsOpen}>
125-
<PopoverTrigger
126-
asChild
127-
className="hover:bg-background-tint-03 rounded-08"
128-
>
129-
{triggerContent}
123+
<Popover open={open} onOpenChange={setOpen}>
124+
<PopoverTrigger asChild>
125+
<div>{triggerContent}</div>
130126
</PopoverTrigger>
131127
<PopoverContent
132128
side="top"
133-
align={align || "end"}
129+
align="center"
134130
className="w-64 p-1 bg-background-tint-01 border shadow-lg flex flex-col"
135131
>
136132
<div className="flex-grow max-h-[300px] default-scrollbar overflow-y-auto">
@@ -151,7 +147,7 @@ export default function LLMPopover({
151147
name,
152148
} as LlmDescriptor);
153149
onSelect?.(structureValue(name, provider, modelName));
154-
setIsOpen(false);
150+
setOpen(false);
155151
}}
156152
>
157153
{icon({
Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,17 @@
11
"use client";
22

3-
import React, { useState } from "react";
3+
import React from "react";
44
import { SvgProps } from "@/icons";
5-
import SvgArrowUp from "@/icons/arrow-up";
6-
import {
7-
Tooltip,
8-
TooltipContent,
9-
TooltipTrigger,
10-
} from "@/components/ui/tooltip";
115
import { cn } from "@/lib/utils";
126
import Truncated from "@/components-2/Truncated";
137
import SvgChevronDownSmall from "@/icons/chevron-down-small";
148

15-
const textClasses = (active: boolean | undefined) =>
16-
({
17-
primary: {
18-
main: ["text-text-04", "stroke-text-04"],
19-
disabled: ["text-text-02", "stroke-text-02"],
20-
},
21-
}) as const;
9+
const textClasses = {
10+
primary: {
11+
main: ["text-text-04", "stroke-text-04"],
12+
disabled: ["text-text-02", "stroke-text-02"],
13+
},
14+
} as const;
2215

2316
export interface SelectButtonProps {
2417
// Button states:
@@ -54,38 +47,40 @@ export function SelectButton({
5447
return (
5548
<button
5649
className={cn(
57-
"flex flex-row justify-center items-center p-spacing-interline gap-spacing-inline rounded-08 hover:bg-background-tint-02 h-[2rem]",
50+
"flex flex-row justify-center items-center p-spacing-interline gap-spacing-inline hover:bg-background-tint-02 rounded-08 h-[2rem] max-w-[10rem] w-full overflow-hidden",
5851
folded ? "w-min" : "w-full",
5952
active ? "bg-background-tint-00" : "bg-transparent",
6053
disabled && "opacity-50 cursor-not-allowed",
6154
className
6255
)}
6356
onClick={disabled ? undefined : onClick}
6457
>
65-
<Icon className={cn(textClasses(active)[variant][state])} />
66-
<div className="flex flex-row justify-center items-center">
67-
{!folded &&
68-
(typeof children === "string" ? (
58+
<div className="w-[1rem] h-[1rem] flex flex-col justify-center items-center">
59+
<Icon className={cn("w-full h-full", textClasses[variant][state])} />
60+
</div>
61+
{!folded && (
62+
<div className="flex flex-row justify-center items-center">
63+
{typeof children === "string" ? (
6964
<Truncated
7065
side="right"
7166
offset={40}
72-
className={cn("text-left", textClasses(active)[variant][state])}
67+
className={cn("text-left", textClasses[variant][state])}
7368
mainAction
74-
disable
7569
>
7670
{children}
7771
</Truncated>
7872
) : (
7973
children
80-
))}
81-
<SvgChevronDownSmall
82-
className={cn(
83-
"h-[1.5rem] w-[1.5rem] transition-transform duration-200 ease-in-out",
84-
textClasses(active)[variant][state],
85-
active && "-rotate-180"
8674
)}
87-
/>
88-
</div>
75+
<SvgChevronDownSmall
76+
className={cn(
77+
"h-[1.5rem] w-[1.5rem] transition-transform duration-200",
78+
textClasses[variant][state],
79+
active && "-rotate-180"
80+
)}
81+
/>
82+
</div>
83+
)}
8984
</button>
9085
);
9186
}

web/src/icons/refresh-cw.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import * as React from "react";
2+
import type { SVGProps } from "react";
3+
const SvgRefreshCw = (props: SVGProps<SVGSVGElement>) => (
4+
<svg
5+
viewBox="0 0 16 16"
6+
fill="none"
7+
xmlns="http://www.w3.org/2000/svg"
8+
{...props}
9+
>
10+
<path
11+
d="M14.448 3.10983V6.77746M14.448 6.77746H10.7803M14.448 6.77746L11.6117 4.11231C10.9547 3.45502 10.142 2.97486 9.24923 2.71664C8.35651 2.45842 7.41292 2.43055 6.50651 2.63564C5.6001 2.84072 4.76042 3.27208 4.06581 3.88945C3.3712 4.50683 2.84431 5.2901 2.53429 6.16618M1 12.8902V9.22254M1 9.22254H4.66763M1 9.22254L3.8363 11.8877C4.49326 12.545 5.30603 13.0251 6.19875 13.2834C7.09147 13.5416 8.03506 13.5694 8.94147 13.3644C9.84787 13.1593 10.6876 12.7279 11.3822 12.1105C12.0768 11.4932 12.6037 10.7099 12.9137 9.83381"
12+
strokeWidth={1.5}
13+
strokeLinecap="round"
14+
strokeLinejoin="round"
15+
/>
16+
</svg>
17+
);
18+
export default SvgRefreshCw;

0 commit comments

Comments
 (0)