summaryrefslogtreecommitdiff
path: root/extension/react-app/src
diff options
context:
space:
mode:
Diffstat (limited to 'extension/react-app/src')
-rw-r--r--extension/react-app/src/components/ComboBox.tsx74
-rw-r--r--extension/react-app/src/components/HeaderButtonWithText.tsx4
-rw-r--r--extension/react-app/src/components/PillButton.tsx49
3 files changed, 108 insertions, 19 deletions
diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx
index df3f970c..14e04a84 100644
--- a/extension/react-app/src/components/ComboBox.tsx
+++ b/extension/react-app/src/components/ComboBox.tsx
@@ -223,11 +223,56 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
const divRef = React.useRef<HTMLDivElement>(null);
const ulRef = React.useRef<HTMLUListElement>(null);
const showAbove = () => {
- return (divRef.current?.getBoundingClientRect().top || 0) > UlMaxHeight;
+ return (
+ (divRef.current?.getBoundingClientRect().top || Number.MAX_SAFE_INTEGER) >
+ UlMaxHeight
+ );
};
useImperativeHandle(ref, () => downshiftProps, [downshiftProps]);
+ const contextItemsDivRef = React.useRef<HTMLDivElement>(null);
+ const handleTabPressed = () => {
+ // Set the focus to the next item in the context items div
+ if (!contextItemsDivRef.current) {
+ return;
+ }
+ const focusableItems =
+ contextItemsDivRef.current.querySelectorAll(".pill-button");
+ const focusableItemsArray = Array.from(focusableItems);
+ const focusedItemIndex = focusableItemsArray.findIndex(
+ (item) => item === document.activeElement
+ );
+ console.log(focusedItemIndex, focusableItems);
+ if (focusedItemIndex === focusableItemsArray.length - 1) {
+ inputRef.current?.focus();
+ } else if (focusedItemIndex !== -1) {
+ const nextItem =
+ focusableItemsArray[
+ (focusedItemIndex + 1) % focusableItemsArray.length
+ ];
+ (nextItem as any)?.focus();
+ } else {
+ const firstItem = focusableItemsArray[0];
+ (firstItem as any)?.focus();
+ }
+ };
+
+ useEffect(() => {
+ if (typeof window !== "undefined") {
+ const listener = (e: any) => {
+ if (e.key === "Tab") {
+ e.preventDefault();
+ handleTabPressed();
+ }
+ };
+ window.addEventListener("keydown", listener);
+ return () => {
+ window.removeEventListener("keydown", listener);
+ };
+ }
+ }, []);
+
const [metaKeyPressed, setMetaKeyPressed] = useState(false);
const [focused, setFocused] = useState(false);
useEffect(() => {
@@ -271,7 +316,10 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
return (
<>
- <div className="px-2 flex gap-2 items-center flex-wrap mt-2">
+ <div
+ className="px-2 flex gap-2 items-center flex-wrap mt-2"
+ ref={contextItemsDivRef}
+ >
{props.selectedContextItems.map((item, idx) => {
return (
<PillButton
@@ -285,6 +333,10 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
}
addingHighlightedCode={props.addingHighlightedCode}
index={idx}
+ onDelete={() => {
+ client?.deleteContextWithIds([item.description.id]);
+ inputRef.current?.focus();
+ }}
/>
);
})}
@@ -303,6 +355,13 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
onClick={() => {
props.onToggleAddContext();
}}
+ className="pill-button focus:outline-none focus:border-red-600 focus:border focus:border-solid"
+ onKeyDown={(e: KeyboardEvent) => {
+ e.preventDefault();
+ if (e.key === "Enter") {
+ props.onToggleAddContext();
+ }
+ }}
>
<DocumentPlusIcon width="1.4em" height="1.4em" />
</HeaderButtonWithText>
@@ -329,10 +388,6 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
setFocused(true);
dispatch(setBottomMessage(undefined));
},
- onBlur: (e) => {
- setFocused(false);
- postVscMessage("blurContinueInput", {});
- },
onKeyDown: (event) => {
dispatch(setBottomMessage(undefined));
if (event.key === "Enter" && event.shiftKey) {
@@ -356,6 +411,8 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
} else if (event.key === "Tab" && items.length > 0) {
downshiftProps.setInputValue(items[0].name);
event.preventDefault();
+ } else if (event.key === "Tab") {
+ (event.nativeEvent as any).preventDownshiftDefault = true;
} else if (
(event.key === "ArrowUp" || event.key === "ArrowDown") &&
event.currentTarget.value.split("\n").length > 1
@@ -383,9 +440,12 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
setCurrentlyInContextQuery(false);
} else if (event.key === "Escape") {
setCurrentlyInContextQuery(false);
- if (downshiftProps.isOpen) {
+ if (downshiftProps.isOpen && items.length > 0) {
downshiftProps.closeMenu();
} else {
+ (event.nativeEvent as any).preventDownshiftDefault = true;
+ // Remove focus from the input
+ inputRef.current?.blur();
// Move cursor back over to the editor
postVscMessage("focusEditor", {});
}
diff --git a/extension/react-app/src/components/HeaderButtonWithText.tsx b/extension/react-app/src/components/HeaderButtonWithText.tsx
index de8e3c98..bcd36972 100644
--- a/extension/react-app/src/components/HeaderButtonWithText.tsx
+++ b/extension/react-app/src/components/HeaderButtonWithText.tsx
@@ -10,6 +10,8 @@ interface HeaderButtonWithTextProps {
disabled?: boolean;
inverted?: boolean;
active?: boolean;
+ className?: string;
+ onKeyDown?: (e: any) => void;
}
const HeaderButtonWithText = (props: HeaderButtonWithTextProps) => {
@@ -29,6 +31,8 @@ const HeaderButtonWithText = (props: HeaderButtonWithTextProps) => {
setHover(false);
}}
onClick={props.onClick}
+ onKeyDown={props.onKeyDown}
+ className={props.className}
>
{props.children}
</HeaderButton>
diff --git a/extension/react-app/src/components/PillButton.tsx b/extension/react-app/src/components/PillButton.tsx
index edef808e..0dcd43eb 100644
--- a/extension/react-app/src/components/PillButton.tsx
+++ b/extension/react-app/src/components/PillButton.tsx
@@ -84,8 +84,34 @@ interface PillButtonProps {
index: number;
addingHighlightedCode?: boolean;
areMultipleItems?: boolean;
+ onDelete?: () => void;
}
+interface StyledButtonProps {
+ warning: string;
+ editing?: boolean;
+ areMultipleItems?: boolean;
+}
+
+const StyledButton = styled(Button)<StyledButtonProps>`
+ position: relative;
+ border-color: ${(props) =>
+ props.warning
+ ? "red"
+ : props.editing && props.areMultipleItems
+ ? vscForeground
+ : "transparent"};
+ border-width: 1px;
+ border-style: solid;
+
+ &:focus {
+ outline: none;
+ border-color: red;
+ border-width: 1px;
+ border-style: solid;
+ }
+`;
+
const PillButton = (props: PillButtonProps) => {
const [isHovered, setIsHovered] = useState(false);
const client = useContext(GUIClientContext);
@@ -132,17 +158,10 @@ const PillButton = (props: PillButtonProps) => {
return (
<>
<div style={{ position: "relative" }}>
- <Button
- style={{
- position: "relative",
- borderColor: props.warning
- ? "red"
- : props.item.editing && props.areMultipleItems
- ? vscForeground
- : "transparent",
- borderWidth: "1px",
- borderStyle: "solid",
- }}
+ <StyledButton
+ areMultipleItems={props.areMultipleItems}
+ warning={props.warning || ""}
+ editing={props.item.editing}
onMouseEnter={() => {
setIsHovered(true);
if (props.onHover) {
@@ -155,6 +174,12 @@ const PillButton = (props: PillButtonProps) => {
props.onHover(false);
}
}}
+ className="pill-button"
+ onKeyDown={(e) => {
+ if (e.key === "Backspace") {
+ props.onDelete?.();
+ }
+ }}
>
{isHovered && (
<GridDiv
@@ -196,7 +221,7 @@ const PillButton = (props: PillButtonProps) => {
</GridDiv>
)}
{props.item.description.name}
- </Button>
+ </StyledButton>
<StyledTooltip id={`edit-${props.index}`}>
{props.item.editing
? "Editing this section (with entire file as context)"