diff --git a/packages/interface/src/components/device/Device.tsx b/packages/interface/src/components/device/Device.tsx index 535af315a..4c3e91f25 100644 --- a/packages/interface/src/components/device/Device.tsx +++ b/packages/interface/src/components/device/Device.tsx @@ -1,11 +1,11 @@ import { KeyIcon } from '@heroicons/react/24/outline'; import { CogIcon, LockClosedIcon } from '@heroicons/react/24/solid'; import { Button } from '@sd/ui'; +import { Loader } from '@sd/ui'; import { Cloud, Desktop, DeviceMobileCamera, DotsSixVertical, Laptop } from 'phosphor-react'; import { useState } from 'react'; import FileItem from '../explorer/FileItem'; -import Loader from '../primitive/Loader'; import ProgressBar from '../primitive/ProgressBar'; import { Tooltip } from '../tooltip/Tooltip'; diff --git a/packages/interface/src/components/dialog/CreateLibraryDialog.tsx b/packages/interface/src/components/dialog/CreateLibraryDialog.tsx index 6ee5faa54..04d4438fd 100644 --- a/packages/interface/src/components/dialog/CreateLibraryDialog.tsx +++ b/packages/interface/src/components/dialog/CreateLibraryDialog.tsx @@ -1,10 +1,9 @@ import { useBridgeMutation } from '@sd/client'; import { Input } from '@sd/ui'; +import { Dialog } from '@sd/ui'; import { useQueryClient } from '@tanstack/react-query'; import { PropsWithChildren, useState } from 'react'; -import Dialog from '../layout/Dialog'; - export default function CreateLibraryDialog({ children, onSubmit diff --git a/packages/interface/src/components/dialog/DeleteLibraryDialog.tsx b/packages/interface/src/components/dialog/DeleteLibraryDialog.tsx index d6090bef3..f84e7ad14 100644 --- a/packages/interface/src/components/dialog/DeleteLibraryDialog.tsx +++ b/packages/interface/src/components/dialog/DeleteLibraryDialog.tsx @@ -1,9 +1,8 @@ import { useBridgeMutation } from '@sd/client'; +import { Dialog } from '@sd/ui'; import { useQueryClient } from '@tanstack/react-query'; import { useState } from 'react'; -import Dialog from '../layout/Dialog'; - interface Props { children: React.ReactNode; libraryUuid: string; diff --git a/packages/interface/src/components/layout/Dialog.tsx b/packages/interface/src/components/layout/Dialog.tsx deleted file mode 100644 index dafd490fc..000000000 --- a/packages/interface/src/components/layout/Dialog.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import * as DialogPrimitive from '@radix-ui/react-dialog'; -import { Button } from '@sd/ui'; -import clsx from 'clsx'; -import { ReactNode } from 'react'; - -import Loader from '../primitive/Loader'; - -export interface DialogProps extends DialogPrimitive.DialogProps { - trigger: ReactNode; - ctaLabel?: string; - ctaDanger?: boolean; - ctaAction?: () => void; - title?: string; - description?: string; - children?: ReactNode; - loading?: boolean; - submitDisabled?: boolean; -} - -export default function Dialog(props: DialogProps) { - return ( - - {props.trigger} - - - -
e.preventDefault()}> -
- - {props.title} - - - {props.description} - - {props.children} -
-
- {props.loading && } -
- - - - -
- - - - - - ); -} diff --git a/packages/interface/src/components/location/LocationListItem.tsx b/packages/interface/src/components/location/LocationListItem.tsx index cab808c03..921861ded 100644 --- a/packages/interface/src/components/location/LocationListItem.tsx +++ b/packages/interface/src/components/location/LocationListItem.tsx @@ -1,13 +1,12 @@ import { TrashIcon } from '@heroicons/react/24/solid'; import { useLibraryMutation } from '@sd/client'; import { Location, Node } from '@sd/client'; -import { Button } from '@sd/ui'; +import { Button, Dialog } from '@sd/ui'; import clsx from 'clsx'; import { Repeat } from 'phosphor-react'; import React, { useState } from 'react'; import { Folder } from '../icons/Folder'; -import Dialog from '../layout/Dialog'; interface LocationListItemProps { location: Location & { node: Node }; diff --git a/packages/interface/src/screens/Overview.tsx b/packages/interface/src/screens/Overview.tsx index 17926e351..3f84f9ad0 100644 --- a/packages/interface/src/screens/Overview.tsx +++ b/packages/interface/src/screens/Overview.tsx @@ -2,6 +2,7 @@ import { ExclamationCircleIcon, PlusIcon } from '@heroicons/react/24/solid'; import { useBridgeQuery, useLibraryQuery, usePlatform } from '@sd/client'; import { Statistics } from '@sd/client'; import { Button, Input } from '@sd/ui'; +import { Dialog } from '@sd/ui'; import byteSize from 'byte-size'; import clsx from 'clsx'; import { useEffect } from 'react'; @@ -10,7 +11,6 @@ import 'react-loading-skeleton/dist/skeleton.css'; import create from 'zustand'; import { Device } from '../components/device/Device'; -import Dialog from '../components/layout/Dialog'; import useCounter from '../hooks/useCounter'; interface StatItemProps { diff --git a/packages/interface/src/screens/settings/library/TagsSettings.tsx b/packages/interface/src/screens/settings/library/TagsSettings.tsx index 005b38e69..62dc93a0f 100644 --- a/packages/interface/src/screens/settings/library/TagsSettings.tsx +++ b/packages/interface/src/screens/settings/library/TagsSettings.tsx @@ -2,13 +2,13 @@ import { TrashIcon } from '@heroicons/react/24/outline'; import { Tag, useLibraryMutation, useLibraryQuery } from '@sd/client'; import { TagUpdateArgs } from '@sd/client'; import { Button, Input } from '@sd/ui'; +import { Dialog } from '@sd/ui'; import clsx from 'clsx'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { useDebounce } from 'rooks'; import Card from '../../../components/layout/Card'; -import Dialog from '../../../components/layout/Dialog'; import { Toggle } from '../../../components/primitive'; import { InputContainer } from '../../../components/primitive/InputContainer'; import { PopoverPicker } from '../../../components/primitive/PopoverPicker'; diff --git a/packages/interface/tsconfig.json b/packages/interface/tsconfig.json index 294537085..cf8e0fb5a 100644 --- a/packages/interface/tsconfig.json +++ b/packages/interface/tsconfig.json @@ -4,5 +4,5 @@ "target": "es2020", "outDir": "./dist" }, - "include": ["src"] + "include": ["src", "../ui/src/Dialog.tsx", "../ui/src/Loader.tsx"] } diff --git a/packages/ui/package.json b/packages/ui/package.json index f34e57799..b9a6871ea 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -20,6 +20,7 @@ "@headlessui/react": "^1.7.3", "@heroicons/react": "^2.0.12", "@radix-ui/react-context-menu": "^1.0.0", + "@radix-ui/react-dialog": "^1.0.0", "@radix-ui/react-dropdown-menu": "^1.0.0", "@tailwindcss/forms": "^0.5.3", "class-variance-authority": "^0.2.3", @@ -28,6 +29,7 @@ "postcss": "^8.4.17", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-loading-icons": "^1.1.0", "react-spring": "^9.5.5", "storybook": "^6.5.12", "tailwindcss": "^3.1.8" diff --git a/packages/ui/src/Dialog.tsx b/packages/ui/src/Dialog.tsx new file mode 100644 index 000000000..e1bedef2f --- /dev/null +++ b/packages/ui/src/Dialog.tsx @@ -0,0 +1,99 @@ +import * as DialogPrimitive from '@radix-ui/react-dialog'; +import clsx from 'clsx'; +import { ReactNode, useState } from 'react'; +import { animated, config, useTransition } from 'react-spring'; + +import { Button, Loader } from '../'; + +export interface DialogProps extends DialogPrimitive.DialogProps { + trigger: ReactNode; + ctaLabel?: string; + ctaDanger?: boolean; + ctaAction?: () => void; + title?: string; + description?: string; + children?: ReactNode; + transformOrigin?: string; + loading?: boolean; + submitDisabled?: boolean; +} + +export function Dialog(props: DialogProps) { + const [open, setOpen] = useState(false); + + const transitions = useTransition(open, { + from: { + opacity: 0, + transform: `translateY(20px)`, + transformOrigin: props.transformOrigin || 'bottom' + }, + enter: { opacity: 1, transform: `translateY(0px)` }, + leave: { opacity: 0, transform: `translateY(20px)` }, + config: { mass: 0.4, tension: 200, friction: 10 } + }); + + return ( + + {props.trigger} + {transitions( + (styles, show) => + show && ( + + + + + +
e.preventDefault()}> +
+ + {props.title} + + + {props.description} + + {props.children} +
+
+ {props.loading && } +
+ + + + +
+ + + + + + + ) + )} + + ); +} diff --git a/packages/interface/src/components/primitive/Loader.tsx b/packages/ui/src/Loader.tsx similarity index 79% rename from packages/interface/src/components/primitive/Loader.tsx rename to packages/ui/src/Loader.tsx index 08dbdfb81..fadd2473d 100644 --- a/packages/interface/src/components/primitive/Loader.tsx +++ b/packages/ui/src/Loader.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx'; import { Puff } from 'react-loading-icons'; -export default function Loader(props: { className?: string }) { +export function Loader(props: { className?: string }) { return (