mirror of
https://github.com/documenso/documenso.git
synced 2025-11-17 02:01:33 +10:00
feat: updated ui items
Signed-off-by: Adithya Krishna <adithya@documenso.com>
This commit is contained in:
@ -45,7 +45,7 @@ export default function MarketingLayout({ children }: MarketingLayoutProps) {
|
||||
<Image
|
||||
src={backgroundPattern}
|
||||
alt="background pattern"
|
||||
className="!h-34 w-full object-cover"
|
||||
className="h-[2rem] w-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<AnnouncementBar className="relative" isShown={true} />
|
||||
|
||||
@ -2,11 +2,14 @@
|
||||
|
||||
import React, { useRef, useState } from 'react';
|
||||
|
||||
import Image from 'next/image';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { BadgeCheck, File } from 'lucide-react';
|
||||
import { File } from 'lucide-react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
||||
import Check from '@documenso/assets/Check.svg';
|
||||
import Lucas from '@documenso/assets/images/Lucas.png';
|
||||
import Timur from '@documenso/assets/images/Timur.png';
|
||||
import type { User } from '@documenso/prisma/client';
|
||||
@ -60,7 +63,7 @@ export const PublicProfileIntro = ({ user }: PublicProfileIntroProps) => {
|
||||
|
||||
const isProfileURLClaimed = user.profileURL ? false : true;
|
||||
const [showClaimingDialog, setShowClaimingDialog] = useState(isProfileURLClaimed);
|
||||
const [showClaimedDialog, setShowClaimedDialog] = useState(false);
|
||||
const [showClaimedDialog, setShowClaimedDialog] = useState(true);
|
||||
|
||||
const onFormSubmit = async ({ profileURL }: TPublicProfileFormSchema) => {
|
||||
try {
|
||||
@ -92,40 +95,38 @@ export const PublicProfileIntro = ({ user }: PublicProfileIntroProps) => {
|
||||
<Dialog open={showClaimingDialog} onOpenChange={setShowClaimingDialog}>
|
||||
<DialogContent position="center" className="pb-4">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="font-semi-bold text-center text-xl">
|
||||
<DialogTitle className="font-semi-bold text-center text-2xl">
|
||||
Introducing public profile!
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-center">
|
||||
<DialogDescription className="text-muted-foreground/60 text-center text-sm">
|
||||
Reserve your Documenso public profile username
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<Card className="relative px-6 py-6">
|
||||
<Card className="flex flex-col items-center px-6 py-6">
|
||||
<code className="bg-muted rounded-md px-1 py-1 text-sm">
|
||||
<Card className="relative flex flex-col items-center border-none bg-gray-50 px-6 py-6 pb-0 shadow-none">
|
||||
<code className="rounded-md border-2 border-gray-200 px-1 py-1 text-sm">
|
||||
<span>documenso.com/u/timur</span>
|
||||
</code>
|
||||
<Avatar className="dark:border-border mt-2 h-12 w-12 border-2 border-solid border-white">
|
||||
<Avatar className="dark:border-border mt-2 h-20 w-20 border-2 border-solid border-white bg-white">
|
||||
<AvatarImage className="AvatarImage" src={Timur.src} alt="Timur" />
|
||||
<AvatarFallback className="text-xs text-gray-400">Timur</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex flex-row gap-x-2">
|
||||
Timur Ercan <BadgeCheck fill="#A2E771" />
|
||||
Timur Ercan <Image alt="Check" src={Check} />
|
||||
</div>
|
||||
<span className="text-center">
|
||||
<span className="text-muted-foreground/60 text-center">
|
||||
Hey I’m Timur <br /> Pick any of the following agreements below and start signing to
|
||||
get started
|
||||
</span>
|
||||
</Card>
|
||||
<Card className="mt-2 items-center">
|
||||
<CardHeader className="p-2">Documents</CardHeader>
|
||||
<Card className="bg mt-2 w-full items-center shadow-none">
|
||||
<CardHeader className="p-4 text-gray-500">Documents</CardHeader>
|
||||
<hr className="mb-2" />
|
||||
<div className="mb-2 flex flex-row items-center justify-between">
|
||||
<div className="flex flex-row items-center gap-x-2">
|
||||
<File className="ml-3" />
|
||||
<div className="flex flex-col">
|
||||
<span className="text-md">NDA.pdf</span>
|
||||
<span className="text-muted-foregroun mt-0.5 text-xs">
|
||||
<span className="text-muted-foreground mt-0.5 text-xs">
|
||||
Like to discuss about my work?
|
||||
</span>
|
||||
</div>
|
||||
@ -135,6 +136,12 @@ export const PublicProfileIntro = ({ user }: PublicProfileIntroProps) => {
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
<div
|
||||
className="fade-overlay bg-black-100 absolute bottom-0 h-1/4 w-full"
|
||||
style={{
|
||||
background: `linear-gradient(180deg, rgba(255, 255, 255, 0.06) 0%, white 75%, white 100%)`,
|
||||
}}
|
||||
></div>
|
||||
</Card>
|
||||
|
||||
<Form {...form}>
|
||||
@ -173,7 +180,7 @@ export const PublicProfileIntro = ({ user }: PublicProfileIntroProps) => {
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<Dialog open={showClaimedDialog} onOpenChange={setShowClaimedDialog}>
|
||||
<Dialog open={false} onOpenChange={setShowClaimedDialog}>
|
||||
<DialogContent position="center" className="pb-4">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="font-semi-bold text-center text-xl">All set!</DialogTitle>
|
||||
@ -192,7 +199,7 @@ export const PublicProfileIntro = ({ user }: PublicProfileIntroProps) => {
|
||||
<AvatarFallback className="text-xs text-gray-400">Timur</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex flex-row gap-x-2">
|
||||
Lucas Smith <BadgeCheck fill="#A2E771" />
|
||||
Lucas Smith <Image alt="Check" src={Check} />
|
||||
</div>
|
||||
<div className="flex inline-flex h-full w-full flex-col items-center justify-center gap-3 py-2">
|
||||
<Skeleton className="w-75 h-4 animate-none rounded-full" />
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Card } from '@documenso/ui/primitives/card';
|
||||
|
||||
import ClaimUsernameCard from '../../../components/(dashboard)/claim-username-card/claim-username-card';
|
||||
import { NewHeader } from '../../../components/(dashboard)/layout/new/new-header';
|
||||
|
||||
type SignUpLayoutProps = {
|
||||
@ -13,13 +10,11 @@ export default function SignUpLayout({ children }: SignUpLayoutProps) {
|
||||
return (
|
||||
<>
|
||||
<NewHeader className="mx-auto h-16 max-w-screen-xl px-4 md:h-20 lg:px-8" />
|
||||
<main className="bg-sand-100 flex flex-col items-center justify-center overflow-hidden px-4 py-12 md:p-12 lg:p-[7.2rem]">
|
||||
<div className="flex w-full items-center gap-x-8">
|
||||
<ClaimUsernameCard />
|
||||
<Card className="px-6 py-6">
|
||||
<div className="w-full">{children}</div>
|
||||
</Card>
|
||||
</div>
|
||||
<main
|
||||
className="bg-sand-100 scale-90 items-center justify-center px-4 md:h-20 lg:mx-28 lg:px-8"
|
||||
style={{ height: 'calc(100vh - 80px)' }}
|
||||
>
|
||||
<div className="grid grid-cols-12 gap-y-8 overflow-hidden p-2 lg:gap-x-8">{children}</div>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import type { Metadata } from 'next';
|
||||
import Link from 'next/link';
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
import { IS_GOOGLE_SSO_ENABLED } from '@documenso/lib/constants/auth';
|
||||
import { decryptSecondaryData } from '@documenso/lib/server-only/crypto/decrypt';
|
||||
|
||||
import { SignUpForm } from '~/components/forms/signup';
|
||||
@ -31,25 +29,7 @@ export default function SignUpPage({ searchParams }: SignUpPageProps) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1 className="text-3xl font-semibold">Create a new account</h1>
|
||||
|
||||
<p className="text-muted-foreground/60 mt-2 text-sm">
|
||||
Create your account and start using state-of-the-art document signing. Open and beautiful
|
||||
signing is within your grasp.
|
||||
</p>
|
||||
|
||||
<SignUpForm
|
||||
className="mt-1"
|
||||
initialEmail={email || undefined}
|
||||
isGoogleSSOEnabled={IS_GOOGLE_SSO_ENABLED}
|
||||
/>
|
||||
|
||||
<p className="text-muted-foreground mt-6 text-center text-sm">
|
||||
Already have an account?{' '}
|
||||
<Link href="/signin" className="text-primary duration-200 hover:opacity-70">
|
||||
Sign in instead
|
||||
</Link>
|
||||
</p>
|
||||
<SignUpForm className="mt-1" initialEmail={email || undefined} isGoogleSSOEnabled={true} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -4,8 +4,9 @@ import React from 'react';
|
||||
|
||||
import Image from 'next/image';
|
||||
|
||||
import { BadgeCheck, File } from 'lucide-react';
|
||||
import { File } from 'lucide-react';
|
||||
|
||||
import Check from '@documenso/assets/Check.svg';
|
||||
import Timur from '@documenso/assets/images/Timur.png';
|
||||
import backgroundPattern from '@documenso/assets/images/background-blog-og.png';
|
||||
import { cn } from '@documenso/ui/lib/utils';
|
||||
@ -13,68 +14,71 @@ import { Avatar, AvatarFallback, AvatarImage } from '@documenso/ui/primitives/av
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { Card, CardFooter, CardHeader } from '@documenso/ui/primitives/card';
|
||||
|
||||
export default function ClaimUsernameCard() {
|
||||
type ClaimUsernameCardProps = {
|
||||
className: string;
|
||||
};
|
||||
|
||||
export default function ClaimUsernameCard({ className }: ClaimUsernameCardProps) {
|
||||
const onSignUpClick = () => {};
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="absolute -inset-96 -z-[1] flex items-center justify-center bg-contain opacity-50">
|
||||
<div className={cn('relative', className)}>
|
||||
<Card className={cn('relative h-full overflow-hidden px-16 py-16 shadow-none')}>
|
||||
<Image
|
||||
src={backgroundPattern}
|
||||
alt="background pattern"
|
||||
className="dark:brightness-95 dark:contrast-[100%] dark:invert"
|
||||
className="absolute left-0 top-0 h-full w-full bg-cover opacity-50 dark:brightness-95 dark:contrast-[100%] dark:invert"
|
||||
/>
|
||||
</div>
|
||||
<Card className={cn('relative px-16 py-16')}>
|
||||
<Card className="flex flex-col items-center px-6 py-6">
|
||||
<code className="bg-muted rounded-md px-1 py-1 text-sm">
|
||||
<Card className="mt-28 flex flex-col items-center px-6 py-6 shadow-none">
|
||||
<code className="rounded-md border-2 border-gray-200 px-1 py-1 text-sm">
|
||||
<span>documenso.com/u/timur</span>
|
||||
</code>
|
||||
<Avatar className="dark:border-border mt-2 h-12 w-12 border-2 border-solid border-white">
|
||||
<Avatar className="dark:border-border mt-2 h-20 w-20 border-2 border-solid border-white">
|
||||
<AvatarImage className="AvatarImage" src={Timur.src} alt="Timur" />
|
||||
<AvatarFallback className="text-xs text-gray-400">Timur</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex flex-row gap-x-2">
|
||||
Timur Ercan <BadgeCheck fill="#A2E771" />
|
||||
<div className="mb-2 flex flex-row gap-x-2">
|
||||
Timur Ercan <Image alt="Check" src={Check} />
|
||||
</div>
|
||||
<span className="text-center">
|
||||
Hey I’m Timur <br /> Pick any of the following agreements below and start signing to get
|
||||
started
|
||||
<span className="text-muted-foreground/60 text-center ">
|
||||
Hey I’m Timur <br /> Pick any of the following agreements below and <br /> start signing
|
||||
to get started
|
||||
</span>
|
||||
</Card>
|
||||
<Card className="mt-2 items-center">
|
||||
<CardHeader className="p-2">Documents</CardHeader>
|
||||
<Card className="mt-2 w-full items-center shadow-none">
|
||||
<CardHeader className="p-4 text-gray-500">Documents</CardHeader>
|
||||
<hr className="mb-2" />
|
||||
<div className="mb-2 flex flex-row items-center justify-between">
|
||||
<div className="flex flex-row items-center gap-x-2">
|
||||
<File className="ml-3" />
|
||||
<File className="text-muted-foreground ml-3" />
|
||||
<div className="flex flex-col">
|
||||
<span className="text-md">NDA.pdf</span>
|
||||
<span className="text-muted-foregroun mt-0.5 text-xs">
|
||||
<span className="text-muted-foreground mt-0.5 text-xs">
|
||||
Like to discuss about my work?
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<Button className="mr-3" variant="default">
|
||||
<Button className="mr-3 px-6" variant="default">
|
||||
Sign
|
||||
</Button>
|
||||
</div>
|
||||
<hr className="mb-2" />
|
||||
<div className="mb-2 flex flex-row items-center justify-between">
|
||||
<div className="flex flex-row items-center gap-x-2">
|
||||
<File className="ml-3" />
|
||||
<File className="text-muted-foreground ml-3" />
|
||||
<div className="flex flex-col">
|
||||
<span className="text-md">NDA.pdf</span>
|
||||
<span className="text-muted-foregroun mt-0.5 text-xs">
|
||||
<span className="text-muted-foreground mt-0.5 text-xs">
|
||||
Like to discuss about my work?
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<Button className="mr-3" variant="default">
|
||||
<Button className="mr-3 px-6" variant="default">
|
||||
Sign
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
<CardFooter className="mt-20 justify-center">
|
||||
</Card>
|
||||
|
||||
<CardFooter className="mt-32 justify-center">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
@ -14,6 +17,7 @@ import { trpc } from '@documenso/trpc/react';
|
||||
import { ZPasswordSchema } from '@documenso/trpc/server/auth-router/schema';
|
||||
import { cn } from '@documenso/ui/lib/utils';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { Card } from '@documenso/ui/primitives/card';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@ -27,6 +31,16 @@ import { PasswordInput } from '@documenso/ui/primitives/password-input';
|
||||
import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
import ClaimUsernameCard from '../(dashboard)/claim-username-card/claim-username-card';
|
||||
|
||||
export const STEP = {
|
||||
SIGNUP: 'SIGNUP',
|
||||
CLAIM: 'CLAIM',
|
||||
} as const;
|
||||
|
||||
type StepKeys = keyof typeof STEP;
|
||||
type StepValues = (typeof STEP)[StepKeys];
|
||||
|
||||
const SIGN_UP_REDIRECT_PATH = '/documents';
|
||||
|
||||
export const ZSignUpFormSchema = z
|
||||
@ -35,6 +49,7 @@ export const ZSignUpFormSchema = z
|
||||
email: z.string().email().min(1),
|
||||
password: ZPasswordSchema,
|
||||
signature: z.string().min(1, { message: 'We need your signature to sign documents' }),
|
||||
profileURL: z.string().trim().min(1, { message: 'Please enter a valid URL slug.' }),
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
@ -58,6 +73,7 @@ export const SignUpForm = ({ className, initialEmail, isGoogleSSOEnabled }: Sign
|
||||
const { toast } = useToast();
|
||||
const analytics = useAnalytics();
|
||||
const searchParams = useSearchParams();
|
||||
const [step, setStep] = useState<StepValues>(STEP.SIGNUP);
|
||||
|
||||
let src: string | null = null;
|
||||
if (searchParams) {
|
||||
@ -70,18 +86,33 @@ export const SignUpForm = ({ className, initialEmail, isGoogleSSOEnabled }: Sign
|
||||
email: initialEmail ?? '',
|
||||
password: '',
|
||||
signature: '',
|
||||
profileURL: '',
|
||||
},
|
||||
resolver: zodResolver(ZSignUpFormSchema),
|
||||
});
|
||||
|
||||
const isSubmitting = form.formState.isSubmitting;
|
||||
const isValid = form.formState.isValid;
|
||||
|
||||
const signature = form.watch('signature');
|
||||
|
||||
const { mutateAsync: signup } = trpc.auth.signup.useMutation();
|
||||
const { mutateAsync: updatePublicProfile } = trpc.profile.updatePublicProfile.useMutation();
|
||||
|
||||
const onFormSubmit = async ({ name, email, password, signature }: TSignUpFormSchema) => {
|
||||
const onFormSubmit = async ({
|
||||
name,
|
||||
email,
|
||||
password,
|
||||
signature,
|
||||
profileURL,
|
||||
}: TSignUpFormSchema) => {
|
||||
try {
|
||||
await signup({ name, email, password, signature });
|
||||
|
||||
await updatePublicProfile({
|
||||
profileURL,
|
||||
});
|
||||
|
||||
await signIn('credentials', {
|
||||
email,
|
||||
password,
|
||||
@ -111,6 +142,16 @@ export const SignUpForm = ({ className, initialEmail, isGoogleSSOEnabled }: Sign
|
||||
}
|
||||
};
|
||||
|
||||
const onNextStepClick = () => {
|
||||
if (step === STEP.SIGNUP) {
|
||||
setStep(STEP.CLAIM);
|
||||
|
||||
setTimeout(() => {
|
||||
document.querySelector<HTMLElement>('#signature')?.focus();
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
const onSignUpWithGoogleClick = async () => {
|
||||
try {
|
||||
await signIn('google', { callbackUrl: SIGN_UP_REDIRECT_PATH });
|
||||
@ -124,13 +165,68 @@ export const SignUpForm = ({ className, initialEmail, isGoogleSSOEnabled }: Sign
|
||||
}
|
||||
};
|
||||
|
||||
const stepsRemaining = useMemo(() => {
|
||||
if (step === STEP.CLAIM) {
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}, [step]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ClaimUsernameCard className="col-span-12 gap-y-4 lg:col-span-7" />
|
||||
<Card className="col-span-12 gap-y-4 bg-gray-50 px-6 py-6 shadow-none lg:col-span-5">
|
||||
<div className="w-full">
|
||||
{step === STEP.SIGNUP && (
|
||||
<>
|
||||
<h1 className="text-3xl font-semibold">Create a new account</h1>
|
||||
|
||||
<p className="text-muted-foreground/60 mt-2 text-sm">
|
||||
Create your account and start using state-of-the-art document signing. Open and
|
||||
beautiful signing is within your grasp.
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
{step === STEP.CLAIM && (
|
||||
<>
|
||||
<h1 className="text-3xl font-semibold">Claim your username now</h1>
|
||||
|
||||
<p className="text-muted-foreground/60 mt-2 text-sm">
|
||||
You will get notified & be able to set up your documenso public profile when we
|
||||
launch the feature
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
<hr className="mb-6 mt-4" />
|
||||
<Form {...form}>
|
||||
<form
|
||||
className={cn('flex w-full flex-col gap-y-4', className)}
|
||||
className={cn('flex h-full w-full flex-col gap-y-4', className)}
|
||||
onSubmit={form.handleSubmit(onFormSubmit)}
|
||||
>
|
||||
<fieldset className="flex w-full flex-col gap-y-4" disabled={isSubmitting}>
|
||||
<div className={cn(step === STEP.SIGNUP && 'hidden')}>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="profileURL"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Public profile URL</FormLabel>
|
||||
<FormControl>
|
||||
<>
|
||||
<Input id="username" type="text" className="mb-2 mt-2" {...field} />
|
||||
<div className="mt-2">
|
||||
<code className="bg-muted rounded-md px-1 py-1 text-sm">
|
||||
documenso.com/u/
|
||||
</code>
|
||||
</div>
|
||||
</>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className={cn('space-y-2', step === STEP.CLAIM && 'invisible')}>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="name"
|
||||
@ -138,7 +234,7 @@ export const SignUpForm = ({ className, initialEmail, isGoogleSSOEnabled }: Sign
|
||||
<FormItem>
|
||||
<FormLabel>Full Name</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="text" {...field} />
|
||||
<Input type="text" className="bg-white" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -152,7 +248,7 @@ export const SignUpForm = ({ className, initialEmail, isGoogleSSOEnabled }: Sign
|
||||
<FormItem>
|
||||
<FormLabel>Email Address</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="email" {...field} />
|
||||
<Input type="email" className="bg-white" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -166,7 +262,7 @@ export const SignUpForm = ({ className, initialEmail, isGoogleSSOEnabled }: Sign
|
||||
<FormItem>
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormControl>
|
||||
<PasswordInput {...field} />
|
||||
<PasswordInput className="bg-white" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -181,10 +277,12 @@ export const SignUpForm = ({ className, initialEmail, isGoogleSSOEnabled }: Sign
|
||||
<FormLabel>Sign Here</FormLabel>
|
||||
<FormControl>
|
||||
<SignaturePad
|
||||
className="h-36 w-full"
|
||||
id="signatureText"
|
||||
className="w-full"
|
||||
disabled={isSubmitting}
|
||||
containerClassName="mt-2 rounded-lg border bg-background"
|
||||
onChange={(v) => onChange(v ?? '')}
|
||||
height={200}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@ -192,17 +290,9 @@ export const SignUpForm = ({ className, initialEmail, isGoogleSSOEnabled }: Sign
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
size="lg"
|
||||
loading={isSubmitting}
|
||||
className="dark:bg-documenso dark:hover:opacity-90"
|
||||
>
|
||||
{isSubmitting ? 'Signing up...' : 'Sign Up'}
|
||||
</Button>
|
||||
|
||||
{isGoogleSSOEnabled && (
|
||||
<>
|
||||
<div className="relative flex items-center justify-center gap-x-4 py-2 text-xs uppercase">
|
||||
@ -224,7 +314,50 @@ export const SignUpForm = ({ className, initialEmail, isGoogleSSOEnabled }: Sign
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<p className="text-muted-foreground text-left text-sm">
|
||||
Already have an account?{' '}
|
||||
<Link href="/signin" className="text-primary duration-200 hover:opacity-70">
|
||||
Sign in instead
|
||||
</Link>
|
||||
</p>
|
||||
<div className="mt-6 flex items-center justify-between">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
{isValid ? 'Claim username' : `Basic details ${stepsRemaining}/2`}
|
||||
</p>
|
||||
|
||||
<p className="text-muted-foreground block text-xs md:hidden">Minimise contract</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-background relative h-[2px] w-full">
|
||||
<div
|
||||
className={cn('bg-primary/60 absolute inset-y-0 left-0 duration-200', {
|
||||
'w-1/2': stepsRemaining === 1,
|
||||
'w-full': isValid,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
{!isValid && (
|
||||
<Button
|
||||
loading={isSubmitting}
|
||||
className="dark:bg-documenso ml-auto w-52 dark:hover:opacity-90"
|
||||
onClick={() => onNextStepClick()}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
)}
|
||||
{isValid && (
|
||||
<Button
|
||||
type="submit"
|
||||
loading={isSubmitting}
|
||||
className="dark:bg-documenso ml-auto w-52 dark:hover:opacity-90"
|
||||
>
|
||||
Complete
|
||||
</Button>
|
||||
)}
|
||||
</form>
|
||||
</Form>
|
||||
</div>
|
||||
</Card>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
3
packages/assets/Check.svg
Normal file
3
packages/assets/Check.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.54572 1.10579C9.57786 -0.0821356 11.4223 -0.0821393 12.4545 1.10579L13.2585 2.03112C13.3917 2.18452 13.5947 2.25838 13.7954 2.22654L15.0061 2.03449C16.5603 1.78794 17.9732 2.97353 18.0003 4.54698L18.0214 5.77262C18.0249 5.97581 18.1329 6.16284 18.3071 6.26746L19.358 6.89855C20.7071 7.70873 21.0274 9.52517 20.0368 10.7479L19.2651 11.7004C19.1372 11.8583 19.0997 12.0709 19.1659 12.2631L19.5652 13.422C20.0779 14.9098 19.1557 16.5072 17.6109 16.8071L16.4075 17.0407C16.208 17.0794 16.0426 17.2182 15.9698 17.408L15.5308 18.5525C14.9672 20.0218 13.234 20.6526 11.8578 19.8893L10.7858 19.2948C10.6081 19.1962 10.3921 19.1962 10.2144 19.2948L9.14242 19.8893C7.76623 20.6526 6.033 20.0218 5.4694 18.5525L5.03038 17.408C4.9576 17.2182 4.79216 17.0794 4.59268 17.0407L3.38932 16.8071C1.84448 16.5072 0.922245 14.9098 1.43495 13.422L1.83431 12.2631C1.90052 12.0709 1.86302 11.8583 1.7351 11.7004L0.963432 10.7479C-0.0272148 9.52517 0.293068 7.70873 1.64218 6.89855L2.69306 6.26746C2.86728 6.16284 2.97526 5.97581 2.97875 5.77263L2.99985 4.54699C3.02694 2.97354 4.43987 1.78794 5.99413 2.03449L7.20481 2.22654C7.40551 2.25838 7.60845 2.18452 7.74173 2.03112L8.54572 1.10579ZM13.7072 9.42195C14.0977 9.03143 14.0977 8.39826 13.7072 8.00774C13.3167 7.61721 12.6835 7.61721 12.293 8.00774L9.5001 10.8006L8.7072 10.0077C8.31667 9.61721 7.68351 9.61721 7.29298 10.0077C6.90246 10.3983 6.90246 11.0314 7.29298 11.422L8.43944 12.5684C9.02522 13.1542 9.97497 13.1542 10.5608 12.5684L13.7072 9.42195Z" fill="#7AC455"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@ -17,6 +17,7 @@ export type SignaturePadProps = Omit<HTMLAttributes<HTMLCanvasElement>, 'onChang
|
||||
onChange?: (_signatureDataUrl: string | null) => void;
|
||||
containerClassName?: string;
|
||||
disabled?: boolean;
|
||||
height?: number;
|
||||
};
|
||||
|
||||
export const SignaturePad = ({
|
||||
@ -25,6 +26,7 @@ export const SignaturePad = ({
|
||||
defaultValue,
|
||||
onChange,
|
||||
disabled = false,
|
||||
height,
|
||||
...props
|
||||
}: SignaturePadProps) => {
|
||||
const $el = useRef<HTMLCanvasElement>(null);
|
||||
@ -230,6 +232,7 @@ export const SignaturePad = ({
|
||||
onPointerUp={(event) => onMouseUp(event)}
|
||||
onPointerLeave={(event) => onMouseLeave(event)}
|
||||
onPointerEnter={(event) => onMouseEnter(event)}
|
||||
height={height}
|
||||
{...props}
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user