Skip to content

Commit

Permalink
implement newsletter modal
Browse files Browse the repository at this point in the history
  • Loading branch information
bmstefanski committed Oct 4, 2021
1 parent 131d80d commit 75c9e69
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 12 deletions.
8 changes: 7 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@
"titleBar.activeBackground": "#c334b5",
"titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#c334b599",
"titleBar.inactiveForeground": "#e7e7e799"
"titleBar.inactiveForeground": "#e7e7e799",
"editorGroup.border": "#d258c6",
"panel.border": "#d258c6",
"sash.hoverBorder": "#d258c6",
"sideBar.border": "#d258c6",
"statusBarItem.remoteBackground": "#c334b5",
"statusBarItem.remoteForeground": "#e7e7e7"
},
"peacock.color": "#c334b5"
}
2 changes: 2 additions & 0 deletions components/GlobalStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const GlobalStyle = createGlobalStyle`
--tertiary: 231,241,251;
--inputBackground: 255,255,255;
--navbarBackground: 255,255,255;
--modalBackground: 251,251,253;
}
.dark-theme {
Expand All @@ -33,6 +34,7 @@ export const GlobalStyle = createGlobalStyle`
--z-navbar: 8888;
--z-drawer: 9999;
--z-modal: 9999;
}
/* Box sizing rules */
Expand Down
13 changes: 8 additions & 5 deletions components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { NavItems, SingleNavItem } from 'types';
import { HamburgerIcon } from './HamburgerIcon';
import { media } from 'utils/media';
import Button from './Button';
import { useNewsletterModalContext } from 'contexts/newsletter-modal.context';

type NavbarProps = { items: NavItems };
type ScrollingDirections = 'up' | 'down' | 'none';
Expand Down Expand Up @@ -82,12 +83,14 @@ export default function Navbar({ items }: NavbarProps) {
}

