From 38f0deaaca89b273c30a515a8f053d46f219e26d Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Thu, 10 Feb 2022 01:43:31 +0000 Subject: [PATCH 1/4] fix: Add FormCloseButton for project / workspace create forms --- .../Form/FormCloseButton.stories.tsx | 16 +++++ site/components/Form/FormCloseButton.test.tsx | 67 +++++++++++++++++++ site/components/Form/FormCloseButton.tsx | 56 ++++++++++++++++ site/components/Form/index.ts | 1 + site/components/Icons/Close.tsx | 8 +++ site/forms/CreateProjectForm.tsx | 10 ++- site/forms/CreateWorkspaceForm.tsx | 4 +- 7 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 site/components/Form/FormCloseButton.stories.tsx create mode 100644 site/components/Form/FormCloseButton.test.tsx create mode 100644 site/components/Form/FormCloseButton.tsx create mode 100644 site/components/Icons/Close.tsx 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..193d3112c7efd --- /dev/null +++ b/site/components/Form/FormCloseButton.test.tsx @@ -0,0 +1,67 @@ +import { fireEvent, render, screen, waitFor } from "@testing-library/react" +import React from "react" +import { FormCloseButton, FormCloseButtonProps } 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") + fireEvent.click(element) + + 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..44ced2df2c5c8 --- /dev/null +++ b/site/components/Form/FormCloseButton.tsx @@ -0,0 +1,56 @@ +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(6), + 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 } /> + + Date: Thu, 10 Feb 2022 01:46:29 +0000 Subject: [PATCH 2/4] Tweak styling --- site/components/Form/FormCloseButton.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/site/components/Form/FormCloseButton.tsx b/site/components/Form/FormCloseButton.tsx index 44ced2df2c5c8..a22f71e8c5b7d 100644 --- a/site/components/Form/FormCloseButton.tsx +++ b/site/components/Form/FormCloseButton.tsx @@ -38,7 +38,7 @@ export const FormCloseButton: React.FC = ({ onClose }) => const useStyles = makeStyles((theme) => ({ closeButton: { position: "fixed", - top: theme.spacing(6), + top: theme.spacing(3), right: theme.spacing(6), opacity: 0.5, color: theme.palette.text.primary, @@ -46,7 +46,6 @@ const useStyles = makeStyles((theme) => ({ opacity: 1, }, }, - label: { position: "absolute", left: "50%", From 19fb01b754fd05225c469c8b3c28f5bf5fcae0e0 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Thu, 10 Feb 2022 01:49:45 +0000 Subject: [PATCH 3/4] Clean up tests --- site/components/Form/FormCloseButton.test.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/site/components/Form/FormCloseButton.test.tsx b/site/components/Form/FormCloseButton.test.tsx index 193d3112c7efd..32a46d722f8ad 100644 --- a/site/components/Form/FormCloseButton.test.tsx +++ b/site/components/Form/FormCloseButton.test.tsx @@ -26,8 +26,11 @@ describe("FormCloseButton", () => { // Then const element = await screen.findByText("ESC") + + // When fireEvent.click(element) + // Then expect(onClose).toBeCalledTimes(1) }) From ed80c224d5bf42b58abdcae7054806f92b3465b6 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Thu, 10 Feb 2022 03:45:19 +0000 Subject: [PATCH 4/4] Fix lint issues --- site/components/Form/FormCloseButton.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/components/Form/FormCloseButton.test.tsx b/site/components/Form/FormCloseButton.test.tsx index 32a46d722f8ad..393f7bcc657f0 100644 --- a/site/components/Form/FormCloseButton.test.tsx +++ b/site/components/Form/FormCloseButton.test.tsx @@ -1,6 +1,6 @@ -import { fireEvent, render, screen, waitFor } from "@testing-library/react" +import { fireEvent, render, screen } from "@testing-library/react" import React from "react" -import { FormCloseButton, FormCloseButtonProps } from "./FormCloseButton" +import { FormCloseButton } from "./FormCloseButton" describe("FormCloseButton", () => { it("renders", async () => { 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