diff --git a/frontend/agents/AgentCardListButton.js b/frontend/agents/AgentCardListButton.js index db1aadb0..9b169a0d 100644 --- a/frontend/agents/AgentCardListButton.js +++ b/frontend/agents/AgentCardListButton.js @@ -1,14 +1,12 @@ import React from "react"; -import { Box, IconButton, SimpleGrid } from "@chakra-ui/react"; +import { Box, SimpleGrid } from "@chakra-ui/react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faAddressBook } from "@fortawesome/free-solid-svg-icons"; import { ModalTrigger } from "components/Modal"; import { usePaginatedAPI } from "utils/hooks/usePaginatedAPI"; -import { - useEditorColorMode, - useSideBarColorMode, -} from "chains/editor/useColorMode"; +import { useEditorColorMode } from "chains/editor/useColorMode"; +import { MenuItem } from "site/MenuItem"; const AgentCardList = ({ agents, Card }) => { const { scrollbar } = useEditorColorMode(); @@ -34,7 +32,6 @@ const AgentCardList = ({ agents, Card }) => { }; export const AgentCardListButton = ({ Card }) => { - const style = useSideBarColorMode(); const { page, load } = usePaginatedAPI("/api/agents/", { limit: 1000, load: false, @@ -42,11 +39,9 @@ export const AgentCardListButton = ({ Card }) => { return ( - } - title={"add/remove assistants"} - {...style.button} - /> + + + diff --git a/frontend/agents/NewAgentButton.js b/frontend/agents/NewAgentButton.js index 72b1fd56..c004f2b2 100644 --- a/frontend/agents/NewAgentButton.js +++ b/frontend/agents/NewAgentButton.js @@ -1,24 +1,18 @@ import React from "react"; import { Link } from "react-router-dom"; -import { IconButton } from "@chakra-ui/react"; -import { useColorMode } from "@chakra-ui/color-mode"; +import { Tooltip } from "@chakra-ui/react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faDiagramProject } from "@fortawesome/free-solid-svg-icons"; +import { MenuItem } from "site/MenuItem"; export const NewAgentButton = () => { - const { colorMode } = useColorMode(); - return ( - - } - title={"New Agent or Chain"} - > - New Agent - - + + + + + + + ); }; diff --git a/frontend/chains/ChainCardListButton.js b/frontend/chains/ChainCardListButton.js index 4ff319d8..4ee95fe5 100644 --- a/frontend/chains/ChainCardListButton.js +++ b/frontend/chains/ChainCardListButton.js @@ -1,5 +1,5 @@ import React from "react"; -import { Box, IconButton, SimpleGrid } from "@chakra-ui/react"; +import { Box, SimpleGrid } from "@chakra-ui/react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faChain } from "@fortawesome/free-solid-svg-icons"; @@ -10,6 +10,7 @@ import { useSideBarColorMode, } from "chains/editor/useColorMode"; import ChainCard from "chains/ChainCard"; +import { MenuItem } from "site/MenuItem"; const ChainCardList = ({ chains, Card }) => { const { scrollbar } = useEditorColorMode(); @@ -40,11 +41,9 @@ export const ChainCardListButton = ({ Card }) => { return ( - } - title={"Chains"} - {...style.button} - /> + + + diff --git a/frontend/chains/ChainEditorView.js b/frontend/chains/ChainEditorView.js index 413c94bf..626ee407 100644 --- a/frontend/chains/ChainEditorView.js +++ b/frontend/chains/ChainEditorView.js @@ -1,12 +1,6 @@ import React, { useCallback, useEffect } from "react"; import { useParams } from "react-router-dom"; -import { - HStack, - Spinner, - useDisclosure, - useToast, - VStack, -} from "@chakra-ui/react"; +import { HStack, Spinner, useToast, VStack } from "@chakra-ui/react"; import { ReactFlowProvider, useReactFlow } from "reactflow"; import { Layout, LayoutContent, LayoutLeftPane } from "site/Layout"; diff --git a/frontend/chains/editor/NodeTypeSearch.js b/frontend/chains/editor/NodeTypeSearch.js index ca864c41..69a39518 100644 --- a/frontend/chains/editor/NodeTypeSearch.js +++ b/frontend/chains/editor/NodeTypeSearch.js @@ -222,7 +222,7 @@ export const NodeTypeSearch = ({ initialFocusRef }) => { minWidth={170} overflowY={"hidden"} overflowX={"hidden"} - maxHeight={"calc(100vh - 170px)"} + maxHeight={"calc(100vh - 250px)"} > { const { isOpen, onToggle, onClose, onOpen } = useDisclosure(); @@ -35,19 +36,12 @@ export const NodeTypeSearchButton = () => { }, [selectedConnector]); const { colorMode } = useColorMode(); - const style = - colorMode === "light" - ? { - border: "1px solid", - borderColor: "gray.300", - } - : { - border: "1px solid", - borderColor: "whiteAlpha.50", - }; const highlightColor = colorMode === "light" ? "blue.500" : "blue.400"; const color = colorMode === "light" ? "gray.800" : "white"; + const sideBar = useLeftSidebarContext(); + const width = sideBar.size === "icons" ? "25px" : "110px"; + // HAX: Popover must be closedOnBlue=False to allow for connectors to // switch without closing the popover. It proved very difficult to // prevent onClose from detecting that a new connector was selected. @@ -60,12 +54,15 @@ export const NodeTypeSearchButton = () => { initialFocusRef={initialFocusRef} > - } - {...style} + + width={width} + transition="width 0.3s ease-out, max-width 0.3s ease-out" + > + + + + { store: retrieval, default: isLight ? "gray.400" : "gray.700", }, + indicator: { + success: isLight ? "green.600" : "green.400", + error: isLight ? "red.500" : "red.400", + }, scrollbar: isLight ? { "&::-webkit-scrollbar": { @@ -109,6 +113,13 @@ export const useEditorColorMode = () => { background: theme.colors.gray[500], }, }, + badge: isLight + ? { + color: "white", + } + : { + color: "gray.900", + }, input: isLight ? { bg: "gray.50", diff --git a/frontend/chat/buttons/ChatMembersButton.js b/frontend/chat/buttons/ChatMembersButton.js index 3e5e4cd1..8324a0ca 100644 --- a/frontend/chat/buttons/ChatMembersButton.js +++ b/frontend/chat/buttons/ChatMembersButton.js @@ -1,71 +1,31 @@ import React from "react"; -import { - IconButton, - Popover, - PopoverArrow, - PopoverCloseButton, - PopoverContent, - PopoverHeader, - PopoverTrigger, - useDisclosure, -} from "@chakra-ui/react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faUsers } from "@fortawesome/free-solid-svg-icons"; -import { useColorMode } from "@chakra-ui/color-mode"; import SideBarAgentList from "chat/sidebar/SideBarAgentList"; +import { MenuItem } from "site/MenuItem"; +import { + LeftMenuPopover, + LeftSidebarPopupContent, + LeftSidebarPopupHeader, + LeftSidebarPopupIcon, +} from "site/LeftMenuPopover"; export const ChatMembersButton = ({ graph, onUpdateAgents, agentPage }) => { - const { isOpen, onToggle, onClose } = useDisclosure(); - - const { colorMode } = useColorMode(); - const style = - colorMode === "light" - ? { - border: "1px solid", - borderColor: "gray.300", - } - : { - border: "1px solid", - borderColor: "whiteAlpha.50", - }; - const highlightColor = colorMode === "light" ? "blue.500" : "blue.400"; - const color = colorMode === "light" ? "gray.800" : "white"; - return ( - - - } - {...style} - onClick={onToggle} - title={"Chat members"} - /> - - - - Assistants - - - + + + + + + + Assistants + - - + + ); }; diff --git a/frontend/chat/buttons/NewChatButton.js b/frontend/chat/buttons/NewChatButton.js index b60e993d..b01b9530 100644 --- a/frontend/chat/buttons/NewChatButton.js +++ b/frontend/chat/buttons/NewChatButton.js @@ -1,14 +1,10 @@ -import { Button, Icon, IconButton } from "@chakra-ui/react"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faPlus } from "@fortawesome/free-solid-svg-icons"; import React from "react"; import useCreateChat from "chat/hooks/useCreateChat"; -import { useColorMode } from "@chakra-ui/color-mode"; import PlusMessageIcon from "components/PlusMessageIcon"; +import { MenuItem } from "site/MenuItem"; export const NewChatButton = () => { const { createChat } = useCreateChat(); - const { colorMode } = useColorMode(); const handleCreate = async () => { try { await createChat(); @@ -25,12 +21,8 @@ export const NewChatButton = () => { }; return ( - } - title={"New Chat"} - onClick={handleCreate} - /> + + + ); }; diff --git a/frontend/components/ColorModeButton.js b/frontend/components/ColorModeButton.js index 4748ab07..67313f2d 100644 --- a/frontend/components/ColorModeButton.js +++ b/frontend/components/ColorModeButton.js @@ -1,36 +1,18 @@ import React from "react"; import { useColorMode } from "@chakra-ui/color-mode"; -import { Button, IconButton } from "@chakra-ui/react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faMoon } from "@fortawesome/free-solid-svg-icons"; import { faSun } from "@fortawesome/free-regular-svg-icons"; +import { MenuItem } from "site/MenuItem"; export const ColorModeButton = () => { const { colorMode, toggleColorMode } = useColorMode(); - const style = - colorMode === "light" - ? { - text: "Dark Mode", - border: "1px solid", - borderColor: "gray.300", - } - : { - title: "Light Mode", - border: "1px solid", - borderColor: "whiteAlpha.50", - }; const icon = colorMode === "light" ? faMoon : faSun; const title = colorMode === "light" ? "Dark Mode" : "Light Mode"; return ( -
- } - onClick={toggleColorMode} - > - Toggle {colorMode === "light" ? "Dark" : "Light"} - -
+ + + ); }; diff --git a/frontend/components/Modal.js b/frontend/components/Modal.js index dd6efcd1..c300aece 100644 --- a/frontend/components/Modal.js +++ b/frontend/components/Modal.js @@ -10,6 +10,7 @@ import { ModalBody, ModalCloseButton, } from "@chakra-ui/react"; +import { MenuItem } from "site/MenuItem"; export const ModalClose = React.createContext(null); @@ -64,6 +65,7 @@ export const ModalTrigger = ({ const button = React.Children.toArray(children).find( (child) => + child.type === MenuItem || child.type === ModalTriggerButton || child.type === IconButton || child.type === Button diff --git a/frontend/components/PlusMessageIcon.js b/frontend/components/PlusMessageIcon.js index b1b6353f..5db247d7 100644 --- a/frontend/components/PlusMessageIcon.js +++ b/frontend/components/PlusMessageIcon.js @@ -2,22 +2,31 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faMessage, faPlus } from "@fortawesome/free-solid-svg-icons"; import { useColorMode } from "@chakra-ui/color-mode"; +import { Box } from "@chakra-ui/layout"; +import { StackableIcon } from "icons/StackableIcon"; const PlusMessageIcon = () => { const { colorMode } = useColorMode(); - const iconColor = colorMode === "light" ? "black" : "black"; + const iconColor = colorMode === "light" ? "gray.200" : "black"; + return ( - - - + + - + fontSize={"xs"} + fontWeight={"bold"} + > + +
+ ); }; + export default PlusMessageIcon; diff --git a/frontend/icons/IndicatorIcon.js b/frontend/icons/IndicatorIcon.js new file mode 100644 index 00000000..965da103 --- /dev/null +++ b/frontend/icons/IndicatorIcon.js @@ -0,0 +1,31 @@ +import React from "react"; +import { Box } from "@chakra-ui/react"; +import { useEditorColorMode } from "chains/editor/useColorMode"; + +export const IndicatorIcon = ({ children, color, indicatorSize }) => { + const { isLight, indicator } = useEditorColorMode(); + const bg = isLight ? "gray.100" : "gray.800"; + + const indicatorStyle = { + position: "absolute", + bottom: 0, + right: 0, + transform: "translate(40%, 0%)", + width: indicatorSize + 2 + "px", // Adjust size as needed + height: indicatorSize + 2 + "px", // Adjust size as needed + borderRadius: "50%", + display: "flex", + justifyContent: "center", + alignItems: "center", + }; + + const iconStyle = { + fontSize: indicatorSize + "px", + }; + + return ( + + {children ? React.cloneElement(children, { style: iconStyle }) : null} + + ); +}; diff --git a/frontend/icons/StackableIcon.js b/frontend/icons/StackableIcon.js new file mode 100644 index 00000000..77f7d713 --- /dev/null +++ b/frontend/icons/StackableIcon.js @@ -0,0 +1,24 @@ +import React from "react"; +import { Box } from "@chakra-ui/react"; + +export const StackableIcon = ({ children, ...props }) => { + return ( + + + {children} + + + ); +}; diff --git a/frontend/secrets/SecretsMenuItem.js b/frontend/secrets/SecretsMenuItem.js index ebdf6027..9eb31d0e 100644 --- a/frontend/secrets/SecretsMenuItem.js +++ b/frontend/secrets/SecretsMenuItem.js @@ -12,6 +12,7 @@ import { } from "site/LeftMenuPopover"; import { SecretsTable } from "secrets/SecretsTable"; import { SecretsFormModalButton } from "secrets/SecretsFormModalButton"; +import { MenuItem } from "site/MenuItem"; export const SecretsMenuItem = ({ editor }) => { const { page, isLoading, load } = usePaginatedAPI("/api/secrets/", { @@ -23,7 +24,9 @@ export const SecretsMenuItem = ({ editor }) => { return ( - + + + diff --git a/frontend/site/Layout.js b/frontend/site/Layout.js index 5693681b..6d27801e 100644 --- a/frontend/site/Layout.js +++ b/frontend/site/Layout.js @@ -1,12 +1,14 @@ import React, { Suspense } from "react"; -import { Divider, Flex, Spacer, VStack } from "@chakra-ui/react"; +import { Box, Divider, Flex, Spacer, VStack } from "@chakra-ui/react"; import { useColorMode } from "@chakra-ui/color-mode"; import { ColorModeButton } from "components/ColorModeButton"; import { CenteredSpinner } from "site/CenteredSpinner"; import { NewChatButton } from "chat/buttons/NewChatButton"; import { NewAgentButton } from "agents/NewAgentButton"; import Navigation from "site/Navigation"; -import SidebarProvider from "site/sidebar/context"; +import SidebarProvider, { useLeftSidebarContext } from "site/sidebar/context"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faArrowRight, faArrowLeft } from "@fortawesome/free-solid-svg-icons"; export const LayoutLeftPane = ({ children }) => { return children; @@ -16,6 +18,67 @@ export const LayoutContent = ({ children }) => { return children; }; +export const LeftSideBarToggle = () => { + const leftSideBar = useLeftSidebarContext(); // "icons" or "text" + + const toggle = React.useCallback(() => { + leftSideBar.setSize(leftSideBar.size === "icons" ? "text" : "icons"); + }, [leftSideBar.size]); + + return ( + + + + + + ); +}; + +const LeftSidebar = ({ children }) => { + const { colorMode } = useColorMode(); + const leftSideBar = useLeftSidebarContext(); // "icons" or "text" + return ( + + + + {/* left sidebar */} + + + + {children} + + + + + + ); +}; + export const Layout = ({ children }) => { const { colorMode } = useColorMode(); @@ -29,28 +92,7 @@ export const Layout = ({ children }) => { return ( - - {/* left sidebar */} - - - - {leftPane} - - - - - + {leftPane} { return children; @@ -24,6 +25,7 @@ export const LeftSidebarPopupContent = ({ children }) => { export const LeftMenuPopover = ({ children, onOpen }) => { const { isOpen, onToggle, onClose } = useDisclosure(); + const sideBar = useLeftSidebarContext(); const icon = React.Children.toArray(children).find( (child) => child.type === LeftSidebarPopupIcon @@ -36,12 +38,9 @@ export const LeftMenuPopover = ({ children, onOpen }) => { ); const { colorMode } = useColorMode(); - const style = - colorMode === "light" - ? { border: "1px solid", borderColor: "gray.300" } - : { border: "1px solid", borderColor: "whiteAlpha.50" }; const highlightColor = colorMode === "light" ? "blue.500" : "blue.400"; const color = colorMode === "light" ? "gray.800" : "white"; + const width = sideBar.size === "icons" ? "25px" : "110px"; return ( { onOpen={onOpen} > - + + {icon} + { + return ( + + + {children} + + + {title} + + + ); +}; diff --git a/frontend/site/Navigation.js b/frontend/site/Navigation.js index 4bf36be4..2257eef2 100644 --- a/frontend/site/Navigation.js +++ b/frontend/site/Navigation.js @@ -1,15 +1,11 @@ import React from "react"; import { Box, Divider, HStack, IconButton, Stack } from "@chakra-ui/react"; -import { - faCog, - faSignOutAlt, - faServer, - faMessage, -} from "@fortawesome/free-solid-svg-icons"; +import { faServer, faMessage } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Link } from "react-router-dom"; import { useColorMode } from "@chakra-ui/color-mode"; import { SecretsMenuItem } from "secrets/SecretsMenuItem"; +import { MenuItem } from "site/MenuItem"; function Navigation() { const { colorMode } = useColorMode(); @@ -28,11 +24,9 @@ function Navigation() { - } - title={"Chat history"} - {...style} - /> + + + {false && ( @@ -45,24 +39,12 @@ function Navigation() { )} - + + + - - } - title={"Settings"} - {...style} - /> - - - } - title={"Sign out"} - {...style} - /> - ); diff --git a/frontend/site/sidebar/context.js b/frontend/site/sidebar/context.js index b5edfd88..a5029c3d 100644 --- a/frontend/site/sidebar/context.js +++ b/frontend/site/sidebar/context.js @@ -3,8 +3,8 @@ import React, { createContext, useState, useContext } from "react"; const SidebarContext = createContext(null); export const DEFAULT_SIZES_LEFT = [ - ["icons", "75px"], - ["text", "150px"], + ["icons", "32px"], + ["text", "175px"], ]; export const DEFAULT_SIZES_RIGHT = [