mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 16:23:06 +10:00
wip: refresh design
This commit is contained in:
@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
export { Breadcrumb } from "./breadcrumb";
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
export { Button } from "./Button";
|
||||
export { IconButton } from "./IconButton";
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
export { Dialog } from "./Dialog";
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
export { SelectBox } from "./SelectBox";
|
||||
@ -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>
|
||||
);
|
||||
};
|
||||
@ -1 +0,0 @@
|
||||
export { Tooltip } from "./Tooltip";
|
||||
Reference in New Issue
Block a user