From 50f714d7b8a5e0c66e8db41f939cf2a964663931 Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Sat, 17 Jun 2023 12:06:25 -0700
Subject: more ui details

---
 extension/react-app/src/components/CodeBlock.tsx   |  63 +++++++----
 extension/react-app/src/components/ComboBox.tsx    |  22 +++-
 .../react-app/src/components/StepContainer.tsx     | 118 +++++++++------------
 extension/react-app/src/components/TextDialog.tsx  |  77 +++++++++-----
 extension/react-app/src/components/index.ts        |  20 ----
 extension/react-app/src/index.css                  |   5 +-
 extension/react-app/src/tabs/gui.tsx               |   2 +
 7 files changed, 164 insertions(+), 143 deletions(-)

(limited to 'extension/react-app/src')

diff --git a/extension/react-app/src/components/CodeBlock.tsx b/extension/react-app/src/components/CodeBlock.tsx
index eedae3fb..c4524a51 100644
--- a/extension/react-app/src/components/CodeBlock.tsx
+++ b/extension/react-app/src/components/CodeBlock.tsx
@@ -1,44 +1,62 @@
 import hljs from "highlight.js";
-import { useEffect } from "react";
+import { useEffect, useState } from "react";
 import styled from "styled-components";
-import { defaultBorderRadius, vscBackground } from ".";
+import { defaultBorderRadius, secondaryDark, vscBackground } from ".";
 
-import { Clipboard } from "@styled-icons/heroicons-outline";
+import { Clipboard, CheckCircle } from "@styled-icons/heroicons-outline";
 
 const StyledPre = styled.pre`
   overflow-y: scroll;
   word-wrap: normal;
-  border: 1px solid gray;
+  border: 0.5px solid gray;
   border-radius: ${defaultBorderRadius};
-  background-color: ${vscBackground};
+  background-color: ${secondaryDark};
   padding: 8px;
+  padding-top: 14px;
+  padding-bottom: 16px;
 `;
 
-const StyledCode = styled.code`
-  background-color: ${vscBackground};
-`;
+const StyledCode = styled.code``;
 
-const StyledCopyButton = styled.button`
+const StyledCopyButton = styled.button<{ visible: boolean }>`
+  /* position: relative; */
   float: right;
   border: none;
-  background-color: ${vscBackground};
+  background-color: transparent;
   cursor: pointer;
   padding: 0;
-  margin: 4px;
-  &:hover {
-    color: #fff;
-  }
+  /* margin: 4px; */
+  margin-top: -6px;
+
+  visibility: ${(props) => (props.visible ? "visible" : "hidden")};
 `;
 
-function CopyButton(props: { textToCopy: string }) {
+function CopyButton(props: { textToCopy: string; visible: boolean }) {
+  const [hovered, setHovered] = useState<boolean>(false);
+  const [clicked, setClicked] = useState<boolean>(false);
   return (
     <>
       <StyledCopyButton
+        onMouseEnter={() => {
+          setHovered(true);
+        }}
+        onMouseLeave={() => {
+          setHovered(false);
+        }}
+        visible={clicked || props.visible}
         onClick={() => {
           navigator.clipboard.writeText(props.textToCopy);
+          setClicked(true);
+          setTimeout(() => {
+            setClicked(false);
+          }, 2000);
         }}
       >
-        <Clipboard color="white" size="1.4em" />
+        {clicked ? (
+          <CheckCircle color="#00ff00" size="1.4em" />
+        ) : (
+          <Clipboard color={hovered ? "#00ff00" : "white"} size="1.4em" />
+        )}
       </StyledCopyButton>
     </>
   );
@@ -48,9 +66,18 @@ function CodeBlock(props: { language?: string; children: string }) {
   useEffect(() => {
     hljs.highlightAll();
   }, [props.children]);
+  const [hovered, setHovered] = useState<boolean>(false);
+
   return (
-    <StyledPre>
-      <CopyButton textToCopy={props.children} />
+    <StyledPre
+      onMouseEnter={() => {
+        setHovered(true);
+      }}
+      onMouseLeave={() => {
+        setHovered(false);
+      }}
+    >
+      <CopyButton visible={hovered} textToCopy={props.children} />
       <StyledCode>{props.children}</StyledCode>
     </StyledPre>
   );
diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx
index e855ebe5..ddc9d5dc 100644
--- a/extension/react-app/src/components/ComboBox.tsx
+++ b/extension/react-app/src/components/ComboBox.tsx
@@ -9,16 +9,22 @@ import {
 } from ".";
 
 const mainInputFontSize = 16;
-const MainTextInput = styled.input`
+const MainTextInput = styled.textarea`
+  resize: none;
+
   padding: 8px;
   font-size: ${mainInputFontSize}px;
   border-radius: ${defaultBorderRadius};
-  border: 1px solid #ccc;
+  border: 1px solid white;
   margin: 8px auto;
   width: 100%;
   background-color: ${vscBackground};
   color: white;
-  outline: 1px solid orange;
+
+  &:focus {
+    border: 1px solid transparent;
+    outline: 1px solid orange;
+  }
 `;
 
 const UlMaxHeight = 200;
