wip: refresh design

This commit is contained in:
Mythie
2023-06-09 18:21:18 +10:00
parent 76b2fb5edd
commit 159bcade7b
432 changed files with 19640 additions and 29359 deletions

View File

@ -1,48 +0,0 @@
import React from "react";
import Link from "next/link";
import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/react/20/solid";
export function Breadcrumb(props: any) {
return (
<>
<nav className="sm:hidden" aria-label="Back">
<Link
href={
props.items.length > 1 ? props.items[props.items.length - 2].href : props.items[0].href
}
className="flex items-center text-sm font-medium text-gray-500 hover:text-gray-700">
<ChevronLeftIcon
className="-ml-1 mr-1 h-5 w-5 flex-shrink-0 text-gray-400"
aria-hidden="true"
/>
Back
</Link>
</nav>
<nav className="hidden sm:flex" aria-label="Breadcrumb">
<ol role="list" className="flex items-center space-x-4">
{props?.items.map((item: any, index: number) => (
<React.Fragment key={item.href}>
{index > 0 ? (
<ChevronRightIcon
className="h-5 w-5 flex-shrink-0 text-gray-400"
aria-hidden="true"
/>
) : (
""
)}
<li>
<div className="flex">
<Link
href={item.href}
className="text-sm font-medium text-gray-500 hover:text-gray-700">
{item.title}
</Link>
</div>
</li>
</React.Fragment>
))}
</ol>
</nav>
</>
);
}

View File

@ -1 +0,0 @@
export { Breadcrumb } from "./breadcrumb";

View File

@ -1,50 +0,0 @@
import React from "react";
import Link from "next/link";
import { classNames } from "@documenso/lib";
export function Button(props: any) {
const isLink = typeof props.href !== "undefined" && !props.disabled;
const { color = "primary", icon, disabled, onClick } = props;
const baseStyles =
"inline-flex gap-x-2 items-center justify-center min-w-[80px] rounded-md border border-transparent px-4 py-2 text-sm font-medium shadow-sm disabled:bg-gray-300 duration-200";
const primaryStyles = "text-gray-900 bg-neon hover:bg-neon-dark";
const secondaryStyles = "border-gray-300 bg-white text-gray-700 hover:bg-gray-50";
return isLink ? (
<Link
id={props.id}
href={props.href}
className={classNames(
baseStyles,
color === "primary" ? primaryStyles : secondaryStyles,
props.className
)}
hidden={props.hidden}>
{props.icon ? (
<props.icon className="inline-block h-5 text-inherit" aria-hidden="true"></props.icon>
) : (
""
)}
{props.children}
</Link>
) : (
<button
id={props.id}
type={props.type || "button"}
className={classNames(
baseStyles,
color === "primary" ? primaryStyles : secondaryStyles,
props.className
)}
onClick={props.onClick}
disabled={props.disabled || props.loading}
hidden={props.hidden}>
{props.icon ? (
<props.icon className="inline h-5 text-inherit" aria-hidden="true"></props.icon>
) : (
""
)}
{props.children}
</button>
);
}

View File

@ -1,48 +0,0 @@
import React from "react";
import Link from "next/link";
import { classNames } from "@documenso/lib";
export function IconButton(props: any) {
const isLink = typeof props.href !== "undefined";
const { color = "primary", icon, disabled, onClick } = props;
const baseStyles = "disabled:text-gray-300";
const primaryStyles = "text-neon hover:text-neon-dark";
const secondaryStyles = "text-gray-700 hover:text-neon-dark";
return isLink ? (
<Link
id={props.id}
href={props.href}
className={classNames(
baseStyles,
color === "primary" ? primaryStyles : secondaryStyles,
props.className
)}
hidden={props.hidden}>
{props.icon ? (
<props.icon className="mr-1 inline h-6 text-inherit" aria-hidden="true"></props.icon>
) : (
""
)}
{props.children}
</Link>
) : (
<button
id={props.id}
className={classNames(
baseStyles,
color === "primary" ? primaryStyles : secondaryStyles,
props.className
)}
onClick={props.onClick}
disabled={props.disabled}
hidden={props.hidden}>
{props.icon ? (
<props.icon className="mr-1 inline h-6 text-inherit" aria-hidden="true"></props.icon>
) : (
""
)}
{props.children}
</button>
);
}

View File

@ -1,2 +0,0 @@
export { Button } from "./Button";
export { IconButton } from "./IconButton";

View File

