Skip to content

Commit c3f06c7

Browse files
authored
Implement new onboarding modal #346 (#353)
* onboarding form style changes * made co-op checkbox optional * added grad year validation msg + updated major form control * small styling fixes on header, checkbox, and dropdowns * graduation year validation not needed * removed unused inport * fix email placeholder and scroll overflow
1 parent 746e674 commit c3f06c7

File tree

9 files changed

+115
-92
lines changed

9 files changed

+115
-92
lines changed

apps/web/src/app/_components/combo-box.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export default function ComboBox({
5454

5555
const styleVariant =
5656
variant === "form"
57-
? "flex h-16 w-full rounded-lg border-2 border-cooper-gray-150 bg-white px-3 py-2 text-xl font-normal ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
57+
? "flex h-16 w-full rounded-lg border border-cooper-gray-150 bg-white px-3 py-2 text-xl font-normal ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
5858
: variant === "filtering"
5959
? "w-36 md:w-[21rem] h-10 lg:h-12 border-cooper-gray-400 text-lg placeholder:opacity-50 focus:ring-0 active:ring-0 rounded-lg border-[0.75px] py-0"
6060
: "h-8 py-0";

apps/web/src/app/_components/onboarding/dialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export function OnboardingDialog({
4343
return (
4444
<Dialog open={open} onOpenChange={setOpen}>
4545
<DialogContent
46-
className="max-h-[90dvh] max-w-[85dvw] overflow-y-scroll rounded-lg p-8 md:max-w-[70dvw] lg:max-w-[46rem] lg:p-12"
46+
className="max-h-[90dvh] max-w-[85dvw] overflow-y-auto rounded-lg p-6 md:max-w-[70dvw] lg:max-w-[46rem] lg:p-8"
4747
aria-describedby="The form to create a Cooper profile once you have logged in with a husky google account."
4848
>
4949
<OnboardingForm

apps/web/src/app/_components/onboarding/onboarding-form.tsx

Lines changed: 81 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import { useForm } from "react-hook-form";
44
import { z } from "zod";
55

66
import type { Session } from "@cooper/auth";
7-
import { cn } from "@cooper/ui";
87
import { Button } from "@cooper/ui/button";
98
import { DialogTitle } from "@cooper/ui/dialog";
109
import { Form, FormControl, FormField, FormItem } from "@cooper/ui/form";
10+
import { Checkbox } from "@cooper/ui/checkbox";
1111

1212
import {
1313
FormLabel,
@@ -40,9 +40,7 @@ const formSchema = z.object({
4040
.number()
4141
.min(1, "Graduation month is required")
4242
.max(12, "Invalid month"),
43-
cooped: z.boolean({
44-
required_error: "Please select whether you've completed a co-op before",
45-
}),
43+
cooped: z.boolean().optional(),
4644
});
4745

4846
export type OnboardingFormType = z.infer<typeof formSchema>;
@@ -101,13 +99,10 @@ export function OnboardingForm({
10199

102100
return (
103101
<>
104-
<DialogTitle className="pb-2 text-center text-2xl font-bold">
105-
Create a Cooper Account
102+
<DialogTitle className="pb-6 text-left text-lg font-medium ">
103+
Let’s get you setup
106104
</DialogTitle>
107105
<Form {...form}>
108-
<p className="text-gray-500">
109-
<span className="text-red-500">* </span>Required
110-
</p>
111106
<form
112107
onSubmit={form.handleSubmit(onSubmit)}
113108
className="flex flex-col space-y-6"
@@ -120,7 +115,11 @@ export function OnboardingForm({
120115
<FormItem className="max-w-72">
121116
<FormLabel required>First Name</FormLabel>
122117
<FormControl>
123-
<Input placeholder="First" {...field} />
118+
<Input
119+
placeholder="First"
120+
{...field}
121+
onClear={() => field.onChange("")}
122+
/>
124123
</FormControl>
125124
<FormMessage className="text-base" />
126125
</FormItem>
@@ -133,7 +132,11 @@ export function OnboardingForm({
133132
<FormItem className="max-w-72 lg:ml-2">
134133
<FormLabel required>Last Name</FormLabel>
135134
<FormControl>
136-
<Input placeholder="Last" {...field} />
135+
<Input
136+
placeholder="Last"
137+
{...field}
138+
onClear={() => field.onChange("")}
139+
/>
137140
</FormControl>
138141
<FormMessage />
139142
</FormItem>
@@ -144,10 +147,14 @@ export function OnboardingForm({
144147
control={form.control}
145148
name="email"
146149
render={({ field }) => (
147-
<FormItem className="max-w-72">
150+
<FormItem>
148151
<FormLabel required>Email</FormLabel>
149152
<FormControl>
150-
<Input placeholder="example@example.com" {...field} />
153+
<Input
154+
placeholder="example@husky.neu.edu"
155+
{...field}
156+
onClear={() => field.onChange("")}
157+
/>
151158
</FormControl>
152159
<FormMessage />
153160
</FormItem>
@@ -158,25 +165,28 @@ export function OnboardingForm({
158165
control={form.control}
159166
name="major"
160167
render={() => (
161-
<FormItem className="max-w-72">
162-
<FormLabel>Major</FormLabel>
163-
<ComboBox
164-
defaultLabel={majorLabel || "Select major..."}
165-
searchPlaceholder="Search major..."
166-
searchEmpty="No major found."
167-
valuesAndLabels={majors.map((major) => ({
168-
value: major,
169-
label: major,
170-
}))}
171-
currLabel={majorLabel}
172-
onSelect={(currentValue) => {
173-
setMajorLabel(
174-
currentValue === majorLabel ? "" : currentValue,
175-
);
176-
form.setValue("major", currentValue);
177-
}}
178-
triggerClassName="max-w-72"
179-
/>
168+
<FormItem>
169+
<FormLabel required>Major</FormLabel>
170+
<FormControl>
171+
<ComboBox
172+
variant="form"
173+
defaultLabel={majorLabel || "Select major..."}
174+
searchPlaceholder="Search major..."
175+
searchEmpty="No major found."
176+
valuesAndLabels={majors.map((major) => ({
177+
value: major,
178+
label: major,
179+
}))}
180+
currLabel={majorLabel}
181+
onSelect={(currentValue) => {
182+
setMajorLabel(
183+
currentValue === majorLabel ? "" : currentValue,
184+
);
185+
form.setValue("major", currentValue);
186+
}}
187+
/>
188+
</FormControl>
189+
<FormMessage />
180190
</FormItem>
181191
)}
182192
/>
@@ -185,42 +195,51 @@ export function OnboardingForm({
185195
control={form.control}
186196
name="minor"
187197
render={({ field }) => (
188-
<FormItem className="max-w-72">
198+
<FormItem>
189199
<FormLabel>Minor</FormLabel>
190200
<FormControl>
191-
<Input placeholder="Minor" {...field} />
201+
<Input
202+
placeholder="Minor"
203+
{...field}
204+
onClear={() => field.onChange("")}
205+
/>
192206
</FormControl>
193207
<FormMessage />
194208
</FormItem>
195209
)}
196210
/>
197211
</div>
212+
198213
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
199214
<FormField
200215
control={form.control}
201-
name="graduationYear"
216+
name="graduationMonth"
202217
render={({ field }) => (
203-
<FormItem className="max-w-72">
204-
<FormLabel required>Graduation Year</FormLabel>
218+
<FormItem>
219+
<FormLabel required>Graduation Month</FormLabel>
205220
<FormControl>
206-
<Input placeholder="Year" {...field} />
221+
<Select
222+
placeholder="Month"
223+
options={monthOptions}
224+
className="min-w-full"
225+
{...field}
226+
/>
207227
</FormControl>
208228
<FormMessage />
209229
</FormItem>
210230
)}
211231
/>
212232
<FormField
213233
control={form.control}
214-
name="graduationMonth"
234+
name="graduationYear"
215235
render={({ field }) => (
216-
<FormItem className="max-w-72">
217-
<FormLabel required>Graduation Month</FormLabel>
236+
<FormItem>
237+
<FormLabel required>Graduation Year</FormLabel>
218238
<FormControl>
219-
<Select
220-
placeholder="Month"
221-
options={monthOptions}
222-
className="min-w-full"
239+
<Input
240+
placeholder="Year"
223241
{...field}
242+
onClear={() => field.onChange("")}
224243
/>
225244
</FormControl>
226245
<FormMessage />
@@ -232,42 +251,21 @@ export function OnboardingForm({
232251
control={form.control}
233252
name="cooped"
234253
render={({ field }) => (
235-
<FormItem>
236-
<FormLabel required>
237-
Have you completed a co-op before?
238-
</FormLabel>
254+
<FormItem className="max-w-72">
239255
<FormControl>
240-
<FormItem className="flex items-center space-x-4">
256+
<FormItem>
241257
<FormControl>
242-
<div>
243-
<Button
244-
type="button"
245-
variant={cooped === true ? "default" : "outline"}
246-
className={cn(
247-
"mr-0 h-12 rounded-r-none border-2 border-cooper-gray-300 text-lg text-cooper-gray-400 shadow-none ring-offset-background hover:bg-accent hover:text-black focus-visible:ring-0 focus-visible:ring-ring focus-visible:ring-offset-2",
248-
cooped === true && "bg-cooper-blue-200 text-black",
249-
)}
250-
onClick={() => {
251-
setCooped(true);
252-
field.onChange(true);
253-
}}
254-
>
255-
Yes
256-
</Button>
257-
<Button
258-
type="button"
259-
variant={cooped === false ? "default" : "outline"}
260-
className={cn(
261-
"ml-0 h-12 rounded-l-none border-2 border-l-0 border-cooper-gray-300 text-lg text-cooper-gray-400 shadow-none ring-offset-background hover:bg-accent hover:text-black focus-visible:ring-0 focus-visible:ring-ring focus-visible:ring-offset-2",
262-
cooped === false && "bg-cooper-blue-200 text-black",
263-
)}
264-
onClick={() => {
265-
setCooped(false);
266-
field.onChange(false);
258+
<div className="flex items-center space-x-2">
259+
<Checkbox
260+
checked={cooped}
261+
onCheckedChange={(checked) => {
262+
setCooped(checked === true);
263+
field.onChange(checked === true);
267264
}}
268-
>
269-
No
270-
</Button>
265+
/>
266+
<FormLabel>
267+
I have completed a co-op or internship
268+
</FormLabel>
271269
</div>
272270
</FormControl>
273271
</FormItem>
@@ -277,8 +275,11 @@ export function OnboardingForm({
277275
)}
278276
/>
279277
<div className="mt-4 flex justify-end">
280-
<Button type="submit" className="w-24">
281-
Next
278+
<Button
279+
type="submit"
280+
className=" bg-cooper-gray-550 border-cooper-gray-550 hover:bg-cooper-gray-300 hover:border-cooper-gray-300 px-3.5 py-2 text-base font-bold"
281+
>
282+
Finish
282283
</Button>
283284
</div>
284285
</form>

apps/web/src/app/_components/themed/onboarding/form.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export function FormLabel({
99
...props
1010
}: React.ComponentProps<typeof FormLabelPrimitive> & { required?: boolean }) {
1111
return (
12-
<FormLabelPrimitive className="text-lg font-semibold text-black" {...props}>
12+
<FormLabelPrimitive className="text-sm font-bold text-black" {...props}>
1313
{children}
1414
{required && <span className="ml-1 text-red-500">*</span>}
1515
</FormLabelPrimitive>
Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,32 @@
11
import { Input as InputPrimitive } from "@cooper/ui/input";
2+
import { X } from "lucide-react";
23

3-
export function Input(props: React.ComponentProps<typeof InputPrimitive>) {
4+
interface InputProps extends React.ComponentProps<typeof InputPrimitive> {
5+
onClear?: () => void;
6+
}
7+
8+
export function Input({ onClear, ...props }: InputProps) {
49
return (
5-
<InputPrimitive
6-
className="h-12 rounded-lg border-2 border-cooper-gray-300 text-lg shadow-none hover:bg-accent"
7-
{...props}
8-
/>
10+
<div className="relative w-full">
11+
<InputPrimitive
12+
className="h-9 rounded-lg border border-cooper-gray-150 text-sm shadow-none hover:bg-accent pr-10"
13+
{...props}
14+
/>
15+
{onClear && (
16+
<div className="absolute inset-y-0 right-3 flex items-center">
17+
<button
18+
type="button"
19+
onClick={(e) => {
20+
e.stopPropagation();
21+
onClear();
22+
}}
23+
className="pointer-events-auto flex items-center justify-center rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none"
24+
aria-label="Clear input"
25+
>
26+
<X className="h-4 w-4" />
27+
</button>
28+
</div>
29+
)}
30+
</div>
931
);
1032
}

apps/web/src/app/_components/themed/onboarding/select.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const Select: React.FC<SelectProps> = ({
1919
<div className="relative w-full">
2020
<select
2121
className={cn(
22-
"h-12 w-full appearance-none rounded-lg border-2 border-cooper-gray-300 bg-transparent px-4 pr-10 text-lg text-cooper-gray-400 shadow-none placeholder:text-muted-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
22+
"h-9 w-full appearance-none rounded-lg border border-cooper-gray-150 bg-transparent px-4 pr-10 text-sm text-cooper-gray-350 shadow-none placeholder:text-muted-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
2323
className,
2424
)}
2525
{...props}

packages/ui/src/checkbox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const Checkbox = React.forwardRef<
1313
<CheckboxPrimitive.Root
1414
ref={ref}
1515
className={cn(
16-
"border-cooper-gray-600 data-[state=checked]:bg-cooper-gray-600 peer h-[23px] w-[23px] shrink-0 rounded-[5px] border bg-white ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:text-white",
16+
"border-cooper-gray-600 data-[state=checked]:bg-cooper-gray-550 data-[state=checked]:border-cooper-gray-550 peer h-[23px] w-[23px] shrink-0 rounded-[5px] border bg-white ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:text-white",
1717
className,
1818
)}
1919
{...props}

packages/ui/src/dialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const DialogContent = React.forwardRef<
3737
<DialogPrimitive.Content
3838
ref={ref}
3939
className={cn(
40-
"relative z-50 mx-2 gap-4 rounded-lg border bg-background p-6 shadow-lg animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",
40+
"relative z-50 mx-2 gap-6 rounded-lg border bg-background p-6 shadow-lg animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",
4141
className,
4242
)}
4343
{...props}

packages/ui/src/form.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ const FormItem = React.forwardRef<
7070

7171
return (
7272
<FormItemContext.Provider value={{ id }}>
73-
<div ref={ref} className={cn("space-y-2", className)} {...props} />
73+
<div ref={ref} className={cn("space-y-1.5", className)} {...props} />
7474
</FormItemContext.Provider>
7575
);
7676
});

0 commit comments

Comments
 (0)