summaryrefslogtreecommitdiff
path: root/extension/react-app/src
diff options
context:
space:
mode:
authorNate Sesti <sestinj@gmail.com>2023-08-12 12:13:49 -0700
committerNate Sesti <sestinj@gmail.com>2023-08-12 12:13:49 -0700
commitae058c6bac7ea37108e2894e419a22dfb95fd3ff (patch)
treea07c2d1ac24cb7b1418af921f023bcb25baf90ff /extension/react-app/src
parentdfe8be1b00c87a79212d4fc94a33fe74a6040103 (diff)
downloadsncontinue-ae058c6bac7ea37108e2894e419a22dfb95fd3ff.tar.gz
sncontinue-ae058c6bac7ea37108e2894e419a22dfb95fd3ff.tar.bz2
sncontinue-ae058c6bac7ea37108e2894e419a22dfb95fd3ff.zip
feat: :lipstick: UI Improvements!
Diffstat (limited to 'extension/react-app/src')
-rw-r--r--extension/react-app/src/components/Layout.tsx86
-rw-r--r--extension/react-app/src/components/StepContainer.tsx122
-rw-r--r--extension/react-app/src/components/StyledMarkdownPreview.tsx2
-rw-r--r--extension/react-app/src/components/UserInputContainer.tsx54
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>
);