summaryrefslogtreecommitdiff
path: root/extension/react-app/src/components/PillButton.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'extension/react-app/src/components/PillButton.tsx')
-rw-r--r--extension/react-app/src/components/PillButton.tsx257
1 files changed, 148 insertions, 109 deletions
diff --git a/extension/react-app/src/components/PillButton.tsx b/extension/react-app/src/components/PillButton.tsx
index fb685a82..063572b5 100644
--- a/extension/react-app/src/components/PillButton.tsx
+++ b/extension/react-app/src/components/PillButton.tsx
@@ -1,23 +1,23 @@
-import { useContext, useEffect, useState } from "react";
+import { useContext, useEffect, useRef, useState } from "react";
import styled from "styled-components";
import {
StyledTooltip,
defaultBorderRadius,
lightGray,
secondaryDark,
- vscBackground,
vscForeground,
} from ".";
import {
TrashIcon,
PaintBrushIcon,
ExclamationTriangleIcon,
+ EyeIcon,
} from "@heroicons/react/24/outline";
import { GUIClientContext } from "../App";
import { useDispatch } from "react-redux";
-import { setBottomMessage } from "../redux/slices/uiStateSlice";
import { ContextItem } from "../../../schema/FullState";
import { getFontSize } from "../util";
+import HeaderButtonWithText from "./HeaderButtonWithText";
const Button = styled.button<{ fontSize?: number }>`
border: none;
@@ -80,7 +80,13 @@ interface PillButtonProps {
editingAny: boolean;
index: number;
areMultipleItems?: boolean;
- onDelete?: () => void;
+ onDelete?: (index?: number) => void;
+ onClick?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
+ stepIndex?: number;
+ previewing?: boolean;
+ toggleViewContent?: () => void;
+ onBlur?: () => void;
+ focusing?: boolean;
}
interface StyledButtonProps {
@@ -88,6 +94,14 @@ interface StyledButtonProps {
editing?: boolean;
}
+const Container = styled.div<{ previewing?: boolean }>`
+ border-radius: ${defaultBorderRadius};
+ background-color: ${secondaryDark};
+ display: flex;
+ align-items: center;
+ justify-content: center;
+`;
+
const StyledButton = styled(Button)<StyledButtonProps>`
position: relative;
border-color: ${(props) => props.borderColor || "transparent"};
@@ -96,12 +110,34 @@ const StyledButton = styled(Button)<StyledButtonProps>`
&:focus {
outline: none;
- border-color: ${lightGray};
- border-width: 1px;
- border-style: solid;
+ /* border-color: ${lightGray}; */
+ text-decoration: underline;
+ }
+`;
+
+const HoverableInsidePillButton = styled(HeaderButtonWithText)<{
+ color: string;
+}>`
+ &:hover {
+ background-color: ${(props) => props.color};
}
`;
+const ClickableInsidePillButton = styled(HeaderButtonWithText)<{
+ color: string;
+ selected: boolean;
+}>`
+ ${(props) =>
+ props.selected &&
+ `
+ background-color: ${props.color};
+
+ &:hover {
+ background-color: ${props.color};
+ }
+ `}
+`;
+
const PillButton = (props: PillButtonProps) => {
const [isHovered, setIsHovered] = useState(false);
const client = useContext(GUIClientContext);
@@ -116,122 +152,125 @@ const PillButton = (props: PillButtonProps) => {
}
}, [props.editing, props.item]);
- const dispatch = useDispatch();
+ const pillContainerRef = useRef<HTMLDivElement>(null);
+ const buttonRef = useRef<HTMLButtonElement>(null);
return (
<div style={{ position: "relative" }}>
- <StyledButton
- fontSize={getFontSize()}
- borderColor={props.editing ? (warning ? "red" : undefined) : undefined}
- onMouseEnter={() => {
- setIsHovered(true);
- if (props.onHover) {
- props.onHover(true);
+ <Container previewing={props.previewing} ref={pillContainerRef}>
+ <StyledButton
+ fontSize={getFontSize()}
+ borderColor={
+ props.editing ? (warning ? "red" : undefined) : undefined
}
- }}
- onMouseLeave={() => {
- setIsHovered(false);
- if (props.onHover) {
- props.onHover(false);
- }
- }}
- className="pill-button"
- onKeyDown={(e) => {
- if (e.key === "Backspace") {
- props.onDelete?.();
- }
- }}
- >
- {isHovered && (
- <GridDiv
- style={{
- gridTemplateColumns:
- props.item.editable &&
- props.areMultipleItems &&
- props.editingAny
- ? "1fr 1fr"
- : "1fr",
- backgroundColor: vscBackground,
- }}
- >
- {props.editingAny &&
- props.item.editable &&
- props.areMultipleItems && (
- <ButtonDiv
- data-tooltip-id={`edit-${props.index}`}
- backgroundColor={"#8800aa55"}
- onClick={() => {
- client?.setEditingAtIds([
- props.item.description.id.item_id,
- ]);
- }}
- >
- <PaintBrushIcon style={{ margin: "auto" }} width="1.6em" />
- </ButtonDiv>
- )}
-
- <StyledTooltip id={`pin-${props.index}`}>
- Edit this range
- </StyledTooltip>
- <ButtonDiv
- data-tooltip-id={`delete-${props.index}`}
- backgroundColor={"#cc000055"}
+ ref={buttonRef}
+ onMouseEnter={() => {
+ setIsHovered(true);
+ if (props.onHover) {
+ props.onHover(true);
+ }
+ }}
+ onMouseLeave={() => {
+ setIsHovered(false);
+ if (props.onHover) {
+ props.onHover(false);
+ }
+ }}
+ className={`pill-button-${props.stepIndex || "main"}`}
+ onKeyDown={(e) => {
+ if (e.key === "Backspace") {
+ props.onDelete?.(props.stepIndex);
+ } else if (e.key === "v") {
+ props.toggleViewContent?.();
+ } else if (e.key === "e") {
+ client?.setEditingAtIds([props.item.description.id.item_id]);
+ }
+ }}
+ onClick={(e) => {
+ props.onClick?.(e);
+ }}
+ onBlur={(e) => {
+ if (!pillContainerRef.current?.contains(e.relatedTarget as any)) {
+ props.onBlur?.();
+ } else {
+ e.preventDefault();
+ buttonRef.current?.focus();
+ }
+ }}
+ >
+ <span className={isHovered ? "underline" : ""}>
+ {props.item.description.name}
+ </span>
+ </StyledButton>
+ {((props.focusing && props.item.editable && props.editingAny) ||
+ props.editing) && (
+ <>
+ <ClickableInsidePillButton
+ data-tooltip-id={`circle-div-${props.item.description.name}`}
+ text={
+ props.editing ? "Editing this range" : "Edit this range (e)"
+ }
onClick={() => {
- client?.deleteContextWithIds([props.item.description.id]);
- dispatch(setBottomMessage(undefined));
+ if (!props.editing) {
+ client?.setEditingAtIds([props.item.description.id.item_id]);
+ }
}}
+ tabIndex={-1}
+ color="#f0f4"
+ selected={props.editing}
>
- <TrashIcon style={{ margin: "auto" }} width="1.6em" />
- </ButtonDiv>
- </GridDiv>
+ <PaintBrushIcon width="1.4em" height="1.4em" />
+ </ClickableInsidePillButton>
+ <StyledTooltip id={`circle-div-${props.item.description.name}`}>
+ Editing this range
+ </StyledTooltip>
+ </>
+ )}
+ {(props.focusing || props.previewing) && (
+ <ClickableInsidePillButton
+ text="View (v)"
+ onClick={() => props.toggleViewContent?.()}
+ tabIndex={-1}
+ color="#ff04"
+ selected={props.previewing || false}
+ >
+ <EyeIcon width="1.4em" height="1.4em" />
+ </ClickableInsidePillButton>
+ )}
+ {props.focusing && (
+ <HoverableInsidePillButton
+ text="Delete (⌫)"
+ onClick={() => props.onDelete?.(props.stepIndex)}
+ tabIndex={-1}
+ color="#f004"
+ >
+ <TrashIcon width="1.4em" height="1.4em" />
+ </HoverableInsidePillButton>
)}
- {props.item.description.name}
- </StyledButton>
+ </Container>
<StyledTooltip id={`edit-${props.index}`}>
{props.item.editing
? "Editing this section (with entire file as context)"
: "Edit this section"}
</StyledTooltip>
<StyledTooltip id={`delete-${props.index}`}>Delete</StyledTooltip>
- {props.editing &&
- (warning ? (
- <>
- <CircleDiv
- data-tooltip-id={`circle-div-${props.item.description.name}`}
- className="z-10"
- >
- <ExclamationTriangleIcon
- style={{ margin: "auto" }}
- width="1.0em"
- strokeWidth={2}
- />
- </CircleDiv>
- <StyledTooltip id={`circle-div-${props.item.description.name}`}>
- {warning}
- </StyledTooltip>
- </>
- ) : (
- <>
- <CircleDiv
- data-tooltip-id={`circle-div-${props.item.description.name}`}
- style={{
- backgroundColor: "#8800aa55",
- border: `0.5px solid ${lightGray}`,
- padding: "1px",
- zIndex: 1,
- }}
- >
- <PaintBrushIcon
- style={{ margin: "auto" }}
- width="1.0em"
- strokeWidth={2}
- />
- </CircleDiv>
- <StyledTooltip id={`circle-div-${props.item.description.name}`}>
- Editing this range
- </StyledTooltip>
- </>
- ))}
+ {props.editing && warning && (
+ <>
+ <CircleDiv
+ data-tooltip-id={`circle-div-${props.item.description.name}`}
+ className="z-10"
+ >
+ <ExclamationTriangleIcon
+ style={{ margin: "auto" }}
+ width="1.0em"
+ strokeWidth={2}
+ />
+ </CircleDiv>
+ <StyledTooltip id={`circle-div-${props.item.description.name}`}>
+ {warning}
+ </StyledTooltip>
+ </>
+ )}
</div>
);
};