@@ -108,10 +114,16 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
     <div className="flex px-2" ref={divRef} hidden={!isOpen}>
       <MainTextInput
         disabled={props.disabled}
-        placeholder="Type '/' to see the list of available slash commands..."
+        placeholder="Type '/' to see available slash commands."
         {...getInputProps({
           onKeyDown: (event) => {
-            if (event.key === "Enter" && (!isOpen || items.length === 0)) {
+            if (event.key === "Enter" && event.shiftKey) {
+              // Prevent Downshift's default 'Enter' behavior.
+              (event.nativeEvent as any).preventDownshiftDefault = true;
+            } else if (
+              event.key === "Enter" &&
+              (!isOpen || items.length === 0)
+            ) {
               // Prevent Downshift's default 'Enter' behavior.
               (event.nativeEvent as any).preventDownshiftDefault = true;
               if (props.onEnter) props.onEnter(event);
diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx
index 4c98b04d..1eb1d1fd 100644
--- a/extension/react-app/src/components/StepContainer.tsx
+++ b/extension/react-app/src/components/StepContainer.tsx
@@ -5,14 +5,8 @@ import {
   defaultBorderRadius,
   secondaryDark,
   vscBackground,
-  GradientBorder,
   vscBackgroundTransparent,
-  HeaderButton,
 } from ".";
-import { RangeInFile, FileEdit } from "../../../src/client";
-import CodeBlock from "./CodeBlock";
-import SubContainer from "./SubContainer";
-
 import {
   ChevronDown,
   ChevronRight,
@@ -22,6 +16,7 @@ import {
 import { HistoryNode } from "../../../schema/HistoryNode";
 import ReactMarkdown from "react-markdown";
 import HeaderButtonWithText from "./HeaderButtonWithText";
+import CodeBlock from "./CodeBlock";
 
 interface StepContainerProps {
   historyNode: HistoryNode;
@@ -34,6 +29,8 @@ interface StepContainerProps {
   open: boolean;
   onToggleAll: () => void;
   onToggle: () => void;
+  isFirst: boolean;
+  isLast: boolean;
 }
 
 const MainDiv = styled.div<{ stepDepth: number; inFuture: boolean }>`
@@ -67,12 +64,6 @@ const ContentDiv = styled.div`
   padding-left: 16px;
 `;
 
-const OnHoverDiv = styled.div`
-  text-align: center;
-  padding: 10px;
-  animation: ${appear} 0.3s ease-in-out;
-`;
-
 const MarkdownPre = styled.pre`
   background-color: ${secondaryDark};
   padding: 10px;
@@ -80,7 +71,34 @@ const MarkdownPre = styled.pre`
   border: 0.5px solid white;
 `;
 
-const MarkdownCode = styled.code``;
+const StyledCode = styled.code`
+  word-wrap: break-word;
+  color: lightgray;
+`;
+
+const GradientBorder = styled.div<{
+  borderWidth?: number;
+  borderRadius?: string;
+  borderColor?: string;
+  isFirst: boolean;
+  isLast: boolean;
+}>`
+  border-radius: ${(props) => props.borderRadius || "0"};
+  padding-top: ${(props) =>
+    `${(props.borderWidth || 1) / (props.isFirst ? 1 : 2)}px`};
+  padding-bottom: ${(props) =>
+    `${(props.borderWidth || 1) / (props.isLast ? 1 : 2)}px`};
+  background: ${(props) =>
+    props.borderColor
+      ? props.borderColor
+      : `linear-gradient(
+    101.79deg,
+    #12887a 0%,
+    #87245c 37.64%,
+    #e12637 65.98%,
+    #ffb215 110.45%
+  )`};
+`;
 
 function StepContainer(props: StepContainerProps) {
   const [isHovered, setIsHovered] = useState(false);
@@ -120,12 +138,14 @@ function StepContainer(props: StepContainerProps) {
     >
       <StepContainerDiv open={props.open}>
         <GradientBorder
+          isFirst={props.isFirst}
+          isLast={props.isLast}
           borderColor={
             props.historyNode.observation?.error ? "#f00" : undefined
           }
           className="overflow-hidden cursor-pointer"
           onClick={(e) => {
-            if (props.open && e.metaKey) {
+            if (e.metaKey) {
               props.onToggleAll();
             } else {
               props.onToggle();
@@ -198,66 +218,28 @@ function StepContainer(props: StepContainerProps) {
             <ReactMarkdown
               key={1}
               className="overflow-x-scroll"
-              components={
-                {
-                  // pre: ({ node, ...props }) => {
-                  //   return (
-                  //     <CodeBlock
-                  //       children={props.children[0] as string}
-                  //     ></CodeBlock>
-                  //   );
-                  // },
-                }
-              }
+              components={{
+                pre: ({ node, ...props }) => {
+                  return (
+                    <CodeBlock
+                      children={props.children[0] as string}
+                    ></CodeBlock>
+                  );
+                },
+                code: ({ node, ...props }) => {
+                  return (
+                    <StyledCode
+                      children={props.children[0] as string}
+                    ></StyledCode>
+                  );
+                },
+              }}
             >
               {props.historyNode.step.description as any}
             </ReactMarkdown>
           )}
-
-          {/* {props.historyNode.step.name === "Waiting for user input" && (
-            <InputAndButton
-              onUserInput={(value) => {
-                props.onUserInput(value);
-              }}
-            ></InputAndButton>
-          )}
-          {props.historyNode.step.name === "Waiting for user confirmation" && (
-            <>
-              <input
-                type="button"
-                value="Cancel"
-                className="m-4 p-2 rounded-md border border-solid text-white border-gray-200 bg-vsc-background cursor-pointer hover:bg-white hover:text-black"
-              ></input>
-              <input
-                className="m-4 p-2 rounded-md border border-solid text-white border-gray-200 bg-vsc-background cursor-pointer hover:bg-white hover:text-black"
-                onClick={(e) => {
-                  props.onUserInput("ok");
-                  e.preventDefault();
-                  e.stopPropagation();
-                }}
-                type="button"
-                value="Confirm"
-              />
-            </>
-          )} */}
         </ContentDiv>
       </StepContainerDiv>
-
-      {/* <OnHoverDiv hidden={!open}>
-        <NaturalLanguageInput
-          onKeyDown={(e) => {
-            if (e.key === "Enter") {
-              onTextInput();
-            }
-          }}
-          ref={naturalLanguageInputRef}
-          onClick={(e) => {
-            e.stopPropagation();
-            e.preventDefault();
-          }}
-        ></NaturalLanguageInput>
-        <ContinueButton onClick={onTextInput}></ContinueButton>
-      </OnHoverDiv> */}
     </MainDiv>
   );
 }
diff --git a/extension/react-app/src/components/TextDialog.tsx b/extension/react-app/src/components/TextDialog.tsx
index 31a385d5..e50a7686 100644
--- a/extension/react-app/src/components/TextDialog.tsx
+++ b/extension/react-app/src/components/TextDialog.tsx
@@ -3,6 +3,13 @@ import React, { useEffect, useState } from "react";
 import styled from "styled-components";
 import { Button, buttonColor, secondaryDark, vscBackground } from ".";
 
+const ScreenCover = styled.div`
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(168, 168, 168, 0.5);
+`;
+
 const DialogContainer = styled.div`
   position: absolute;
   top: 50%;
@@ -28,9 +35,10 @@ const TextArea = styled.textarea`
   padding: 8px;
   outline: 1px solid black;
   font-family: Arial, Helvetica, sans-serif;
+  resize: none;
 
   &:focus {
-    outline: 1px solid orange;
+    outline: 1px solid ${buttonColor};
   }
 `;
 
@@ -54,34 +62,45 @@ const TextDialog = (props: {
   }, [props.showDialog]);
 
   return (
-    <DialogContainer hidden={!props.showDialog}>
-      <Dialog>
-        <P>Thanks for your feedback. We'll get back to you soon!</P>
-        <TextArea
-          cols={50}
-          rows={10}
-          ref={textAreaRef}
-          onKeyDown={(e) => {
-            if (e.key === "Enter" && e.metaKey && textAreaRef.current) {
-              props.onEnter(textAreaRef.current.value);
-              setText("");
-            } else if (e.key === "Escape") {
-              props.onClose();
-            }
-          }}
-        />
-        <Button
-          onClick={() => {
-            if (textAreaRef.current) {
-              props.onEnter(textAreaRef.current.value);
-              setText("");
-            }
-          }}
-        >
-          Enter
-        </Button>
-      </Dialog>
-    </DialogContainer>
+    <ScreenCover
+      onClick={() => {
+        props.onClose();
+      }}
+      hidden={!props.showDialog}
+    >
+      <DialogContainer
+        onClick={(e) => {
+          e.stopPropagation();
+        }}
+      >
+        <Dialog>
+          <P>Thanks for your feedback. We'll get back to you soon!</P>
+          <TextArea
+            cols={50}
+            rows={10}
+            ref={textAreaRef}
+            onKeyDown={(e) => {
+              if (e.key === "Enter" && e.metaKey && textAreaRef.current) {
+                props.onEnter(textAreaRef.current.value);
+                setText("");
+              } else if (e.key === "Escape") {
+                props.onClose();
+              }
+            }}
+          />
+          <Button
+            onClick={() => {
+              if (textAreaRef.current) {
+                props.onEnter(textAreaRef.current.value);
+                setText("");
+              }
+            }}
+          >
+            Enter
+          </Button>
+        </Dialog>
+      </DialogContainer>
+    </ScreenCover>
   );
 };
 
diff --git a/extension/react-app/src/components/index.ts b/extension/react-app/src/components/index.ts
index d99b4d96..fc94c51f 100644
--- a/extension/react-app/src/components/index.ts
+++ b/extension/react-app/src/components/index.ts
@@ -95,26 +95,6 @@ export const Loader = styled.div`
   margin: auto;
 `;
 
-export const GradientBorder = styled.div<{
-  borderWidth?: string;
-  borderRadius?: string;
-  borderColor?: string;
-}>`
-  border-radius: ${(props) => props.borderRadius || "0"};
-  padding-top: ${(props) => props.borderWidth || "1px"};
-  padding-bottom: ${(props) => props.borderWidth || "1px"};
-  background: ${(props) =>
-    props.borderColor
-      ? props.borderColor
-      : `linear-gradient(
-    101.79deg,
-    #12887a 0%,
-    #87245c 37.64%,
-    #e12637 65.98%,
-    #ffb215 110.45%
-  )`};
-`;
-
 export const MainContainerWithBorder = styled.div<{ borderWidth?: string }>`
   border-radius: ${defaultBorderRadius};
   padding: ${(props) => props.borderWidth || "1px"};
diff --git a/extension/react-app/src/index.css b/extension/react-app/src/index.css
index db8afab9..6dc514ec 100644
--- a/extension/react-app/src/index.css
+++ b/extension/react-app/src/index.css
@@ -3,8 +3,8 @@
 @tailwind utilities;
 
 :root {
-  --secondary-dark: 37 37 38;
-  --vsc-background: 30 30 30;
+  --secondary-dark: rgb(37, 37, 38);
+  --vsc-background: rgb(30, 30, 30);
   --button-color: rgb(113, 28, 59);
   --button-color-hover: rgba(113, 28, 59, 0.667);
   --def-border-radius: 5px;
@@ -26,7 +26,6 @@ body,
 }
 
 body {
-  background-color: var(--vsc-background);
   padding: 0;
   color: white;
   font-family: "Mona Sans", "Arial", sans-serif;
diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx
index 6aa20e0e..624d22d5 100644
--- a/extension/react-app/src/tabs/gui.tsx
+++ b/extension/react-app/src/tabs/gui.tsx
@@ -331,6 +331,8 @@ function GUI(props: GUIProps) {
         {history?.timeline.map((node: HistoryNode, index: number) => {
           return (
             <StepContainer
+              isLast={index === history.timeline.length - 1}
+              isFirst={index === 0}
               open={stepsOpen[index]}
               onToggle={() => {
                 const nextStepsOpen = [...stepsOpen];
-- 
cgit v1.2.3-70-g09d2