Change modal component to reach-ui modal.

This commit is contained in:
Bradley Shellnut 2021-11-18 17:41:53 -08:00
parent e84e20e0f1
commit 27b650e5ff
6 changed files with 15022 additions and 138 deletions

View file

@ -1,95 +1,113 @@
import { createPortal } from 'react-dom'; import { DialogContent, DialogOverlay } from '@reach/dialog';
import VisuallyHidden from '@reach/visually-hidden';
import '@reach/dialog/styles.css';
import styled from 'styled-components'; import styled from 'styled-components';
const ModalOverlayStyles = styled.div` const DialogStyles = styled.div`
background-color: #999999; @media (max-width: 1000px) {
height: 100vh; div[data-reach-dialog-content] {
left: 0; width: 55vw;
opacity: 0.5; }
position: fixed; }
top: 0; @media (max-width: 800px) {
width: 100vw; div[data-reach-dialog-content] {
z-index: 500; width: 60vw;
}
}
@media (max-width: 650px) {
div[data-reach-dialog-content] {
width: 70vw;
}
}
@media (max-width: 600px) {
div[data-reach-dialog-content] {
width: 80vw;
}
}
@media (max-width: 550px) {
div[data-reach-dialog-content] {
width: 90vw;
}
}
@media (max-width: 500px) {
div[data-reach-dialog-content] {
width: 95vw;
}
}
`; `;
const ModalWrapperStyles = styled.div` const ModalCloseStyles = styled.button`
display: flex; color: var(--black);
justify-content: center; font-size: 2.5rem;
left: 0; text-shadow: none;
outline: 0;
overflow-x: hidden; &:hover {
overflow-y: auto; transition: 0.3s ease transform;
position: fixed; transform: translate3d(0, -2px, 0);
top: 25%; }
width: 100%;
z-index: 1000;
`; `;
const ModalStyles = styled.div` const StandardModalHeader = (props) => {
align-items: center; const { onHide, caption } = props;
background: var(--background); return (
border-radius: 4px; <>
display: flex; <div
flex-direction: column; className="modal-header"
margin: 1.8rem; style={{
max-width: 500px; display: 'flex',
position: relative; flexWrap: 'nowrap',
z-index: 100; alignItems: 'center',
`; justifyContent: 'space-between',
}}
>
<div className="modal-title">{caption}</div>
<ModalCloseStyles
type="button"
className="close-button"
onClick={onHide}
>
<VisuallyHidden>Close</VisuallyHidden>
<span>×</span>
</ModalCloseStyles>
</div>
<hr />
</>
);
};
const ModalHeaderStyles = styled.div` export default function Modal({
align-items: center; isOpen,
display: flex; onHide,
flex-direction: column; contentLabel,
padding: 1.8rem 0.95rem; headerCaption,
`; focusRef = null,
children,
const ModalTitleStyles = styled.h2` }) {
margin-bottom: 0.4rem; return (
`; <DialogOverlay
allowPinchZoom
const ModalButtonStyles = styled.button` initialFocusRef={focusRef}
// border-top: 1px solid var(--primary); onDismiss={onHide}
cursor: pointer; isOpen={isOpen}
font-weight: bold; >
padding: 2rem; <DialogStyles>
width: 100%; <DialogContent
`; aria-label={contentLabel}
style={{
const ModalDescriptionStyles = styled.span` background: 'var(--modalBackground)',
padding: 2rem; boxShadow: 'var(--level-4)',
font-size: 2rem; borderRadius: 'var(--borderRadius)',
text-align: center; maxWidth: '55rem',
`; }}
>
const Modal = ({ isVisible, hideModal, title, message, children }) => <div>
isVisible <div>
? createPortal( <StandardModalHeader caption={headerCaption} onHide={onHide} />
<> {children}
<ModalOverlayStyles /> </div>
<ModalWrapperStyles </div>
aria-modal </DialogContent>
aria-hidden={!isVisible} </DialogStyles>
tabIndex={-1} </DialogOverlay>
role="dialog" );
aria-label={title} }
>
<ModalStyles>
<ModalHeaderStyles>
<ModalTitleStyles>{title}</ModalTitleStyles>
<ModalDescriptionStyles>
{message}
{children}
</ModalDescriptionStyles>
</ModalHeaderStyles>
<ModalButtonStyles type="button" onClick={hideModal}>
Close
</ModalButtonStyles>
</ModalStyles>
</ModalWrapperStyles>
</>,
document.body
)
: null;
export default Modal;

