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

X2C-8 Headlessui Package upgrade #225

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
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
28 changes: 23 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"chromatic": "chromatic --exit-zero-on-changes --build-script-name build:storybook"
},
"dependencies": {
"@headlessui/react": "^1.4.0",
"@headlessui/react": "^1.7.11",
"@tailwindcss/forms": "^0.4.0",
"@tailwindcss/line-clamp": "^0.3.1",
"@tippyjs/react": "^4.2.6",
Expand Down
63 changes: 48 additions & 15 deletions src/components/Modal.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { Dialog, Transition } from "@headlessui/react";
import clsx from "clsx";
import PropTypes from "prop-types";
import React, { Fragment } from "react";
import React, { Fragment, useState } from "react";
import { CloseIcon } from "../icons/CloseIcon";

// Widths are for desktop designs because mobile is always full width
const sizes = {
small: "max-w-100",
medium: "max-w-125",
large: "max-w-150",
huge: "max-w-200",
small: "sm:max-w-100",
medium: "sm:max-w-125",
large: "sm:max-w-150",
huge: "sm:max-w-200",
};

export const Modal = ({
Expand All @@ -25,10 +26,36 @@ export const Modal = ({
}
};

const [clientY, setClientY] = useState();
const handleTouchStart = (e) => {
e.stopPropagation();
setClientY(e.touches?.[0].clientY);
};

const handleTouchMove = (e) => {
e.stopPropagation();
const currentY = e.touches?.[0].clientY;
const diffY = currentY - clientY;
if (diffY > 80) {
// The swipe was more than 80px, so close the div
setTimeout(() => {
// Hack because sometimes there are other operations queued up and calling close now won't close it
onClose();
setClientY(null);
}, 100);
}
};

return (
<Transition appear show={isOpen} as={Fragment}>
<Dialog as="div" className="ui-modal fixed inset-0 z-30 overflow-y-auto" onClose={handleOutsideClick}>
<div className="min-h-screen px-4 text-center">
<Dialog
as="div"
className="ui-modal fixed inset-0 z-30"
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onClose={handleOutsideClick}
>
<div className="sm:min-h-screen sm:p-0 sm:text-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
Expand All @@ -41,25 +68,27 @@ export const Modal = ({
<Dialog.Overlay className="ui-modal-overlay fixed inset-0 bg-gray-dark bg-opacity-75 transition-opacity" />
</Transition.Child>

{/* This element is to trick the browser into centering the modal contents. */}
<span className="inline-block h-screen align-middle" aria-hidden="true">
{/* For desktop only this element is to trick the browser into centering the modal contents. */}
<span className="hidden h-screen align-middle sm:inline-block" aria-hidden="true">
&#8203;
</span>

<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enter="ease-in-out duration-500 sm:duration-300"
enterFrom="opacity-0 translate-y-30 sm:translate-y-4 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leave="ease-in duration-500 sm:duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
leaveTo="opacity-0 translate-y-30 sm:translate-y-0 sm:scale-95"
>
<div
className={clsx(
className,
sizes[size],
"inline-block w-full transform overflow-hidden rounded-lg bg-white p-10 text-left align-middle shadow-xl transition-all",
"absolute bottom-0 sm:relative sm:inline-block",
"w-full transform overflow-hidden rounded-tl-2xl rounded-tr-2xl bg-white py-4 px-8",
"text-left shadow-xl transition-all sm:rounded-lg sm:p-10",
)}
>
{onClose ? (
Expand All @@ -72,7 +101,11 @@ export const Modal = ({
</button>
) : null}

{children}
{/* Show a little bar at the top in mobile only to show you can swipe this down */}
<div className="absolute left-1/2 h-1.5 w-18 -translate-x-1/2 rounded-full bg-black opacity-10 sm:hidden" />

{/* The actual content of the modal with padding for mobile only */}
<div className="pt-6 sm:pt-0">{children}</div>
</div>
</Transition.Child>
</div>
Expand Down
3 changes: 3 additions & 0 deletions src/stories/Overlay/Modal.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export const Default = ({ size, shouldCloseOnOutsideClick }) => {

return (
<div>
<p className="my-4">
This shows the desktop & mobile versions of the modal. The mobile version pops up from the bottom
</p>
<Button onClick={toggle}>Click me to launch a modal</Button>

<Modal size={size} isOpen={isOpen} shouldCloseOnOutsideClick={shouldCloseOnOutsideClick} onClose={toggle}>
Expand Down
1 change: 1 addition & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ const spacing = {
14: "56px",
15: "60px",
16: "64px",
18: "72px",
20: "80px",
24: "96px",
25: "100px",
Expand Down