diff --git a/functions/package.json b/functions/package.json index 6efd935b..bf3a7e58 100644 --- a/functions/package.json +++ b/functions/package.json @@ -23,7 +23,6 @@ "@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.16", - "@material-ui/core": "^4.11.0", "@sendgrid/mail": "^7.4.0", "@testing-library/cypress": "^7.0.3", "antd": "^4.14.0", diff --git a/package.json b/package.json index bbbd39e2..d795281c 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,6 @@ "@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.16", - "@material-ui/core": "^4.11.0", "@sendgrid/mail": "^7.4.0", "@testing-library/cypress": "^7.0.3", "antd": "^4.14.0", diff --git a/src/__tests__/Navbar/Navbar.test.tsx b/src/__tests__/Navbar/Navbar.test.tsx index 54048857..6e46954f 100644 --- a/src/__tests__/Navbar/Navbar.test.tsx +++ b/src/__tests__/Navbar/Navbar.test.tsx @@ -5,12 +5,13 @@ import Navbar from '../../pages/components/Navbar/Navbar'; describe('Navbar', () => { it('renders the card', async () => { - const { findByTestId } = render( + const { findByText } = render( ); - await findByTestId('sub-menu'); + await findByText('IgboAPI'); + await findByText('Try it Out'); }); }); diff --git a/src/__tests__/Navbar/NavigationMenu.test.tsx b/src/__tests__/Navbar/NavigationMenu.test.tsx new file mode 100644 index 00000000..2d4b061e --- /dev/null +++ b/src/__tests__/Navbar/NavigationMenu.test.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import TestContext from '../components/TestContext'; +import NavigationMenu from '../../pages/components/Navbar/NavigationMenu'; +import { navigationLinks } from '../../shared/constants/navigationLinks'; + +describe('NavigationMenu', () => { + it('renders the navigation menu', async () => { + const { findByText } = render( + + + + ); + + await Promise.all(navigationLinks.map(async ({ label }) => await findByText(label))); + }); +}); diff --git a/src/__tests__/Navbar/NavigationOptions.test.tsx b/src/__tests__/Navbar/NavigationOptions.test.tsx new file mode 100644 index 00000000..e4c3a805 --- /dev/null +++ b/src/__tests__/Navbar/NavigationOptions.test.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import TestContext from '../components/TestContext'; +import NavigationOptions from '../../pages/components/Navbar/NavigationOptions'; +import { navigationLinks } from '../../shared/constants/navigationLinks'; + +describe('NavigationOptions', () => { + it('renders the navigation options', async () => { + const { findByText } = render( + + + + ); + + await Promise.all(navigationLinks.map(async ({ label }) => await findByText(label))); + }); +}); diff --git a/src/__tests__/Navbar/SubMenu.test.tsx b/src/__tests__/Navbar/SubMenu.test.tsx deleted file mode 100644 index e486ca8c..00000000 --- a/src/__tests__/Navbar/SubMenu.test.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import { noop } from 'lodash'; -import { render } from '@testing-library/react'; -import TestContext from '../components/TestContext'; -import SubMenu from '../../pages/components/Navbar/SubMenu'; - -describe('SubMenu', () => { - it('renders the sub menu', async () => { - const { findByText } = render( - - - - ); - - await findByText('Features'); - await findByText('Docs'); - await findByText('Get an API Key'); - }); -}); diff --git a/src/__tests__/components/TestContext.tsx b/src/__tests__/components/TestContext.tsx index f88a6ba0..44ab699c 100644 --- a/src/__tests__/components/TestContext.tsx +++ b/src/__tests__/components/TestContext.tsx @@ -6,6 +6,20 @@ configure({ testIdAttribute: 'data-test' }); jest.mock('i18next'); jest.mock('next/router'); +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}); + const TestContext = ({ children }: { children: ReactElement }) => children; export default TestContext; diff --git a/src/pages/components/Demo/Demo.tsx b/src/pages/components/Demo/Demo.tsx index 9857f379..079a152a 100644 --- a/src/pages/components/Demo/Demo.tsx +++ b/src/pages/components/Demo/Demo.tsx @@ -8,14 +8,16 @@ import { API_ROUTE, DICTIONARY_APP_URL } from '../../../siteConstants'; import { Example, Word } from '../../../types'; import { WordDialect } from '../../../types/word'; -const Demo = ({ searchWord, words }: { searchWord?: string; words: Word[] }) => { +const Demo = ({ searchWord, words }: { searchWord?: string, words: Word[] }) => { const [isLoading, setIsLoading] = useState(true); const [isSearchingWord, setIsSearchingWord] = useState(false); const [keyword, setKeyword] = useState(searchWord); const [queries, setQueries] = useState({}); - const [initialQueries, setInitialQueries] = useState<{ examples?: Example[]; dialects?: WordDialect; word?: string }>( - {} - ); + const [initialQueries, setInitialQueries] = useState<{ + examples?: Example[], + dialects?: WordDialect, + word?: string, + }>({}); const [productionUrl, setProductionUrl] = useState(''); const responseBody = JSON.stringify(words, null, 4); useEffect(() => { @@ -51,7 +53,8 @@ const Demo = ({ searchWord, words }: { searchWord?: string; words: Word[] }) => }; const constructRequestUrl = () => { - const appendQueries = constructQueryString() || queryString.stringify(omit(initialQueries, ['word'])); + const appendQueries = + constructQueryString() || queryString.stringify(omit(initialQueries, ['word'])); const requestUrl = `${productionUrl || API_ROUTE}/api/v1/words?keyword=${keyword || ''}` + `${keyword && appendQueries ? '&' : ''}` + @@ -78,7 +81,12 @@ const Demo = ({ searchWord, words }: { searchWord?: string; words: Word[] }) => return !isLoading ? ( - + Test Drive the API @@ -156,7 +164,7 @@ const Demo = ({ searchWord, words }: { searchWord?: string; words: Word[] }) => - + diff --git a/src/pages/components/Navbar/Navbar.tsx b/src/pages/components/Navbar/Navbar.tsx index a2e8a857..23838f55 100644 --- a/src/pages/components/Navbar/Navbar.tsx +++ b/src/pages/components/Navbar/Navbar.tsx @@ -1,32 +1,26 @@ -import React, { useState } from 'react'; -import { Box, Button, Heading, Image, Link as ChakraLink } from '@chakra-ui/react'; -import useMediaQuery from '@material-ui/core/useMediaQuery'; +import React from 'react'; +import { Box, Heading, Link as ChakraLink, Show } from '@chakra-ui/react'; import { Link } from 'react-scroll'; -import SubMenu from './SubMenu'; +import NavigationMenu from './NavigationMenu'; +import NavigationOptions from './NavigationOptions'; import TryItOut from '../TryItOut'; -const menuIcon = ( - - - -); - -const Navbar = ({ to = '/' }: { to?: string }) => { - const [isMenuVisible, setIsMenuVisible] = useState(false); - const matchesLargeScreenQuery = useMediaQuery('(min-width:1024px)'); - return ( - ( + + style={{ zIndex: 2 }} + borderColor="gray.300" + borderWidth="1px" + borderRadius="md" + mt="4" + > + + pb="0" + > {to ? ( @@ -39,32 +33,21 @@ const Navbar = ({ to = '/' }: { to?: string }) => { to="homepage-container" smooth offset={-100} - duration={600}> + duration={600} + > Igbo API )} - {!matchesLargeScreenQuery ? ( - - ) : null} - setIsMenuVisible(false)} - /> - + + + - ); -}; + + + + + +); export default Navbar; diff --git a/src/pages/components/Navbar/NavigationMenu.tsx b/src/pages/components/Navbar/NavigationMenu.tsx new file mode 100644 index 00000000..3f86b813 --- /dev/null +++ b/src/pages/components/Navbar/NavigationMenu.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import Link from 'next/link'; +import { Menu, MenuButton, MenuList, MenuItem, IconButton } from '@chakra-ui/react'; +import { FiChevronDown } from 'react-icons/fi'; +import { navigationLinks } from '../../../shared/constants/navigationLinks'; + +const NavigationMenu = () => ( + + } + variant="ghost" + _hover={{ backgroundColor: 'transparent' }} + _focus={{ backgroundColor: 'transparent' }} + _active={{ backgroundColor: 'transparent' }} + /> + + {navigationLinks.map(({ href, label }) => ( + + {label} + + ))} + + +); + +export default NavigationMenu; diff --git a/src/pages/components/Navbar/NavigationOptions.tsx b/src/pages/components/Navbar/NavigationOptions.tsx new file mode 100644 index 00000000..017da91d --- /dev/null +++ b/src/pages/components/Navbar/NavigationOptions.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { UnorderedList, ListItem, Link } from '@chakra-ui/react'; +import { navigationLinks } from '../../../shared/constants/navigationLinks'; + +const NavigationOptions = () => ( + + x + {navigationLinks.map(({ href, label }) => ( + + + {label} + + + ))} + +); +export default NavigationOptions; diff --git a/src/pages/components/Navbar/SubMenu.tsx b/src/pages/components/Navbar/SubMenu.tsx deleted file mode 100644 index 172a49a1..00000000 --- a/src/pages/components/Navbar/SubMenu.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react'; -import { UnorderedList, ListItem, Link } from '@chakra-ui/react'; - -const SubMenu = ({ isVisible, onSelect }: { isVisible: boolean; onSelect: () => void }) => ( - - - - Features - - - - - About - - - - - Docs - - - - - Get an API Key - - - -); -export default SubMenu; diff --git a/src/pages/components/TryItOut/TryItOut.tsx b/src/pages/components/TryItOut/TryItOut.tsx index dff8b790..ad095215 100644 --- a/src/pages/components/TryItOut/TryItOut.tsx +++ b/src/pages/components/TryItOut/TryItOut.tsx @@ -16,6 +16,7 @@ const TryItOut = ({ size, ...props }: ButtonProps) => { color="white" transitionDuration="200ms" size={size || 'lg'} + px="6" onClick={() => { router.push('/#try-it-out'); window.scrollBy({ top: -100, behavior: 'smooth' }); diff --git a/src/shared/constants/navigationLinks.ts b/src/shared/constants/navigationLinks.ts new file mode 100644 index 00000000..58a89910 --- /dev/null +++ b/src/shared/constants/navigationLinks.ts @@ -0,0 +1,18 @@ +export const navigationLinks: { href: string, label: string }[] = [ + { + href: '#features', + label: 'Features', + }, + { + href: '/about', + label: 'About', + }, + { + href: '/docs', + label: 'Docs', + }, + { + href: '/signup', + label: 'Get an API Key', + }, +]; diff --git a/src/styles.css b/src/styles.css index de9ca290..460fdde5 100644 --- a/src/styles.css +++ b/src/styles.css @@ -42,35 +42,6 @@ @apply duration-200; } -.navbar { - @apply transition-all; - @apply flex; - @apply flex-col; - @apply absolute; - @apply w-screen; - @apply text-gray-800; - @apply list-none; - @apply bg-white; - @apply top-0; - @apply py-10; - @apply mt-16; - @apply px-5; - @apply shadow-md; - @apply rounded-md; - @apply select-none; -} - -.navbar li:hover { - @apply text-gray-500; -} - -.transparent-navbar { - @apply text-white; -} -.transparent-navbar li:hover { - @apply text-blue-200; -} - .error { @apply text-red-600; } @@ -113,24 +84,6 @@ } } -@media (min-width: 1024px) { - .navbar { - @apply flex-row; - @apply w-auto; - @apply relative; - @apply bg-transparent; - @apply py-0; - @apply mt-0; - @apply px-0; - @apply shadow-none; - } - - .transparent-navbar, - .transition-navbar:hover { - @apply text-white; - } -} - .rFix { transform: rotateX(25deg); }