diff --git a/app/components/Modal.tsx b/app/components/Modal.tsx deleted file mode 100644 index e6ba117..0000000 --- a/app/components/Modal.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import { Dialog, Transition } from '@headlessui/react' -import { XMarkIcon } from '@heroicons/react/24/outline' -import clsx from 'clsx' -import { Fragment, type ReactNode, type SetStateAction, useState } from 'react' - -import Button from './Button' - -type HookParameters = { - title: string; - description?: string; - buttonText?: string; - variant?: 'danger' | 'confirm'; - children?: ReactNode; - - // Optional because the button submits - onConfirm?: () => void | Promise; - onOpen?: () => void | Promise; - onClose?: () => void | Promise; -} - -type Overrides = Omit - -type Properties = { - readonly isOpen: boolean; - readonly setIsOpen: (value: SetStateAction) => void; - readonly parameters?: HookParameters; -} - -export type OpenFunction = (overrides?: Overrides) => void - -export default function useModal(properties?: HookParameters) { - const [isOpen, setIsOpen] = useState(false) - const [liveProperties, setLiveProperties] = useState(properties) - - return { - Modal: ( - - ), - - open: (overrides?: Overrides) => { - if (!overrides && !properties) { - throw new Error('No properties provided') - } - - setIsOpen(true) - if (properties?.onOpen) { - void properties.onOpen() - } - - if (overrides) { - setLiveProperties(overrides) - } - }, - - close: () => { - setIsOpen(false) - if (properties?.onClose) { - void properties.onClose() - } - } - } -} - -function Modal({ parameters, isOpen, setIsOpen }: Properties) { - if (!parameters) { - return - } - - return ( - - { - setIsOpen(false) - }} - > - - - - ) -} diff --git a/app/routes/_data.dns._index/magic.tsx b/app/routes/_data.dns._index/magic.tsx index 317893e..589ad13 100644 --- a/app/routes/_data.dns._index/magic.tsx +++ b/app/routes/_data.dns._index/magic.tsx @@ -1,9 +1,8 @@ import { useFetcher } from '@remix-run/react' -import Button from '~/components/Button' -// TODO: Remove useModal and replace with Dialog -import useModal from '~/components/Modal' +import Dialog from '~/components/Dialog' import Spinner from '~/components/Spinner' +import { cn } from '~/utils/cn' type Properties = { readonly isEnabled: boolean; @@ -13,38 +12,59 @@ type Properties = { export default function Modal({ isEnabled, disabled }: Properties) { const fetcher = useFetcher() - const { Modal, open } = useModal({ - title: `${isEnabled ? 'Disable' : 'Enable'} Magic DNS`, - variant: isEnabled ? 'danger' : 'confirm', - buttonText: `${isEnabled ? 'Disable' : 'Enable'} Magic DNS`, - description: 'Devices will no longer be accessible via your tailnet domain. The search domain will also be disabled.', - onConfirm: () => { - fetcher.submit({ - // eslint-disable-next-line @typescript-eslint/naming-convention - 'dns_config.magic_dns': !isEnabled - }, { - method: 'PATCH', - encType: 'application/json' - }) - } - }) return ( - <> - - {Modal} - + + + {close => ( + <> + + {isEnabled ? 'Disable' : 'Enable'} Magic DNS + + + Devices will no longer be accessible via your tailnet domain. + The search domain will also be disabled. + +
+ + Cancel + + { + fetcher.submit({ + // eslint-disable-next-line @typescript-eslint/naming-convention + 'dns_config.magic_dns': !isEnabled + }, { + method: 'PATCH', + encType: 'application/json' + }) + + close() + }} + > + {isEnabled ? 'Disable' : 'Enable'} Magic DNS + +
+ + )} +
+ ) } diff --git a/app/routes/_data.dns._index/rename.tsx b/app/routes/_data.dns._index/rename.tsx index c29792e..53cfbe6 100644 --- a/app/routes/_data.dns._index/rename.tsx +++ b/app/routes/_data.dns._index/rename.tsx @@ -3,11 +3,12 @@ import { useFetcher } from '@remix-run/react' import { useState } from 'react' -import Button from '~/components/Button' import Code from '~/components/Code' +import Dialog from '~/components/Dialog' import Input from '~/components/Input' -import useModal from '~/components/Modal' import Spinner from '~/components/Spinner' +import TextField from '~/components/TextField' +import { cn } from '~/utils/cn' type Properties = { readonly name: string; @@ -18,29 +19,6 @@ type Properties = { export default function Modal({ name, disabled }: Properties) { const [newName, setNewName] = useState(name) const fetcher = useFetcher() - const { Modal, open } = useModal({ - title: 'Rename Tailnet', - description: 'Keep in mind that changing this can lead to all sorts of unexpected behavior and may break existing devices in your tailnet.', - buttonText: 'Rename', - children: ( - { - setNewName(event.target.value) - }} - /> - ), - onConfirm: () => { - fetcher.submit({ - 'dns_config.base_domain': newName - }, { - method: 'PATCH', - encType: 'application/json' - }) - } - }) return (
@@ -64,20 +42,62 @@ export default function Modal({ name, disabled }: Properties) { event.target.select() }} /> - - {Modal} + + + {fetcher.state === 'idle' ? undefined : ( + + )} + Rename Tailnet + + + {close => ( + <> + + Rename Tailnet + + + Keep in mind that changing this can lead to all sorts of unexpected behavior and may break existing devices in your tailnet. + + +
+ + Cancel + + { + fetcher.submit({ + 'dns_config.base_domain': newName + }, { + method: 'PATCH', + encType: 'application/json' + }) + + close() + }} + > + Rename + +
+ + )} +
+
) }