diff --git a/site/components/Form/FormCloseButton.stories.tsx b/site/components/Form/FormCloseButton.stories.tsx new file mode 100644 index 0000000000000..6e011a2536d51 --- /dev/null +++ b/site/components/Form/FormCloseButton.stories.tsx @@ -0,0 +1,16 @@ +import { Story } from "@storybook/react" +import React from "react" +import { FormCloseButton, FormCloseButtonProps } from "./FormCloseButton" + +export default { + title: "Form/FormCloseButton", + component: FormCloseButton, + argTypes: { + onClose: { action: "onClose" }, + }, +} + +const Template: Story = (args) => + +export const Example = Template.bind({}) +Example.args = {} diff --git a/site/components/Form/FormCloseButton.test.tsx b/site/components/Form/FormCloseButton.test.tsx new file mode 100644 index 0000000000000..393f7bcc657f0 --- /dev/null +++ b/site/components/Form/FormCloseButton.test.tsx @@ -0,0 +1,70 @@ +import { fireEvent, render, screen } from "@testing-library/react" +import React from "react" +import { FormCloseButton } from "./FormCloseButton" + +describe("FormCloseButton", () => { + it("renders", async () => { + // When + render( + { + return + }} + />, + ) + + // Then + await screen.findByText("ESC") + }) + + it("calls onClose when clicked", async () => { + // Given + const onClose = jest.fn() + + // When + render() + + // Then + const element = await screen.findByText("ESC") + + // When + fireEvent.click(element) + + // Then + expect(onClose).toBeCalledTimes(1) + }) + + it("calls onClose when escape is pressed", async () => { + // Given + const onClose = jest.fn() + + // When + render() + + // Then + const element = await screen.findByText("ESC") + + // When + fireEvent.keyDown(element, { key: "Escape", code: "Esc", charCode: 27 }) + + // Then + expect(onClose).toBeCalledTimes(1) + }) + + it("doesn't call onClose if another key is pressed", async () => { + // Given + const onClose = jest.fn() + + // When + render() + + // Then + const element = await screen.findByText("ESC") + + // When + fireEvent.keyDown(element, { key: "Enter", code: "Enter", charCode: 13 }) + + // Then + expect(onClose).toBeCalledTimes(0) + }) +}) diff --git a/site/components/Form/FormCloseButton.tsx b/site/components/Form/FormCloseButton.tsx new file mode 100644 index 0000000000000..a22f71e8c5b7d --- /dev/null +++ b/site/components/Form/FormCloseButton.tsx @@ -0,0 +1,55 @@ +import IconButton from "@material-ui/core/IconButton" +import { makeStyles } from "@material-ui/core/styles" +import Typography from "@material-ui/core/Typography" +import React, { useEffect } from "react" +import { CloseIcon } from "../Icons/Close" + +export interface FormCloseButtonProps { + onClose: () => void +} + +export const FormCloseButton: React.FC = ({ onClose }) => { + const styles = useStyles() + + useEffect(() => { + const handleKeyPress = (event: KeyboardEvent) => { + if (event.key === "Escape") { + onClose() + } + } + + document.body.addEventListener("keydown", handleKeyPress, false) + + return () => { + document.body.removeEventListener("keydown", handleKeyPress, false) + } + }, []) + + return ( + + + + ESC + + + ) +} + +const useStyles = makeStyles((theme) => ({ + closeButton: { + position: "fixed", + top: theme.spacing(3), + right: theme.spacing(6), + opacity: 0.5, + color: theme.palette.text.primary, + "&:hover": { + opacity: 1, + }, + }, + label: { + position: "absolute", + left: "50%", + top: "100%", + transform: "translate(-50%, 50%)", + }, +})) diff --git a/site/components/Form/index.ts b/site/components/Form/index.ts index 80ddbbac74b3b..08456432c7f74 100644 --- a/site/components/Form/index.ts +++ b/site/components/Form/index.ts @@ -1,3 +1,4 @@ +export * from "./FormCloseButton" export * from "./FormSection" export * from "./FormDropdownField" export * from "./FormTextField" diff --git a/site/components/Icons/Close.tsx b/site/components/Icons/Close.tsx new file mode 100644 index 0000000000000..ab9a44a898941 --- /dev/null +++ b/site/components/Icons/Close.tsx @@ -0,0 +1,8 @@ +import SvgIcon from "@material-ui/core/SvgIcon" +import React from "react" + +export const CloseIcon: typeof SvgIcon = (props) => ( + + + +) diff --git a/site/forms/CreateProjectForm.tsx b/site/forms/CreateProjectForm.tsx index 1a4558e9b2ef8..a930cf487e054 100644 --- a/site/forms/CreateProjectForm.tsx +++ b/site/forms/CreateProjectForm.tsx @@ -4,7 +4,14 @@ import { FormikContextType, useFormik } from "formik" import React from "react" import * as Yup from "yup" -import { DropdownItem, FormDropdownField, FormTextField, FormTitle, FormSection } from "../components/Form" +import { + DropdownItem, + FormDropdownField, + FormTextField, + FormTitle, + FormSection, + FormCloseButton, +} from "../components/Form" import { LoadingButton } from "../components/Button" import { Organization, Project, Provisioner, CreateProjectRequest } from "./../api" @@ -59,6 +66,7 @@ export const CreateProjectForm: React.FC = ({ return (
+ = ({ project, on } /> + + pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy