Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
0f1bec2
fix: smooth gradient transition on navbar CTA using overlay pseudo-el…
Smartlify07 Jun 30, 2026
9403570
fix: smooth gradient transition on hero book consultation button
Smartlify07 Jun 30, 2026
a057b10
feat: scroll-into-view expand animation on hero image using motion
Smartlify07 Jun 30, 2026
87b105c
fix: hero image expands from 700px to full 1024px container on scroll
Smartlify07 Jun 30, 2026
9aac4c7
refactor: use scale transform for hero image scroll animation instead…
Smartlify07 Jun 30, 2026
61192d6
chore: add motion package and finish navbar animation
Smartlify07 Jun 30, 2026
bda2bae
feat: horizontal expand/shrink on bridging the gap cards on hover
Smartlify07 Jun 30, 2026
8b474c4
fix: add shrink-0 to image wrappers to prevent flex compression
Smartlify07 Jun 30, 2026
a4cc51f
fix: testimonials image overflow and scroll-to-end on button click
Smartlify07 Jun 30, 2026
66137c0
fix: horizontal overflow clipping on testimonials scroll container
Smartlify07 Jun 30, 2026
9e97af0
fix: disable manual horizontal scroll, button-only navigation
Smartlify07 Jun 30, 2026
6f6448b
feat: accordion FAQ with expand/collapse and 360deg plus spin
Smartlify07 Jun 30, 2026
98ecafe
fix: slow cross rotation speed by 2x (600ms)
Smartlify07 Jun 30, 2026
116b00d
feat: add arrow rotation on hover to CTA button
Smartlify07 Jun 30, 2026
441c87c
feat: join button scale up, gradient, and arrow rotation on hover
Smartlify07 Jun 30, 2026
4c60662
feat: add muted hover background to course cards
Smartlify07 Jun 30, 2026
a1a0d49
feat: add gradient overlay and arrow rotation to enroll button
Smartlify07 Jun 30, 2026
f5a804c
feat: add gradient border to enroll button using before pseudo-element
Smartlify07 Jun 30, 2026
d0709b0
fix: revert hero enroll button; add gradient border to content sectio…
Smartlify07 Jun 30, 2026
8758cb7
fix: gradient border only visible on hover, white bg + primary text +…
Smartlify07 Jun 30, 2026
39fbc85
fix: add variant outline and isolate to fix text visibility and z-ind…
Smartlify07 Jun 30, 2026
3f4290f
fix: make Button background transparent so before gradient border is …
Smartlify07 Jun 30, 2026
2cc3e1c
fix: use wrapper pattern for gradient border on enroll button
Smartlify07 Jun 30, 2026
91f17c9
feat: add accordion transitions to course modules, gradient hover to …
Smartlify07 Jun 30, 2026
dedee60
feat: restrict mission hover interaction to large screens only
Smartlify07 Jul 1, 2026
e52454b
feat: add max-width 1440px to all page sections, fix testimonials ali…
Smartlify07 Jul 1, 2026
4aab02a
ch: resolve merge conflicts
Smartlify07 Jul 1, 2026
90572e3
feat: conditional FAQ rendering, donation page CTA with hover state, …
Smartlify07 Jul 1, 2026
df1e1b3
ch: resolve merge conflicts
Smartlify07 Jul 1, 2026
1eb34c5
feat: update auth screens UI with new components and styling
Smartlify07 Jul 1, 2026
92a9c86
feat: add gradient hover to auth form buttons, hide CTA on auth pages
Smartlify07 Jul 1, 2026
e706ff1
ch: fix merge conflicts
Smartlify07 Jul 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/app/(marketing)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { LoginForm } from "@/features/auth/components/login-form"