@ -1,106 +0,0 @@
import React, { useMemo } from "react";
import { Fragment } from "react";
import { sendSigningRequests } from "@documenso/lib/api";
import { truncate } from "@documenso/lib/helpers";
import { Button } from "@documenso/ui";
import { Dialog as DialogComponent, Transition } from "@headlessui/react";
import { Document as PrismaDocument } from "@prisma/client";
type FormValue = {
id: number;
email: string;
name: string;
};
type DialogProps = {
title: string;
open: boolean;
setOpen: (open: boolean) => void;
document: PrismaDocument;
formValues: FormValue[];
setLoading: (loading: boolean) => void;
icon: React.ReactNode;
truncateTitle?: boolean;
};
export function Dialog({
title,
open,
setOpen,
document,
formValues,
setLoading,
icon,
truncateTitle = true,
}: DialogProps) {
const unsentEmailsLength = formValues.filter(
(s: any) => s.email && s.sendStatus != "SENT"
).length;
const documentTitle = truncateTitle ? truncate(document.title) : document.title;
return (
<Transition.Root show={open} as={Fragment}>
<DialogComponent as="div" className="relative z-10" onClose={setOpen}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0">
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
<DialogComponent.Panel className="relative transform overflow-hidden rounded-lg bg-white px-4 pt-5 pb-4 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6">
<div>
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100">
{icon}
</div>
<div className="mt-3 text-center sm:mt-5">
<DialogComponent.Title
as="h3"
className="text-lg font-medium leading-6 text-gray-900">
{title}
</DialogComponent.Title>
<div className="mt-2">
<p className="text-sm text-gray-500">
{`"${documentTitle}" will be sent to ${unsentEmailsLength} recipients.`}
</p>
</div>
</div>
</div>
<div className="mt-5 flex justify-end gap-3 sm:mt-6 sm:grid sm:flex-none sm:grid-flow-row-dense sm:grid-cols-2 ">
<Button color="secondary" onClick={() => setOpen(false)}>
Cancel
</Button>
<Button
onClick={() => {
setOpen(false);
setLoading(true);
sendSigningRequests(document).finally(() => {
setLoading(false);
});
}}>
Send
</Button>
</div>
</DialogComponent.Panel>
</Transition.Child>
</div>
</div>
</DialogComponent>
</Transition.Root>
);
}

View File

@ -1 +0,0 @@
export { Dialog } from "./Dialog";

View File

@ -1,75 +0,0 @@
import React, { Fragment, useState } from "react";
import { classNames } from "@documenso/lib";
import { Listbox, Transition } from "@headlessui/react";
import { CheckIcon, ChevronUpDownIcon } from "@heroicons/react/24/outline";
export function SelectBox(props: any) {
return (
<div className={props.className}>
<Listbox
value={props.value}
onChange={(e) => {
props.onChange(e);
}}>
{({ open }) => (
<>
<Listbox.Label className="block text-sm font-medium text-gray-700">
{props.label}
</Listbox.Label>
<div className="relative mt-1">
<Listbox.Button className="focus:border-neon focus:ring-neon relative w-full cursor-default rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 text-left shadow-sm focus:outline-none focus:ring-1 sm:text-sm">
<span className="block truncate">{props?.value?.label}</span>
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<ChevronUpDownIcon className="h-5 w-5 text-gray-400" aria-hidden="true" />
</span>
</Listbox.Button>
<Transition
show={open}
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0">
<Listbox.Options className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
{props.options.map((option: any) => (
<Listbox.Option
key={option.value}
className={({ active }) =>
classNames(
active ? "bg-neon text-white" : "text-gray-900",
"relative cursor-default select-none py-2 pl-3 pr-9"
)
}
value={option}>
{({ selected, active }) => (
<>
<span
className={classNames(
selected ? "font-semibold" : "font-normal",
"block truncate"
)}>
{option.label}
</span>
{option.value === props.value.value ? (
<span
className={classNames(
active ? "text-white" : "text-neon",
"absolute inset-y-0 right-0 flex items-center pr-4"
)}>
<CheckIcon className="h-5 w-5" aria-hidden="true" />
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</>
)}
</Listbox>
</div>
);
}

View File

@ -1 +0,0 @@
export { SelectBox } from "./SelectBox";

View File

@ -1,34 +0,0 @@
import React, { useState } from "react";
import { classNames } from "@documenso/lib";
export function Tooltip(props: any) {
let timeout: NodeJS.Timeout;
const [active, setActive] = useState(false);
const showTip = () => {
timeout = setTimeout(() => {
setActive(true);
}, props.delay || 40);
};
const hideTip = () => {
clearInterval(timeout);
setActive(false);
};
return (
<div className="relative" onPointerEnter={showTip} onPointerLeave={hideTip}>
{props.children}
<div
className={classNames(
"absolute left-1/4 -translate-x-1/2 transform px-4 transition-all delay-50 duration-120",
active && "bottom-9 opacity-100",
!active && "pointer-events-none bottom-6 opacity-0"
)}>
<span className="text-neon-800 bg-neon-200 inline-block rounded py-1 px-2 text-xs">
{props.label}
</span>
</div>
</div>
);
};

View File

@ -1 +0,0 @@
export { Tooltip } from "./Tooltip";