diff options
Diffstat (limited to 'extension/react-app/src/components/PillButton.tsx')
-rw-r--r-- | extension/react-app/src/components/PillButton.tsx | 257 |
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> ); }; |