diff --git a/web/src/app/admin/models/llm/LLMProviderUpdateForm.tsx b/web/src/app/admin/models/llm/LLMProviderUpdateForm.tsx
index a9ddb8e4dee..9b9b55d0187 100644
--- a/web/src/app/admin/models/llm/LLMProviderUpdateForm.tsx
+++ b/web/src/app/admin/models/llm/LLMProviderUpdateForm.tsx
@@ -222,7 +222,6 @@ export function LLMProviderUpdateForm({
name,
value: name,
}))}
- direction="up"
maxHeight="max-h-56"
/>
) : (
@@ -246,7 +245,6 @@ export function LLMProviderUpdateForm({
value: name,
}))}
includeDefault
- direction="up"
maxHeight="max-h-56"
/>
) : (
diff --git a/web/src/app/admin/settings/SettingsForm.tsx b/web/src/app/admin/settings/SettingsForm.tsx
index 3be9e3cb7be..761eef0601a 100644
--- a/web/src/app/admin/settings/SettingsForm.tsx
+++ b/web/src/app/admin/settings/SettingsForm.tsx
@@ -51,7 +51,7 @@ function Selector({
{label && }
{subtext && {subtext}}
-
+
{
+ const llmAcceptsImages = checkLLMSupportsImageInput(
+ ...getFinalLLM(llmProviders, livePersona)
+ );
+ if (!llmAcceptsImages) {
+ setPopup({
+ type: "error",
+ message:
+ "The current Assistant does not support image input. Please select an assistant with Vision support.",
+ });
+ return;
+ }
+
uploadFilesForChat(acceptedFiles).then(([fileIds, error]) => {
if (error) {
setPopup({
@@ -690,11 +702,6 @@ export function ChatPage({
});
}}
noClick
- disabled={
- !checkLLMSupportsImageInput(
- ...getFinalLLM(llmProviders, livePersona)
- )
- }
onDragLeave={() => console.log("buh")}
onDragEnter={() => console.log("floppa")}
>
diff --git a/web/src/app/chat/sessionSidebar/AssistantsTab.tsx b/web/src/app/chat/sessionSidebar/AssistantsTab.tsx
index 83d4a34f49f..404491961da 100644
--- a/web/src/app/chat/sessionSidebar/AssistantsTab.tsx
+++ b/web/src/app/chat/sessionSidebar/AssistantsTab.tsx
@@ -3,6 +3,7 @@ import { BasicSelectable } from "@/components/BasicClickable";
import { User } from "@/lib/types";
import { Text } from "@tremor/react";
import Link from "next/link";
+import { FaRobot } from "react-icons/fa";
import { FiEdit } from "react-icons/fi";
function AssistantDisplay({
@@ -24,7 +25,9 @@ function AssistantDisplay({
onSelect(persona)}>
-
{persona.name}
+
+ {persona.name}
+
@@ -54,7 +57,7 @@ export function AssistantsTab({
const globalAssistants = personas.filter((persona) => persona.is_public);
const personalAssistants = personas.filter(
(persona) =>
- !user || (persona.users.includes(user.id) && !persona.is_public)
+ (!user || persona.users.includes(user.id)) && !persona.is_public
);
return (
diff --git a/web/src/app/chat/sessionSidebar/SessionDisplay.tsx b/web/src/app/chat/sessionSidebar/SessionDisplay.tsx
index a5070f58a73..1714bd8ce00 100644
--- a/web/src/app/chat/sessionSidebar/SessionDisplay.tsx
+++ b/web/src/app/chat/sessionSidebar/SessionDisplay.tsx
@@ -156,6 +156,7 @@ export function ChatSessionDisplay({
/>
}
+ requiresContentPadding
/>
diff --git a/web/src/components/Dropdown.tsx b/web/src/components/Dropdown.tsx
index 9b42ec56b3a..b88fe8693c5 100644
--- a/web/src/components/Dropdown.tsx
+++ b/web/src/components/Dropdown.tsx
@@ -286,78 +286,91 @@ export function DefaultDropdown({
selected,
onSelect,
includeDefault = false,
- direction = "down",
+ side,
maxHeight,
}: {
options: StringOrNumberOption[];
selected: string | null;
onSelect: (value: string | number | null) => void;
includeDefault?: boolean;
- direction?: "up" | "down";
+ side?: "top" | "right" | "bottom" | "left";
maxHeight?: string;
}) {
const selectedOption = options.find((option) => option.value === selected);
+ const [isOpen, setIsOpen] = useState(false);
+
+ const Content = (
+
+
+ {selectedOption?.name ||
+ (includeDefault ? "Default" : "Select an option...")}
+
+
+
+ );
+
+ const Dropdown = (
+
+ {includeDefault && (
+ {
+ onSelect(null);
+ }}
+ isSelected={selected === null}
+ />
+ )}
+ {options.map((option, ind) => {
+ const isSelected = option.value === selected;
+ return (
+ onSelect(option.value)}
+ isSelected={isSelected}
+ />
+ );
+ })}
+
+ );
return (
-
- {includeDefault && (
- {
- onSelect(null);
- }}
- isSelected={selected === null}
- />
- )}
- {options.map((option, ind) => {
- const isSelected = option.value === selected;
- return (
- onSelect(option.value)}
- isSelected={isSelected}
- />
- );
- })}
-
- }
- >
-
-
- {selectedOption?.name ||
- (includeDefault ? "Default" : "Select an option...")}
-
-
-
-
+ setIsOpen(!isOpen)}>
+
setIsOpen(open)}
+ content={Content}
+ popover={Dropdown}
+ align="start"
+ side={side}
+ sideOffset={5}
+ matchWidth
+ />
+
);
}
diff --git a/web/src/components/admin/connectors/Field.tsx b/web/src/components/admin/connectors/Field.tsx
index 825dc3ad811..39d280efd91 100644
--- a/web/src/components/admin/connectors/Field.tsx
+++ b/web/src/components/admin/connectors/Field.tsx
@@ -233,7 +233,7 @@ interface SelectorFormFieldProps {
options: StringOrNumberOption[];
subtext?: string | JSX.Element;
includeDefault?: boolean;
- direction?: "up" | "down";
+ side?: "top" | "right" | "bottom" | "left";
maxHeight?: string;
onSelect?: (selected: string | number | null) => void;
}
@@ -244,7 +244,7 @@ export function SelectorFormField({
options,
subtext,
includeDefault = false,
- direction = "down",
+ side = "bottom",
maxHeight,
onSelect,
}: SelectorFormFieldProps) {
@@ -262,7 +262,7 @@ export function SelectorFormField({
selected={field.value}
onSelect={onSelect || ((selected) => setFieldValue(name, selected))}
includeDefault={includeDefault}
- direction={direction}
+ side={side}
maxHeight={maxHeight}
/>
diff --git a/web/src/components/popover/Popover.tsx b/web/src/components/popover/Popover.tsx
index ac5d5bcf2a5..22ae839c977 100644
--- a/web/src/components/popover/Popover.tsx
+++ b/web/src/components/popover/Popover.tsx
@@ -1,5 +1,7 @@
"use client";
+import "./styles.css";
+
import * as RadixPopover from "@radix-ui/react-popover";
export function Popover({
@@ -7,11 +9,21 @@ export function Popover({
onOpenChange,
content,
popover,
+ side,
+ align,
+ sideOffset,
+ matchWidth,
+ requiresContentPadding,
}: {
open: boolean;
onOpenChange: (open: boolean) => void;
content: JSX.Element;
popover: JSX.Element;
+ side?: "top" | "right" | "bottom" | "left";
+ align?: "start" | "center" | "end";
+ sideOffset?: number;
+ matchWidth?: boolean;
+ requiresContentPadding?: boolean;
}) {
/*
This Popover is needed when we want to put a popup / dropdown in a component
@@ -24,14 +36,30 @@ export function Popover({
return (
-
+
{/* NOTE: this weird `-mb-1.5` is needed to offset the Anchor, otherwise
the content will shift up by 1.5px when the Popover is open. */}
- {open ? {content}
: content}
+ {open ? (
+
+ {content}
+
+ ) : (
+ content
+ )}
-
- {popover}
+
+ {popover}
+
);
diff --git a/web/src/components/popover/styles.css b/web/src/components/popover/styles.css
new file mode 100644
index 00000000000..f35957ba847
--- /dev/null
+++ b/web/src/components/popover/styles.css
@@ -0,0 +1,9 @@
+/* styles.css */
+
+.PopoverContentMatchWidth {
+ width: var(--radix-popover-trigger-width);
+}
+
+.PopoverContent[data-side="top"] {
+ transform: translateY(var(--radix-popover-trigger-height) px);
+}