function NavItem({ href, title, outlined }: SingleNavItem) {
const { setIsModalOpened } = useNewsletterModalContext();

function showNewsletterModal() {
setIsModalOpened(true);
}

if (outlined) {
return (
<NextLink href="#early-access" passHref>
<CustomButton>{title}</CustomButton>
</NextLink>
);
return <CustomButton onClick={showNewsletterModal}>{title}</CustomButton>;
}

return (
Expand Down
107 changes: 107 additions & 0 deletions components/NewsletterModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import useEscClose from 'hooks/useEscKey';
import styled from 'styled-components';
import { media } from 'utils/media';
import Button from './Button';
import CloseIcon from './CloseIcon';
import Container from './Container';
import Input from './Input';
import Overlay from './Overlay';

export interface NewsletterModalProps {
onClose: () => void;
}

export default function NewsletterModal({ onClose }: NewsletterModalProps) {
useEscClose({ onClose });

return (
<Overlay>
<Container>
<Card>
<CloseIconContainer>
<CloseIcon onClick={onClose} />
</CloseIconContainer>
<Title>Are you ready to enroll to the best newsletter ever?</Title>
<Row>
<CustomInput placeholder="Enter your email..." />
<CustomButton>Submit</CustomButton>
</Row>
</Card>
</Container>
</Overlay>
);
}

const Card = styled.div`
display: flex;
position: relative;
flex-direction: column;
margin: auto;
padding: 10rem 5rem;
background: rgb(var(--modalBackground));
border-radius: 0.6rem;
max-width: 70rem;
overflow: hidden;
${media('<=tablet')} {
padding: 7.5rem 2.5rem;
}
`;

const CloseIconContainer = styled.div`
position: absolute;
right: 2rem;
top: 2rem;
svg {
cursor: pointer;
width: 2rem;
}
`;

const Title = styled.div`
font-size: 3.2rem;
font-weight: bold;
line-height: 1.1;
letter-spacing: -0.03em;
text-align: center;
color: rgb(var(--text));
${media('<=tablet')} {
font-size: 2.6rem;
}
`;

const Row = styled.div`
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
margin-top: 3rem;
${media('<=tablet')} {
flex-direction: column;
}
`;

const CustomButton = styled(Button)`
height: 100%;
padding: 1.8rem;
margin-left: 1.5rem;
box-shadow: var(--shadow-lg);
${media('<=tablet')} {
width: 100%;
margin-left: 0;
margin-top: 1rem;
}
`;

const CustomInput = styled(Input)`
width: 60%;
${media('<=tablet')} {
width: 100%;
}
`;
15 changes: 15 additions & 0 deletions components/Overlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import styled from 'styled-components';

const Overlay = styled.div`
position: fixed;
inset: 0;
background: rgba(var(--secondary), 0.997);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: var(--z-modal);
color: rgb(var(--textSecondary));
`;

export default Overlay;
31 changes: 31 additions & 0 deletions contexts/newsletter-modal.context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { Dispatch, PropsWithChildren, SetStateAction, useContext, useState } from 'react';

interface NewsletterModalContextProps {
isModalOpened: boolean;
setIsModalOpened: Dispatch<SetStateAction<boolean>>;
}

export const NewsletterModalContext = React.createContext<NewsletterModalContextProps | null>(null);

export function NewsletterModalContextProvider<T>({ children }: PropsWithChildren<T>) {
const [isModalOpened, setIsModalOpened] = useState(false);

return (
<NewsletterModalContext.Provider
value={{
isModalOpened,
setIsModalOpened,
}}
>
{children}
</NewsletterModalContext.Provider>
);
}

export function useNewsletterModalContext() {
const context = useContext(NewsletterModalContext);
if (!context) {
throw new Error('useNewsletterModalContext can only be used inside NewsletterModalContextProvider');
}
return context;
}
25 changes: 25 additions & 0 deletions hooks/useEscKey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useCallback, useEffect } from 'react';

export interface UseEscCloseProps {
onClose: () => void;
}

export default function useEscClose({ onClose }: UseEscCloseProps) {
const handleUserKeyPress = useCallback(
(event) => {
const { keyCode } = event;
const escapeKeyCode = 27;
if (keyCode === escapeKeyCode) {
onClose();
}
},
[onClose],
);

useEffect(() => {
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, [handleUserKeyPress]);
}
30 changes: 24 additions & 6 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import { GlobalStyle } from 'components/GlobalStyles';
import Navbar from 'components/Navbar';
import { NavItems } from 'types';
import NavigationDrawer from 'components/NavigationDrawer';
import NewsletterModal from 'components/NewsletterModal';
import { NewsletterModalContextProvider, useNewsletterModalContext } from 'contexts/newsletter-modal.context';
import { PropsWithChildren } from 'react';

const navItems: NavItems = [
{ title: 'Why logoipsum', href: '/' },
Expand Down Expand Up @@ -37,15 +40,30 @@ function MyApp({ Component, pageProps }: AppProps) {
{/* <script async src="https://www.google-analytics.com/analytics.js"></script> */}
</Head>
<GlobalStyle />
<NavigationDrawer items={navItems}>

<Providers>
<Modals />
<Navbar items={navItems} />
</NavigationDrawer>
{/* <NavigationDrawer items={navItems}> */}
{/* <Navbar items={navItems} /> */}
{/* </NavigationDrawer> */}
{standaloneMarkup}
{standaloneMarkup}
</Providers>
</>
);
}

function Providers<T>({ children }: PropsWithChildren<T>) {
return (
<NewsletterModalContextProvider>
<NavigationDrawer items={navItems}>{children}</NavigationDrawer>
</NewsletterModalContextProvider>
);
}

function Modals() {
const { isModalOpened, setIsModalOpened } = useNewsletterModalContext();
if (!isModalOpened) {
return null;
}
return <NewsletterModal onClose={() => setIsModalOpened(false)} />;
}

export default MyApp;

1 comment on commit 75c9e69

@vercel
Copy link

@vercel vercel bot commented on 75c9e69 Oct 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.