Skip to content

Commit

Permalink
Merge pull request #10 from dalurness/jesse/add-dialogs-to-solution
Browse files Browse the repository at this point in the history
Add Dialog to solution
  • Loading branch information
janka102 authored Nov 11, 2024
2 parents 5175405 + aa8ceb1 commit 5f9348d
Show file tree
Hide file tree
Showing 14 changed files with 631 additions and 435 deletions.
30 changes: 30 additions & 0 deletions src/components/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Modal, type ModalProps } from "./Modal";

export interface DialogProps extends ModalProps {}

/**
* Open a dialog popup that can be dimissed by clicking outside of it.
*
* This is opened programatically and the content is centered on the screen.
*/
export function Dialog({
open = false,
onToggle = () => {},
children,
className = "",
}: DialogProps) {
return (
// For some reason TypeScript complains if these are possibly undefined, so set defaults above
<Modal open={open} onToggle={onToggle} className={className}>
{(args) => (
<div className="fixed inset-0 z-10 w-screen pointer-events-none">
<div className="flex min-h-full items-center justify-center p-4 sm:p-0">
<div className="relative rounded-lg overflow-hidden bg-yeti-light-1 shadow-xl pointer-events-auto w-full sm:my-8 sm:max-w-lg">
{typeof children === "function" ? children(args) : children}
</div>
</div>
</div>
)}
</Modal>
);
}
67 changes: 67 additions & 0 deletions src/components/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useEffect, useRef, type ReactNode } from "react";
import { twMerge } from "tailwind-merge";

export interface ModalProps {
open?: boolean;
onToggle?: (open: boolean) => void;
button?: ReactNode | (({ isOpen }: { isOpen: boolean }) => ReactNode);
children:
| ReactNode
| (({
isOpen,
close,
}: {
isOpen: boolean;
close: () => void;
}) => ReactNode);
className?: string;
}

/**
* Open a modal popup that can be dimissed by clicking outside of it.
*
* This has a button that opens the modal and anything can be displayed inside.
*/
export function Modal({
open,
onToggle,
button,
children,
className,
}: ModalProps) {
const details = useRef<HTMLDetailsElement>(null);
const isOpen = details.current?.open === true;
function close() {
if (details.current) {
details.current.open = false;
}
}

useEffect(() => {
function onToggleEvent() {
onToggle?.(details.current!.open);
}
details.current?.addEventListener("toggle", onToggleEvent);

return () => {
details.current?.removeEventListener("toggle", onToggleEvent);
};
}, [onToggle]);

return (
<details ref={details} className={twMerge(className, "group")} open={open}>
<summary
// when no button, hide off-screen and make it so you can't tab to it
className={twMerge("list-none", !button && "fixed -top-96 -left-96")}
tabIndex={button ? undefined : -1}
>
{typeof button === "function" ? button({ isOpen }) : button}

{/* fullscreen background element that you can click to close when it's open */}
<div className="fixed inset-0 bg-yeti-dark-9/50 hidden group-open:block cursor-pointer"></div>
</summary>

{typeof children === "function" ? children({ isOpen, close }) : children}
</details>
);
}
21 changes: 11 additions & 10 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { MdCalendarMonth, MdEventBusy } from "react-icons/md";
import { Calendar } from "./Calendar";
import { Link } from "./Link";
import { Modal } from "./Modal";

const { BASE_URL } = import.meta.env;

Expand All @@ -19,19 +20,19 @@ export function Navbar({ day }: NavbarProps) {
<img src={BASE_URL + "logo.svg"} alt="Logo" className="w-10" />
WCF
</Link>
<details className="ml-auto group">
<summary className="list-none hover:text-yeti-dark-7 cursor-pointer">
<MdCalendarMonth size={32} className="group-open:hidden" />
<MdEventBusy size={32} className="hidden group-open:block" />

{/* fullscreen background element that you can click to close when it's open */}
<div className="fixed inset-0 bg-yeti-dark-3/50 hidden group-open:block"></div>
</summary>

<Modal
className="ml-auto"
button={
<div className="hover:text-yeti-dark-7 cursor-pointer">
<MdCalendarMonth size={32} className="group-open:hidden" />
<MdEventBusy size={32} className="hidden group-open:block" />
</div>
}
>
<nav className="fixed right-0 left-0 md:left-auto z-10 flex flex-col bg-yeti-light-3 shadow-lg p-4 md:px-8 rounded-md md:rounded-r-none h-full w-screen md:max-w-screen-md">
<Calendar current={day} />
</nav>
</details>
</Modal>
</div>
</header>
);
Expand Down
Loading

0 comments on commit 5f9348d

Please sign in to comment.