diff --git a/app/components/FilterMenu.tsx b/app/components/FilterMenu.tsx new file mode 100644 index 0000000..1b6939a --- /dev/null +++ b/app/components/FilterMenu.tsx @@ -0,0 +1,99 @@ +import { useState, FormEvent } from "react"; +import { + Button, + Flex, + FormControl, + FormLabel, + Heading, + Show, + Hide, + Select, + HStack, +} from "@nycplanning/streetscape"; +import { ChevronDownIcon } from "@chakra-ui/icons"; + +export type GeographyType = "cd" | "ccd" | null; + +export const FilterMenu = ({ onClose }: FilterMenuProps) => { + const [geographyType, setGeorgaphyType] = useState("cd"); + return ( + + + { + onClose(); + }} + role={"button"} + width={"full"} + height={8} + color={"gray.300"} + aria-label="Close geography filter menu" + /> + + + + + Filter by Geography + + + + Geography Type + + + + {geographyType !== "ccd" ? ( + + Borough + + + ) : null} + + District + + + + + + + ); +}; + +export interface FilterMenuProps { + onClose: () => void; +} diff --git a/app/components/Overlay.tsx b/app/components/Overlay.tsx new file mode 100644 index 0000000..0766d48 --- /dev/null +++ b/app/components/Overlay.tsx @@ -0,0 +1,51 @@ +import { Flex, Button, Hide, Show } from "@nycplanning/streetscape"; +import { ReactNode, useState } from "react"; +import { FilterMenu } from "./FilterMenu"; + +export const Overlay = () => { + const [shouldShowFilterMenu, setShouldShowFilterMenu] = useState(false); + + return ( + + + setShouldShowFilterMenu(false)} /> + + {shouldShowFilterMenu ? ( + + setShouldShowFilterMenu(false)} /> + + ) : null} + {!shouldShowFilterMenu ? ( + + + + ) : null} + + ); +}; + +export interface OverlayProps { + children: ReactNode; +} diff --git a/app/root.tsx b/app/root.tsx index e7ea64c..faa17df 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -10,6 +10,7 @@ import { } from "@remix-run/react"; import { Atlas } from "./components/atlas.client"; import { ClientOnly } from "remix-utils/client-only"; +import { Overlay } from "./components/Overlay"; function Document({ children, @@ -22,6 +23,7 @@ function Document({ + {title} {/* Silence /favicon.ico error by pointing to null image. Remove link to null image after creating valid favicon. */} - Loading map...}> - {() => } + + {() => ( + <> + + + )} diff --git a/package-lock.json b/package-lock.json index 239a357..5e51f4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,10 +1,14 @@ { "name": "ae-cp-map", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { + "name": "ae-cp-map", + "version": "0.0.1", "dependencies": { + "@chakra-ui/icons": "^2.1.1", "@deck.gl/react": "^9.0.8", "@emotion/react": "^11.11.3", "@emotion/server": "^11.11.0", diff --git a/package.json b/package.json index 6ce38d2..ce875a0 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "kubb:generate": "kubb generate" }, "dependencies": { + "@chakra-ui/icons": "^2.1.1", "@deck.gl/react": "^9.0.8", "@emotion/react": "^11.11.3", "@emotion/server": "^11.11.0", diff --git a/tests/app.spec.ts b/tests/app.spec.ts new file mode 100644 index 0000000..48476d9 --- /dev/null +++ b/tests/app.spec.ts @@ -0,0 +1,29 @@ +import { test, expect } from '@playwright/test'; + +test('filter by geography button on mobile', async ({ page }) => { + await page.goto('http://localhost:5173/'); + await page.setViewportSize({ + width: 375, + height: 812, + }); + await page.getByText('Filter by Geography').click(); + await expect(page.getByText('Geography Type')).toBeVisible(); +}); + +test('filter menu shows by default on desktop', async ({ page }) => { + await page.goto('http://localhost:5173/'); + await expect( + page.getByRole('button', { name: 'Filter by Geography', exact: true }), + ).not.toBeVisible(); + await page.getByText('Filter by Geography').click(); + await expect(page.getByText('Geography Type')).toBeVisible(); +}); + +test('selecting City Council District hides borough select input', async ({ + page, +}) => { + await page.goto('http://localhost:5173/'); + await expect(page.getByLabel('Borough')).toBeVisible(); + await page.getByLabel('Geography Type').selectOption('City Council District'); + await expect(page.getByLabel('Borough')).not.toBeVisible(); +}); diff --git a/tests/example.spec.ts b/tests/example.spec.ts deleted file mode 100644 index b60fe7c..0000000 --- a/tests/example.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { test, expect } from "@playwright/test"; - -test("has title", async ({ page }) => { - await page.goto("https://playwright.dev/"); - - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Playwright/); -}); - -test("get started link", async ({ page }) => { - await page.goto("https://playwright.dev/"); - - // Click the get started link. - await page.getByRole("link", { name: "Get started" }).click(); - - // Expects page to have a heading with the name of Installation. - await expect( - page.getByRole("heading", { name: "Installation" }), - ).toBeVisible(); -});