diff options
author | Nate Sesti <sestinj@gmail.com> | 2023-08-12 12:13:49 -0700 |
---|---|---|
committer | Nate Sesti <sestinj@gmail.com> | 2023-08-12 12:13:49 -0700 |
commit | ae058c6bac7ea37108e2894e419a22dfb95fd3ff (patch) | |
tree | a07c2d1ac24cb7b1418af921f023bcb25baf90ff /extension/react-app/src | |
parent | dfe8be1b00c87a79212d4fc94a33fe74a6040103 (diff) | |
download | sncontinue-ae058c6bac7ea37108e2894e419a22dfb95fd3ff.tar.gz sncontinue-ae058c6bac7ea37108e2894e419a22dfb95fd3ff.tar.bz2 sncontinue-ae058c6bac7ea37108e2894e419a22dfb95fd3ff.zip |
feat: :lipstick: UI Improvements!
Diffstat (limited to 'extension/react-app/src')
4 files changed, 116 insertions, 148 deletions
diff --git a/extension/react-app/src/components/Layout.tsx b/extension/react-app/src/components/Layout.tsx index a3b1946a..0721585d 100644 --- a/extension/react-app/src/components/Layout.tsx +++ b/extension/react-app/src/components/Layout.tsx @@ -3,15 +3,13 @@ import { defaultBorderRadius, secondaryDark, vscForeground } from "."; import { Outlet } from "react-router-dom"; import Onboarding from "./Onboarding"; import TextDialog from "./TextDialog"; -import { useContext } from "react"; +import { useContext, useEffect } from "react"; import { GUIClientContext } from "../App"; import { useDispatch, useSelector } from "react-redux"; import { RootStore } from "../redux/store"; import { setBottomMessage, setBottomMessageCloseTimeout, - setDialogEntryOn, - setDialogMessage, setShowDialog, } from "../redux/slices/uiStateSlice"; import { @@ -57,8 +55,6 @@ const Footer = styled.footer` justify-content: right; padding: 8px; align-items: center; - margin-top: 8px; - border-top: 0.1px solid gray; `; // #endregion @@ -78,9 +74,6 @@ const Layout = () => { ); // #region Selectors - const vscMediaUrl = useSelector( - (state: RootStore) => state.config.vscMediaUrl - ); const bottomMessage = useSelector( (state: RootStore) => state.uiState.bottomMessage @@ -91,6 +84,20 @@ const Layout = () => { // #endregion + useEffect(() => { + const handleKeyDown = (event: any) => { + if (event.metaKey && event.key === "n" && event.altKey) { + client?.loadSession(undefined); + } + }; + + window.addEventListener("keydown", handleKeyDown); + + return () => { + window.removeEventListener("keydown", handleKeyDown); + }; + }, [client]); + return ( <LayoutTopDiv> <div @@ -131,51 +138,11 @@ const Layout = () => { {bottomMessage} </BottomMessageDiv> <Footer> - {vscMediaUrl && ( - <a - href="https://github.com/continuedev/continue" - style={{ marginRight: "auto" }} - > - <img - src={`${vscMediaUrl}/continue-dev-square.png`} - width="22px" - style={{ backgroundColor: "black", color: "red" }} - /> - </a> - )} - <HeaderButtonWithText - onClick={() => { - // Show the dialog - dispatch( - setDialogMessage(`Continue uses GPT-4 by default, but works with any model. If you'd like to keep your code completely private, there are few options: - - Run a local model with ggml: [5 minute quickstart](https://github.com/continuedev/ggml-server-example) - - Use Azure OpenAI service, which is GDPR and HIPAA compliant: [Tutorial](https://continue.dev/docs/customization#azure-openai-service) - - If you already have an LLM deployed on your own infrastructure, or would like to do so, please contact us at hi@continue.dev. - `) - ); - dispatch(setDialogEntryOn(false)); - dispatch(setShowDialog(true)); - }} - text={"Use Private Model"} - > - <div - style={{ - fontSize: "18px", - marginLeft: "2px", - marginRight: "2px", - }} - > - 🔒 - </div> - </HeaderButtonWithText> <HeaderButtonWithText onClick={() => { client?.loadSession(undefined); }} - text="New Session" + text="New Session (⌥⌘N)" > <PlusIcon width="1.4em" height="1.4em" /> </HeaderButtonWithText> @@ -195,21 +162,14 @@ const Layout = () => { <BookOpenIcon width="1.4em" height="1.4em" /> </HeaderButtonWithText> </a> - <HeaderButtonWithText - onClick={() => { - // Set dialog open - dispatch( - setDialogMessage( - "Having trouble using Continue? Want a new feature? Let us know! This box is anonymous, but we will promptly address your feedback." - ) - ); - dispatch(setDialogEntryOn(true)); - dispatch(setShowDialog(true)); - }} - text="Feedback" + <a + href="https://github.com/continuedev/continue/issues/new/choose" + className="no-underline" > - <ChatBubbleOvalLeftEllipsisIcon width="1.4em" height="1.4em" /> - </HeaderButtonWithText> + <HeaderButtonWithText text="Feedback"> + <ChatBubbleOvalLeftEllipsisIcon width="1.4em" height="1.4em" /> + </HeaderButtonWithText> + </a> </Footer> </div> </LayoutTopDiv> diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index fe81e9e1..ce7d9a58 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -1,12 +1,6 @@ import { useContext, useEffect, useRef, useState } from "react"; import styled, { keyframes } from "styled-components"; -import { - defaultBorderRadius, - secondaryDark, - vscBackground, - vscBackgroundTransparent, - vscForeground, -} from "."; +import { secondaryDark, vscBackground } from "."; import { ChevronDownIcon, ChevronRightIcon, @@ -48,18 +42,10 @@ const MainDiv = styled.div<{ margin-right: 0px; `; -const StepContainerDiv = styled.div<{ open: boolean }>` - /* background-color: ${(props) => - props.open ? vscBackground : secondaryDark}; */ - /* border-radius: ${defaultBorderRadius}; */ - /* padding: 8px; */ -`; - const HeaderDiv = styled.div<{ error: boolean; loading: boolean }>` background-color: ${(props) => (props.error ? "#522" : vscBackground)}; display: grid; grid-template-columns: 1fr auto auto; - grid-gap: 8px; align-items: center; padding-right: 8px; `; @@ -73,7 +59,8 @@ const LeftHeaderSubDiv = styled.div` `; const ContentDiv = styled.div<{ isUserInput: boolean }>` - padding: 8px; + padding-left: 4px; + padding-right: 2px; background-color: ${(props) => props.isUserInput ? secondaryDark : vscBackground}; font-size: 13px; @@ -151,9 +138,9 @@ function StepContainer(props: StepContainerProps) { }} hidden={props.historyNode.step.hide as any} > - <StepContainerDiv open={props.open}> + <div> <GradientBorder - loading={(props.historyNode.active as boolean) || false} + loading={props.historyNode.active as boolean} isFirst={props.isFirst} isLast={props.isLast} borderColor={ @@ -198,62 +185,63 @@ function StepContainer(props: StepContainerProps) { > <Backward size="1.6em" onClick={props.onReverse}></Backward> </HeaderButton> */} - - <> - {(props.historyNode.logs as any)?.length > 0 && ( + {(isHovered || (props.historyNode.active as boolean)) && ( + <div className="flex gap-2 items-center"> + {(props.historyNode.logs as any)?.length > 0 && ( + <HeaderButtonWithText + text="Logs" + onClick={(e) => { + e.stopPropagation(); + client?.showLogsAtIndex(props.index); + }} + > + <MagnifyingGlassIcon width="1.4em" height="1.4em" /> + </HeaderButtonWithText> + )} <HeaderButtonWithText - text="Logs" onClick={(e) => { e.stopPropagation(); - client?.showLogsAtIndex(props.index); + props.onDelete(); }} + text={ + props.historyNode.active + ? `Stop (${getMetaKeyLabel()}⌫)` + : "Delete" + } > - <MagnifyingGlassIcon width="1.4em" height="1.4em" /> + {props.historyNode.active ? ( + <StopCircleIcon + width="1.4em" + height="1.4em" + onClick={props.onDelete} + /> + ) : ( + <XMarkIcon + width="1.4em" + height="1.4em" + onClick={props.onDelete} + /> + )} </HeaderButtonWithText> - )} - <HeaderButtonWithText - onClick={(e) => { - e.stopPropagation(); - props.onDelete(); - }} - text={ - props.historyNode.active - ? `Stop (${getMetaKeyLabel()}⌫)` - : "Delete" - } - > - {props.historyNode.active ? ( - <StopCircleIcon - width="1.4em" - height="1.4em" - onClick={props.onDelete} - /> + {props.historyNode.observation?.error ? ( + <HeaderButtonWithText + text="Retry" + onClick={(e) => { + e.stopPropagation(); + props.onRetry(); + }} + > + <ArrowPathIcon + width="1.4em" + height="1.4em" + onClick={props.onRetry} + /> + </HeaderButtonWithText> ) : ( - <XMarkIcon - width="1.4em" - height="1.4em" - onClick={props.onDelete} - /> + <></> )} - </HeaderButtonWithText> - {props.historyNode.observation?.error ? ( - <HeaderButtonWithText - text="Retry" - onClick={(e) => { - e.stopPropagation(); - props.onRetry(); - }} - > - <ArrowPathIcon - width="1.4em" - height="1.4em" - onClick={props.onRetry} - /> - </HeaderButtonWithText> - ) : ( - <></> - )} - </> + </div> + )} </HeaderDiv> </GradientBorder> <ContentDiv hidden={!props.open} isUserInput={isUserInput}> @@ -283,7 +271,7 @@ function StepContainer(props: StepContainerProps) { /> )} </ContentDiv> - </StepContainerDiv> + </div> </MainDiv> ); } diff --git a/extension/react-app/src/components/StyledMarkdownPreview.tsx b/extension/react-app/src/components/StyledMarkdownPreview.tsx index b1079c96..5957f8dd 100644 --- a/extension/react-app/src/components/StyledMarkdownPreview.tsx +++ b/extension/react-app/src/components/StyledMarkdownPreview.tsx @@ -11,7 +11,6 @@ const StyledMarkdownPreview = styled(MarkdownPreview)<{ light?: boolean }>` pre { background-color: ${(props) => props.light ? vscBackground : secondaryDark}; - padding: 1px; border-radius: ${defaultBorderRadius}; border: 0.5px solid white; } @@ -27,6 +26,7 @@ const StyledMarkdownPreview = styled(MarkdownPreview)<{ light?: boolean }>` background-color: ${(props) => props.light ? vscBackground : secondaryDark}; color: ${vscForeground}; + padding: 10px; } background-color: ${(props) => (props.light ? "transparent" : vscBackground)}; diff --git a/extension/react-app/src/components/UserInputContainer.tsx b/extension/react-app/src/components/UserInputContainer.tsx index 7e964ad9..90cd549b 100644 --- a/extension/react-app/src/components/UserInputContainer.tsx +++ b/extension/react-app/src/components/UserInputContainer.tsx @@ -1,7 +1,7 @@ -import React from "react"; +import React, { useState } from "react"; import ReactMarkdown from "react-markdown"; import styled from "styled-components"; -import { secondaryDark, vscBackground } from "."; +import { defaultBorderRadius, secondaryDark, vscBackground } from "."; import HeaderButtonWithText from "./HeaderButtonWithText"; import { XMarkIcon } from "@heroicons/react/24/outline"; import { HistoryNode } from "../../../schema/HistoryNode"; @@ -21,35 +21,55 @@ const StyledDiv = styled.div` align-items: center; border-bottom: 1px solid ${vscBackground}; padding: 8px; - padding-top: 4px; - padding-bottom: 4px; + padding-top: 0px; + padding-bottom: 0px; `; const DeleteButtonDiv = styled.div` position: absolute; top: 8px; - right: 16px; + right: 8px; +`; + +const StyledPre = styled.pre` + margin-right: 22px; + margin-left: 8px; + white-space: pre-wrap; + word-wrap: break-word; + font-family: "Lexend", sans-serif; + font-size: 13px; `; const UserInputContainer = (props: UserInputContainerProps) => { + const [isHovered, setIsHovered] = useState(false); return ( - <StyledDiv> - <StyledMarkdownPreview + <StyledDiv + onMouseEnter={() => { + setIsHovered(true); + }} + onMouseLeave={() => { + setIsHovered(false); + }} + > + {/* <StyledMarkdownPreview light={true} source={props.children} className="mr-6" - /> + /> */} + <StyledPre className="mr-6">{props.children}</StyledPre> {/* <ReactMarkdown children={props.children} className="w-fit mr-10" /> */} <DeleteButtonDiv> - <HeaderButtonWithText - onClick={(e) => { - props.onDelete(); - e.stopPropagation(); - }} - text="Delete" - > - <XMarkIcon width="1.4em" height="1.4em" /> - </HeaderButtonWithText> + {isHovered && ( + <HeaderButtonWithText + onClick={(e) => { + props.onDelete(); + e.stopPropagation(); + }} + text="Delete" + > + <XMarkIcon width="1.4em" height="1.4em" /> + </HeaderButtonWithText> + )} </DeleteButtonDiv> </StyledDiv> ); |