Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GEN-1117] feat: reusable modal component #8

Merged
merged 5 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frontend/webapp/app/globals.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Preload key fonts in your global CSS */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Kode+Mono:wght@400;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Kode+Mono:wght@100;200;300;400;500;600;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;700&display=swap');
69 changes: 19 additions & 50 deletions frontend/webapp/components/setup/headers/header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Button, Text } from '@/reuseable-components';
import theme from '@/styles/theme';
import Image from 'next/image';
import React from 'react';
import styled from 'styled-components';
import { NavigationButtons, Text } from '@/reuseable-components';

interface SetupHeaderProps {
onBack?: () => void;
onNext?: () => void;
onBack: () => void;
onNext: () => void;
}

const HeaderContainer = styled.div`
Expand All @@ -21,24 +20,12 @@ const HeaderContainer = styled.div`

const Title = styled(Text)``;

const HeaderButton = styled(Button)`
display: flex;
align-items: center;
gap: 8px;
`;

const Logo = styled.div`
display: flex;
align-items: center;
font-size: 1.2em;
`;

const NavigationButtons = styled.div`
display: flex;
gap: 8px;
align-items: center;
`;

export const SetupHeader: React.FC<SetupHeaderProps> = ({ onBack, onNext }) => {
return (
<HeaderContainer>
Expand All @@ -51,40 +38,22 @@ export const SetupHeader: React.FC<SetupHeaderProps> = ({ onBack, onNext }) => {
/>
</Logo>
<Title family={'secondary'}>START WITH ODIGOS</Title>
<NavigationButtons>
<HeaderButton variant="secondary" onClick={onBack}>
<Image
src="/icons/common/arrow-white.svg"
alt="back"
width={8}
height={12}
/>
<Text
color={theme.colors.secondary}
size={14}
decoration={'underline'}
family="secondary"
>
BACK
</Text>
</HeaderButton>
<HeaderButton variant="primary" onClick={onNext}>
<Text
decoration={'underline'}
color={theme.colors.dark_grey}
size={14}
family="secondary"
>
NEXT
</Text>
<Image
src="/icons/common/arrow-black.svg"
alt="next"
width={8}
height={12}
/>
</HeaderButton>
</NavigationButtons>
<NavigationButtons
buttons={[
{
label: 'BACK',
iconSrc: '/icons/common/arrow-white.svg',
onClick: onBack,
variant: 'secondary',
},
{
label: 'NEXT',
iconSrc: '/icons/common/arrow-black.svg',
onClick: onNext,
variant: 'primary',
},
]}
/>
</HeaderContainer>
);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import React, { useEffect, useState } from 'react';
import { Button, SectionTitle, Text } from '@/reuseable-components';
import {
Button,
Modal,
NavigationButtons,
SectionTitle,
Text,
} from '@/reuseable-components';
import styled from 'styled-components';
import Image from 'next/image';
import theme from '@/styles/theme';
Expand All @@ -21,6 +27,14 @@ const AddDestinationButton = styled(Button)`

export function ChooseDestinationContainer() {
const { data, loading, error } = useQuery(GET_DESTINATION_TYPE);
const [isModalOpen, setModalOpen] = useState(false);

const handleOpenModal = () => setModalOpen(true);
const handleCloseModal = () => setModalOpen(false);
const handleSubmit = () => {
console.log('Action submitted');
setModalOpen(false);
};

useEffect(() => {
if (error) {
Expand All @@ -36,7 +50,10 @@ export function ChooseDestinationContainer() {
description="Add backend destinations where collected data will be sent and configure their settings."
/>
<AddDestinationButtonWrapper>
<AddDestinationButton variant="secondary">
<AddDestinationButton
variant="secondary"
onClick={() => handleOpenModal()}
>
<Image
src="/icons/common/plus.svg"
alt="back"
Expand All @@ -52,6 +69,33 @@ export function ChooseDestinationContainer() {
ADD DESTINATION
</Text>
</AddDestinationButton>
<Modal
isOpen={isModalOpen}
actionComponent={
<NavigationButtons
buttons={[
// {
// label: 'BACK',
// iconSrc: '/icons/common/arrow-white.svg',
// onClick: () => {},
// variant: 'secondary',
// },
{
label: 'NEXT',
iconSrc: '/icons/common/arrow-black.svg',
onClick: () => {},
variant: 'primary',
},
]}
/>
}
header={{
title: 'Modal Title',
}}
onClose={handleCloseModal}
>
<p>This is the modal content.</p>
</Modal>
</AddDestinationButtonWrapper>
</>
);
Expand Down
14 changes: 14 additions & 0 deletions frontend/webapp/public/icons/common/x.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions frontend/webapp/reuseable-components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export * from './divider';
export * from './counter';
export * from './toggle';
export * from './checkbox';
export * from './modal';
export * from './navigation-buttons';
129 changes: 129 additions & 0 deletions frontend/webapp/reuseable-components/modal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import React from 'react';
import Image from 'next/image';
import { Text } from '../text';
import ReactDOM from 'react-dom';
import styled from 'styled-components';
import { Button } from '../button';

interface ModalProps {
isOpen: boolean;
header: {
title: string;
};
actionComponent?: React.ReactNode;
onClose: () => void;
children: React.ReactNode;
}

const Overlay = styled.div`
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(17, 17, 17, 0.8);
backdrop-filter: blur(1px);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
`;

const ModalWrapper = styled.div`
background: ${({ theme }) => theme.colors.translucent_bg};
border-radius: 40px;
border: ${({ theme }) => `1px solid ${theme.colors.border}`};
width: 1080px;
box-shadow: 0px 1px 1px 0px rgba(17, 17, 17, 0.8),
0px 2px 2px 0px rgba(17, 17, 17, 0.8), 0px 5px 5px 0px rgba(17, 17, 17, 0.8),
0px 10px 10px 0px rgba(17, 17, 17, 0.8),
0px 0px 8px 0px rgba(17, 17, 17, 0.8);
`;

const ModalHeader = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
height: 80px;
border-bottom: 1px solid ${({ theme }) => theme.colors.border};
padding: 0 24px;
`;

const ModalCloseButton = styled.div`
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
`;

const HeaderActionsWrapper = styled.div`
display: flex;
align-items: center;
gap: 8px;
`;

const ModalContent = styled.div`
padding: 1rem;
`;

const ModalTitleContainer = styled.div`
position: absolute;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
justify-content: center;
width: 100%;
pointer-events: none;
`;

const ModalTitle = styled(Text)`
text-transform: uppercase;
font-family: ${({ theme }) => theme.font_family.secondary};
pointer-events: auto;
`;

const CancelText = styled(Text)`
text-transform: uppercase;
font-weight: 600;
font-size: 14px;
font-family: ${({ theme }) => theme.font_family.secondary};
text-decoration: underline;
cursor: pointer;
`;

const Modal: React.FC<ModalProps> = ({
isOpen,
header,
onClose,
children,
actionComponent,
}) => {
if (!isOpen) return null;

return ReactDOM.createPortal(
<Overlay>
<ModalWrapper>
<ModalHeader>
<ModalCloseButton onClick={onClose}>
<Image
src="/icons/common/x.svg"
alt="close"
width={15}
height={12}
/>
<CancelText>{'Cancel'}</CancelText>
</ModalCloseButton>
<ModalTitleContainer>
<ModalTitle>{header.title}</ModalTitle>
</ModalTitleContainer>
<HeaderActionsWrapper>{actionComponent}</HeaderActionsWrapper>
</ModalHeader>
<ModalContent>{children}</ModalContent>
</ModalWrapper>
</Overlay>,
document.body
);
};

export { Modal };
Loading
Loading