View file

@ -51,6 +51,9 @@ const GlobalStyles = createGlobalStyle`
--linkHover: var(--lightViolet); --linkHover: var(--lightViolet);
--lightHairLine: var(--lightGrey); --lightHairLine: var(--lightGrey);
/* Modal */
--modalBackground: var(--background);
/* Styles */ /* Styles */
--line: solid 1px var(--lineColor); --line: solid 1px var(--lineColor);

14843
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -9,45 +9,49 @@
"start": "next start" "start": "next start"
}, },
"dependencies": { "dependencies": {
"@reach/dialog": "^0.16.2",
"@reach/portal": "^0.16.2",
"@reach/visually-hidden": "^0.16.0",
"babel-core": "^6.26.3", "babel-core": "^6.26.3",
"babel-plugin-styled-components": "^1.12.0", "babel-plugin-styled-components": "^1.13.3",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"cloudinary-build-url": "^0.2.1", "cloudinary-build-url": "^0.2.1",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"escape-html": "^1.0.3",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"mongodb": "^3.6.9", "mongodb": "^4.1.4",
"mongoose": "^5.12.13", "mongoose": "^6.0.12",
"next": "^10.2.3", "next": "^11.1.2",
"next-iron-session": "^4.2.0", "next-iron-session": "^4.2.0",
"next-with-apollo": "^5.1.1", "next-with-apollo": "^5.2.1",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-icons": "^4.2.0", "react-icons": "^4.3.1",
"styled-components": "^5.3.0", "styled-components": "^5.3.1",
"swr": "^0.5.6", "swr": "^0.5.6",
"waait": "^1.0.5" "waait": "^1.0.5"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.14.3", "@babel/core": "^7.16.0",
"@babel/preset-env": "^7.14.4", "@babel/preset-env": "^7.16.0",
"@typescript-eslint/eslint-plugin": "^4.26.1", "@typescript-eslint/eslint-plugin": "^4.32.0",
"@typescript-eslint/parser": "^4.26.1", "@typescript-eslint/parser": "^4.32.0",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"eslint": "^7.28.0", "eslint": "^7.32.0",
"eslint-config-airbnb": "^18.2.1", "eslint-config-airbnb": "^18.2.1",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-config-wesbos": "^2.0.0-beta.7", "eslint-config-wesbos": "^2.1.0",
"eslint-plugin-html": "^6.1.2", "eslint-plugin-html": "^6.2.0",
"eslint-plugin-import": "^2.23.4", "eslint-plugin-import": "^2.25.3",
"eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^3.4.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.24.0", "eslint-plugin-react": "^7.27.0",
"eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-hooks": "^4.3.0",
"prettier": "^2.3.1", "prettier": "^2.4.1",
"typescript": "^4.3.2" "typescript": "^4.4.4"
}, },
"eslintConfig": { "eslintConfig": {
"extends": [ "extends": [
@ -108,4 +112,4 @@
} }
} }
} }
} }

View file

@ -10,7 +10,6 @@ import Group from '../../models/Group';
import Guest from '../../models/Guest'; import Guest from '../../models/Guest';
import connectDb from '../../utils/db'; import connectDb from '../../utils/db';
import { CalendarIcon, MapIcon } from '../../lib/svgs'; import { CalendarIcon, MapIcon } from '../../lib/svgs';
import useModal from '../../lib/useModal';
import Modal from '../../components/Modal'; import Modal from '../../components/Modal';
const RSVPGroupStyles = styled.div` const RSVPGroupStyles = styled.div`
@ -131,6 +130,14 @@ const ErrorContactStyles = styled.p`
} }
`; `;
const ModalContentStyles = styled.div`
display: flex;
flex-direction: column;
align-items: center;
font-size: 2rem;
text-align: center;
`;
export default function SingleGroupPage({ group }) { export default function SingleGroupPage({ group }) {
const { guests, note } = group; const { guests, note } = group;
const { user } = useUser({ redirectTo: '/login' }); const { user } = useUser({ redirectTo: '/login' });
@ -139,9 +146,12 @@ export default function SingleGroupPage({ group }) {
const [message, setMessage] = useState(''); const [message, setMessage] = useState('');
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [groupHasPlusOne, setGroupHasPlusOne] = useState(false); const [groupHasPlusOne, setGroupHasPlusOne] = useState(false);
const { isVisible, toggleModal } = useModal(); const [showModal, setShowModal] = useState(false);
const address = 'Central Park, New York, New York, USA'; const address = 'Central Park, New York, New York, USA';
const openModal = () => setShowModal(true);
const closeModal = () => setShowModal(false);
function getInitialFormData() { function getInitialFormData() {
const initial = {}; const initial = {};
for (const guest of guests) { for (const guest of guests) {
@ -163,9 +173,8 @@ export default function SingleGroupPage({ group }) {
return initial; return initial;
} }
const { inputs, handleChange, clearForm, resetForm } = useForm( const { inputs, handleChange, clearForm, resetForm } =
getInitialFormData useForm(getInitialFormData);
);
if (!user || user.isLoggedIn === false) { if (!user || user.isLoggedIn === false) {
return <Layout>Loading...</Layout>; return <Layout>Loading...</Layout>;
@ -205,7 +214,7 @@ export default function SingleGroupPage({ group }) {
body.guests.length > 1 ? 's' : '' body.guests.length > 1 ? 's' : ''
}. Don't forget to save the date!!` }. Don't forget to save the date!!`
); );
toggleModal(); openModal();
} else { } else {
setErrorCount(errorCount + 1); setErrorCount(errorCount + 1);
setErrorMsg('Unable to RSVP Your Group'); setErrorMsg('Unable to RSVP Your Group');
@ -370,14 +379,21 @@ export default function SingleGroupPage({ group }) {
)} )}
<button type="submit">Submit RSVP</button> <button type="submit">Submit RSVP</button>
</FormStyles> </FormStyles>
<Modal isVisible={isVisible} hideModal={toggleModal} title="RSVP Success"> <Modal
<p>{message}</p> isOpen={showModal}
<div> onHide={closeModal}
<p>Monday, June 3, 2030 at 5:00 PM</p> contentLabel="RSVP Success"
<a href="/myevents.ics" aria-label="Click to add to calendar"> headerCaption={<h2>RSVP Success</h2>}
<CalendarIcon /> Add to Calendar >
</a> <ModalContentStyles>
</div> <p>{message}</p>
<div>
<p>Saturday, June 25, 2022 at 5:00 PM</p>
<a href="/ibwedding.ics" aria-label="Click to add to calendar">
<CalendarIcon /> Add to Calendar
</a>
</div>
</ModalContentStyles>
</Modal> </Modal>
</div> </div>
); );
@ -389,20 +405,21 @@ export async function getServerSideProps({ params }) {
// TODO: REMOVE THIS WHEN TAKING YOUR SITE TO PRODUCTION // TODO: REMOVE THIS WHEN TAKING YOUR SITE TO PRODUCTION
if (process.env.SITE_ENV === 'TEST_SITE') { if (process.env.SITE_ENV === 'TEST_SITE') {
const group = {};
group.id = params.id; group.id = params.id;
group.guests = [{ group.guests = [
id: 'TEST_GUEST_ID_12345', {
firstName: 'Test', id: 'TEST_GUEST_ID_12345',
lastName: 'Lastname', firstName: 'Test',
rsvpStatus: false, lastName: 'Lastname',
dietaryNotes: '', rsvpStatus: false,
songRequests: '', dietaryNotes: '',
hasPlusOne: true, songRequests: '',
plusOne: false, hasPlusOne: true,
plusOneFirstName: '', plusOne: false,
plusOneLastName: '', plusOneFirstName: '',
}]; plusOneLastName: '',
},
];
group.note = ''; group.note = '';
return { props: { group } }; return { props: { group } };
} }

View file

@ -1,4 +1,3 @@
// import mongo from 'mongodb';
import mongoose from 'mongoose'; import mongoose from 'mongoose';
const url = process.env.MONGO_URL; const url = process.env.MONGO_URL;