Make login and onboarding mobile friendly

This commit is contained in:
bkellam 2025-02-27 13:25:24 -08:00
parent d0b75ce57d
commit 161f21eb57
8 changed files with 21 additions and 17 deletions

View file

@ -252,7 +252,7 @@ const ImportSecretDialog = ({ open, onOpenChange, onSecretCreated, codeHostType
onOpenChange={onOpenChange} onOpenChange={onOpenChange}
> >
<DialogContent <DialogContent
className="p-16 max-w-2xl max-h-[80vh] overflow-scroll" className="p-16 max-w-[90vw] sm:max-w-2xl max-h-[80vh] overflow-scroll rounded-lg"
> >
<DialogHeader> <DialogHeader>
<DialogTitle className="text-2xl font-semibold">Import a secret</DialogTitle> <DialogTitle className="text-2xl font-semibold">Import a secret</DialogTitle>

View file

@ -83,7 +83,7 @@ interface CodeHostSelectionProps {
const CodeHostSelection = ({ onSelect }: CodeHostSelectionProps) => { const CodeHostSelection = ({ onSelect }: CodeHostSelectionProps) => {
return ( return (
<div className="flex flex-row gap-4"> <div className="grid grid-cols-2 sm:grid-cols-4 gap-4">
<CodeHostButton <CodeHostButton
name="GitHub" name="GitHub"
logo={getCodeHostIcon("github")!} logo={getCodeHostIcon("github")!}

View file

@ -72,7 +72,7 @@ export const InviteTeam = ({ nextStep }: InviteTeamProps) => {
}, [onComplete, form, captureEvent]); }, [onComplete, form, captureEvent]);
return ( return (
<Card className="p-12 w-[500px]"> <Card className="p-12 w-full sm:max-w-[500px]">
<Form {...form}> <Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}> <form onSubmit={form.handleSubmit(onSubmit)}>
<CardContent className="space-y-4"> <CardContent className="space-y-4">

View file

@ -41,8 +41,8 @@ export default async function Onboard({ params, searchParams }: OnboardProps) {
const lastRequiredStep = OnboardingSteps.Checkout; const lastRequiredStep = OnboardingSteps.Checkout;
return ( return (
<div className="flex flex-col items-center p-12 min-h-screen bg-backgroundSecondary relative"> <div className="flex flex-col items-center py-12 px-4 sm:px-12 min-h-screen bg-backgroundSecondary relative">
<LogoutEscapeHatch className="absolute top-0 right-0 p-12" /> <LogoutEscapeHatch className="absolute top-0 right-0 p-4 sm:p-12" />
{step === OnboardingSteps.ConnectCodeHost && ( {step === OnboardingSteps.ConnectCodeHost && (
<> <>
<OnboardHeader <OnboardHeader

View file

@ -45,14 +45,14 @@ export const LoginForm = ({ callbackUrl, error, enabledMethods }: LoginFormProps
}, [error]); }, [error]);
return ( return (
<div className="flex flex-col items-center justify-center"> <div className="flex flex-col items-center justify-center w-full">
<div className="mb-6 flex flex-col items-center"> <div className="mb-6 flex flex-col items-center">
<SourcebotLogo <SourcebotLogo
className="h-16" className="h-12 sm:h-16"
/> />
<h2 className="text-lg font-bold">Sign in to your account</h2> <h2 className="text-lg font-bold text-center">Sign in to your account</h2>
</div> </div>
<Card className="flex flex-col items-center border p-12 rounded-lg gap-6 w-[500px] bg-background"> <Card className="flex flex-col items-center border p-6 sm:p-12 rounded-lg gap-4 sm:gap-6 w-full sm:w-[500px] max-w-[500px] bg-background">
{error && ( {error && (
<div className="text-sm text-destructive text-center text-wrap border p-2 rounded-md border-destructive"> <div className="text-sm text-destructive text-center text-wrap border p-2 rounded-md border-destructive">
{errorMessage} {errorMessage}

View file

@ -27,7 +27,7 @@ export default async function Login({ searchParams }: LoginProps) {
}); });
return ( return (
<div className="flex flex-col items-center p-12 h-screen bg-backgroundSecondary"> <div className="flex flex-col items-center p-4 sm:p-12 min-h-screen w-full bg-backgroundSecondary">
<LoginForm <LoginForm
callbackUrl={searchParams.callbackUrl} callbackUrl={searchParams.callbackUrl}
error={searchParams.error} error={searchParams.error}

View file

@ -7,7 +7,7 @@ import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from "
import { useForm } from "react-hook-form" import { useForm } from "react-hook-form"
import { z } from "zod" import { z } from "zod"
import { zodResolver } from "@hookform/resolvers/zod" import { zodResolver } from "@hookform/resolvers/zod"
import { useCallback } from "react"; import { useCallback, useState } from "react";
import { isServiceError } from "@/lib/utils" import { isServiceError } from "@/lib/utils"
import { Loader2 } from "lucide-react" import { Loader2 } from "lucide-react"
import { useToast } from "@/components/hooks/use-toast" import { useToast } from "@/components/hooks/use-toast"
@ -20,6 +20,7 @@ export function OrgCreateForm() {
const { toast } = useToast(); const { toast } = useToast();
const router = useRouter(); const router = useRouter();
const captureEvent = useCaptureEvent(); const captureEvent = useCaptureEvent();
const [isLoading, setIsLoading] = useState(false);
const onboardingFormSchema = z.object({ const onboardingFormSchema = z.object({
name: z.string() name: z.string()
@ -49,9 +50,9 @@ export function OrgCreateForm() {
domain: "", domain: "",
} }
}); });
const { isSubmitting } = form.formState;
const onSubmit = useCallback(async (data: z.infer<typeof onboardingFormSchema>) => { const onSubmit = useCallback(async (data: z.infer<typeof onboardingFormSchema>) => {
setIsLoading(true);
const response = await createOrg(data.name, data.domain); const response = await createOrg(data.name, data.domain);
if (isServiceError(response)) { if (isServiceError(response)) {
toast({ toast({
@ -60,9 +61,12 @@ export function OrgCreateForm() {
captureEvent('wa_onboard_org_create_fail', { captureEvent('wa_onboard_org_create_fail', {
error: response.errorCode, error: response.errorCode,
}) })
setIsLoading(false);
} else { } else {
router.push(`/${data.domain}/onboard`); router.push(`/${data.domain}/onboard`);
captureEvent('wa_onboard_org_create_success', {}) captureEvent('wa_onboard_org_create_success', {});
// @note: we don't want to set isLoading to false here since we want to show the loading
// spinner until the page is redirected.
} }
}, [router, toast, captureEvent]); }, [router, toast, captureEvent]);
@ -113,8 +117,8 @@ export function OrgCreateForm() {
</FormItem> </FormItem>
)} )}
/> />
<Button variant="default" className="w-full" type="submit" disabled={isSubmitting}> <Button variant="default" className="w-full" type="submit" disabled={isLoading}>
{isSubmitting && <Loader2 className="w-4 h-4 mr-2 animate-spin" />} {isLoading && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
Create Create
</Button> </Button>
</form> </form>

View file

@ -12,14 +12,14 @@ export default async function Onboarding() {
} }
return ( return (
<div className="flex flex-col items-center min-h-screen p-12 bg-backgroundSecondary relative"> <div className="flex flex-col items-center min-h-screen py-12 px-4 sm:px-12 bg-backgroundSecondary relative">
<OnboardHeader <OnboardHeader
title="Setup your organization" title="Setup your organization"
description="Create a organization for your team to search and share code across your repositories." description="Create a organization for your team to search and share code across your repositories."
step={OnboardingSteps.CreateOrg} step={OnboardingSteps.CreateOrg}
/> />
<OrgCreateForm /> <OrgCreateForm />
<LogoutEscapeHatch className="absolute top-0 right-0 p-12" /> <LogoutEscapeHatch className="absolute top-0 right-0 p-4 sm:p-12" />
</div> </div>
); );
} }