export default function Page() {
return (
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
<div className="w-full max-w-sm">
<div className="flex min-h-svh w-full items-center justify-center bg-white p-6 md:py-15.5">
<div className="w-full max-w-110.5">
<LoginForm />
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/app/(marketing)/signup/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { SignupForm } from "@/features/auth/components/signup-form"

export default function Page() {
return (
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
<div className="w-full max-w-sm">
<div className="flex min-h-svh w-full items-center justify-center bg-white p-6 md:py-15.5">
<div className="w-full max-w-110.5">
<SignupForm />
</div>
</div>
Expand Down
153 changes: 153 additions & 0 deletions src/features/auth/components/auth-code-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
"use client"

import { Lock } from "lucide-react"
import Link from "next/link"
import { Controller, useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"

import { cn } from "@/shared/utils"
import { Button } from "@/shared/ui/button"
import {
Field,
FieldDescription,
FieldError,
FieldGroup,
FieldLabel,
FieldSeparator,
} from "@/shared/ui/field"
import { Input } from "@/shared/ui/input"

const codeSchema = z.object({
code: z
.string()
.trim()
.regex(/^\d{6}$/, { message: "Enter the 6-digit code" }),
})

type AuthCodeFormProps = React.ComponentProps<"div"> & {
email: string
mode: "login" | "signup"
onDifferentAccount?: () => void
onResendCode?: () => void
onSubmitCode?: (code: string) => void | Promise<void>
Comment on lines +28 to +33

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Prevent auth actions from silently no-oping.

onSubmitCode and onResendCode are optional, and the current login/signup callers omit them. That means submitting a valid code and clicking “Resend code” can complete with no verification or resend request. Make these callbacks required, or render an explicit disabled/error state until they are provided.

Proposed contract tightening
 type AuthCodeFormProps = React.ComponentProps<"div"> & {
   email: string
   mode: "login" | "signup"
   onDifferentAccount?: () => void
-  onResendCode?: () => void
-  onSubmitCode?: (code: string) => void | Promise<void>
+  onResendCode: () => void | Promise<void>
+  onSubmitCode: (code: string) => void | Promise<void>
 }
@@
   const onSubmit = async (data: z.infer<typeof codeSchema>) => {
-    await onSubmitCode?.(data.code)
+    await onSubmitCode(data.code)
   }

Also applies to: 59-60, 117-123

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/auth/components/auth-code-form.tsx` around lines 28 - 33, The
auth flow in AuthCodeForm can silently do nothing because onSubmitCode and
onResendCode are optional while the current callers omit them. Tighten the
contract in AuthCodeFormProps by making the callbacks required, or add an
explicit disabled/error state in AuthCodeForm and its submit/resend handlers
until the callers provide them. Update the related login/signup call sites and
any handler usage in AuthCodeForm so submitting a code and clicking “Resend
code” always triggers real auth behavior or is clearly blocked.

}

export function AuthCodeForm({
className,
email,
mode,
onDifferentAccount,
onResendCode,
onSubmitCode,
...props
}: AuthCodeFormProps) {
const form = useForm<z.infer<typeof codeSchema>>({
resolver: zodResolver(codeSchema),
defaultValues: {
code: "",
},
})

const actionLabel = mode === "login" ? "Log in" : "Sign up"
const flowLabel = mode === "login" ? "login" : "sign up"
const switchLabel =
mode === "login"
? "Log in to a different account"
: "Sign up with a different account"

const onSubmit = async (data: z.infer<typeof codeSchema>) => {
await onSubmitCode?.(data.code)
}

return (
<div
className={cn("flex w-full flex-col items-center gap-[45px]", className)}
{...props}
>
<div className="flex w-full flex-col items-center gap-[30px] text-center">
<h1 className="text-4xl leading-normal font-extrabold text-ma-text">
Check your inbox
</h1>
<p className="max-w-[442px] text-lg leading-normal text-[#6b7280]">
Enter the 6-digit code we sent to{" "}
<span className="font-medium text-ma-text">{email}</span> to finish
your {flowLabel}.
</p>
</div>

<form className="w-full" onSubmit={form.handleSubmit(onSubmit)}>
<FieldGroup className="gap-5">
<Controller
control={form.control}
name="code"
render={({ fieldState, field }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor={field.name} className="sr-only">
6-digit code
</FieldLabel>
<div className="relative">
<Input
{...field}
id={field.name}
inputMode="numeric"
autoComplete="one-time-code"
aria-invalid={fieldState.invalid}
placeholder="6-digit code"
className="h-11 rounded-md border-[#6b7280] px-5 py-5 pr-14 text-lg placeholder:text-[#6b7280]"
/>
<Lock
className="pointer-events-none absolute top-1/2 right-5 size-6 -translate-y-1/2 text-[#6b7280]"
aria-hidden="true"
/>
</div>
<FieldError errors={[fieldState.error]} />
</Field>
)}
/>

<Button
type="submit"
className="group relative h-[53px] w-full overflow-hidden rounded-[60px] bg-ma-text px-5 py-4 text-base font-semibold text-white"
>
<span className="relative z-10">{actionLabel}</span>
<div className="pointer-events-none absolute inset-0 rounded-[60px] bg-gradient-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</Button>

<FieldSeparator className="my-0 w-full [&_[data-slot=field-separator-content]]:bg-white">
<button
type="button"
onClick={onResendCode}
className="text-lg leading-normal font-medium text-ma-text underline underline-offset-2"
>
Resend code
</button>
</FieldSeparator>
</FieldGroup>
</form>

<div className="flex w-full items-center justify-center rounded-md bg-[#f5f5f5] px-[30px] py-[50px]">
{onDifferentAccount ? (
<button
type="button"
onClick={onDifferentAccount}
className="text-lg leading-normal font-semibold text-ma-text underline underline-offset-2"
>
{switchLabel}
</button>
) : (
<Link
href={mode === "login" ? "/login" : "/signup"}
className="text-lg leading-normal font-semibold text-ma-text underline underline-offset-2"
>
{switchLabel}
</Link>
)}
</div>

<FieldDescription className="sr-only">
Use the code sent to your email address to continue.
</FieldDescription>
</div>
)
}
42 changes: 42 additions & 0 deletions src/features/auth/components/auth-google-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Button } from "@/shared/ui/button"

function GoogleMark() {
return (
<svg
aria-hidden="true"
viewBox="0 0 18 18"
className="size-4"
focusable="false"
>
<path
fill="#4285f4"
d="M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.88 2.68-6.62Z"
/>
<path
fill="#34a853"
d="M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.8.54-1.84.86-3.04.86-2.34 0-4.32-1.58-5.03-3.7H.96v2.34A9 9 0 0 0 9 18Z"
/>
<path
fill="#fbbc05"
d="M3.97 10.72A5.41 5.41 0 0 1 3.68 9c0-.6.1-1.18.29-1.72V4.94H.96A9 9 0 0 0 0 9c0 1.45.35 2.82.96 4.06l3.01-2.34Z"
/>
<path
fill="#ea4335"
d="M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.58A8.65 8.65 0 0 0 9 0 9 9 0 0 0 .96 4.94l3.01 2.34C4.68 5.16 6.66 3.58 9 3.58Z"
/>
</svg>
)
}

export function AuthGoogleButton({ label }: { label: string }) {
return (
<Button
type="button"
variant="outline"
className="h-[53px] w-full gap-2.5 rounded-[60px] border-[#d9d9d9] bg-white px-5 py-4 text-base font-medium text-ma-text hover:bg-[#f5f5f5]"
>
<GoogleMark />
{label}
</Button>
Comment on lines +31 to +40

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Expose a Google auth action.

This renders an inert type="button" and the login/signup forms pass no handler, so the Google option never starts OAuth. Accept/pass through button props so callers can wire the auth action.

Proposed prop forwarding
+import type { ComponentProps } from "react"
 import { Button } from "`@/shared/ui/button`"
+import { cn } from "`@/shared/utils`"
@@
-export function AuthGoogleButton({ label }: { label: string }) {
+type AuthGoogleButtonProps = ComponentProps<typeof Button> & {
+  label: string
+}
+
+export function AuthGoogleButton({
+  label,
+  className,
+  type = "button",
+  ...props
+}: AuthGoogleButtonProps) {
   return (
     <Button
-      type="button"
+      type={type}
       variant="outline"
-      className="h-[53px] w-full gap-2.5 rounded-[60px] border-[`#d9d9d9`] bg-white px-5 py-4 text-base font-medium text-ma-text hover:bg-[`#f5f5f5`]"
+      className={cn(
+        "h-[53px] w-full gap-2.5 rounded-[60px] border-[`#d9d9d9`] bg-white px-5 py-4 text-base font-medium text-ma-text hover:bg-[`#f5f5f5`]",
+        className,
+      )}
+      {...props}
     >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function AuthGoogleButton({ label }: { label: string }) {
return (
<Button
type="button"
variant="outline"
className="h-[53px] w-full gap-2.5 rounded-[60px] border-[#d9d9d9] bg-white px-5 py-4 text-base font-medium text-ma-text hover:bg-[#f5f5f5]"
>
<GoogleMark />
{label}
</Button>
type AuthGoogleButtonProps = ComponentProps<typeof Button> & {
label: string
}
export function AuthGoogleButton({
label,
className,
type = "button",
...props
}: AuthGoogleButtonProps) {
return (
<Button
type={type}
variant="outline"
className={cn(
"h-[53px] w-full gap-2.5 rounded-[60px] border-[`#d9d9d9`] bg-white px-5 py-4 text-base font-medium text-ma-text hover:bg-[`#f5f5f5`]",
className,
)}
{...props}
>
<GoogleMark />
{label}
</Button>
)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/auth/components/auth-google-button.tsx` around lines 31 - 40,
AuthGoogleButton currently renders a non-functional button and blocks the Google
auth flow because it only accepts label and never forwards an action handler.
Update AuthGoogleButton to accept and pass through button props (especially
onClick and any other needed Button props) to the underlying Button component,
while keeping the existing label and GoogleMark rendering so login/signup forms
can wire the OAuth action.

)
}
Loading