Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 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
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"dotenv": "^17.4.2",
"drizzle-orm": "^0.45.2",
"lucide-react": "^1.17.0",
"motion": "^12.42.0",
"next": "16.2.6",
"next-themes": "^0.4.6",
"pg": "^8.21.0",
Expand Down
60 changes: 60 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions src/features/marketing/components/contact-hero-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,13 @@ export function ContactHeroSection() {

<Button
type="button"
className="mt-1 h-[53px] w-full gap-2.5 rounded-[60px] bg-ma-text px-5 py-4 text-base font-semibold text-white hover:bg-ma-text/90"
className="group relative mt-1 h-[53px] w-full overflow-hidden rounded-[60px] bg-ma-text px-5 py-4 text-base font-semibold text-white"
>
Send your message
<ArrowRight className="size-5" aria-hidden="true" />
<span className="relative z-10 inline-flex items-center gap-2.5">
Send your message
<ArrowRight className="size-5 transition-transform duration-300 group-hover:rotate-[-30deg]" aria-hidden="true" />
</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>
</FieldGroup>
</form>
Expand Down
199 changes: 152 additions & 47 deletions src/features/marketing/components/course-detail-content-section.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
"use client"

import Image from "next/image"
import Link from "next/link"
import {
ArrowRight,
ChevronDown,
ChevronUp,
Clock,
Languages,
Layers,
PlayCircle,
Star,
User,
} from "lucide-react"
import { useState } from "react"

import { Button } from "@/shared/ui/button"

Expand All @@ -28,17 +30,105 @@ const modules = [
"Beginner-friendly digital business models",
],
},
{ title: "Week 2: AI Productivity & Prompting" },
{ title: "Week 3: Business Validation & Fast Monetization Planning" },
{ title: "Week 4: Branding & Digital Presence" },
{ title: "Week 5: Product & Service Creation" },
{ title: "Week 6: Marketing & Public Launch" },
{ title: "Week 7: Client Acquisition & Sales Systems" },
{ title: "Week 8: Revenue Optimization & Sustainability" },
{ title: "Week 9: Automation & Efficiency" },
{ title: "Week 10: Portfolio & Authority Building" },
{ title: "Week 11: Scaling Small Businesses" },
{ title: "Week 12: Demo Day & Graduation" },
{
title: "Week 2: AI Productivity & Prompting",
topics: [
"Crafting effective AI prompts",
"Automating daily workflows with AI",
"AI tools for task management",
"Integrating AI into existing tools",
],
},
{
title: "Week 3: Business Validation & Fast Monetization Planning",
topics: [
"Identifying market problems & opportunities",
"Lean validation techniques",
"Fast monetization strategies",
"Building a minimum viable offer",
],
},
{
title: "Week 4: Branding & Digital Presence",
topics: [
"Defining your brand identity",
"Building a simple website",
"Social media positioning",
"Content creation fundamentals",
],
},
{
title: "Week 5: Product & Service Creation",
topics: [
"Designing digital products",
"Service packaging and pricing",
"AI-assisted product development",
"Testing and iterating your offer",
],
},
{
title: "Week 6: Marketing & Public Launch",
topics: [
"Launch campaign planning",
"Organic marketing channels",
"Paid advertising basics",
"Building launch momentum",
],
},
{
title: "Week 7: Client Acquisition & Sales Systems",
topics: [
"Sales funnel fundamentals",
"Lead generation strategies",
"CRM and follow-up systems",
"Closing techniques for beginners",
],
},
{
title: "Week 8: Revenue Optimization & Sustainability",
topics: [
"Pricing strategy refinement",
"Upselling and cross-selling",
"Customer retention tactics",
"Financial management basics",
],
},
{
title: "Week 9: Automation & Efficiency",
topics: [
"Workflow automation tools",
"AI chatbots for customer support",
"Email marketing automation",
"Analytics and performance tracking",
],
},
{
title: "Week 10: Portfolio & Authority Building",
topics: [
"Creating a professional portfolio",
"Publishing thought leadership content",
"Speaking and networking opportunities",
"Building social proof",
],
},
{
title: "Week 11: Scaling Small Businesses",
topics: [
"Hiring and delegation basics",
"Systems and SOPs for growth",
"Expanding product lines",
"Partnership and collaboration strategies",
],
},
{
title: "Week 12: Demo Day & Graduation",
topics: [
"Presenting your business pitch",
"Demo day preparation",
"Graduation and next steps",
"Community and alumni network",
],
},
]

const reviews = [
Expand Down Expand Up @@ -66,51 +156,62 @@ const courseInformation = [
function CourseModule({
title,
topics,
open = false,
open: defaultOpen = false,
}: {
title: string
topics?: string[]
open?: boolean
}) {
const [open, setOpen] = useState(defaultOpen)

return (
<details
open={open}
className="group rounded-2xl border border-[#d9d9d9] bg-white px-5 pt-[17px] pb-5 open:bg-[#f5f5f5]"
<div
className={`rounded-2xl border border-[#d9d9d9] px-5 pt-[17px] pb-5 transition-colors ${
open ? "bg-[#f5f5f5]" : "bg-white"
}`}
>
<summary className="flex cursor-pointer list-none items-center justify-between gap-4 [&::-webkit-details-marker]:hidden">
<button
type="button"
onClick={() => setOpen(!open)}
className="flex w-full cursor-pointer items-center justify-between gap-4 text-left"
>
<h3 className="text-sm/[100%] leading-normal font-bold text-ma-text sm:text-base">
{title}
</h3>
<span className="inline-flex size-7 shrink-0 items-center justify-center rounded-[15px] border border-[#d9d9d9] bg-white">
<ChevronDown
className="size-3.5 group-open:hidden"
aria-hidden="true"
/>
<ChevronUp
className="hidden size-3.5 group-open:block"
className={`size-3.5 transition-transform duration-600 ${
open ? "rotate-180" : ""
}`}
aria-hidden="true"
/>
</span>
</summary>
</button>

{topics ? (
<div className="mt-4 text-sm leading-normal text-ma-text sm:text-[15px]">
<p>Topics:</p>
<ul className="list-disc pl-5">
{topics.map((topic) => (
<li key={topic}>{topic}</li>
))}
</ul>
</div>
) : null}
</details>
<div
className={`overflow-hidden transition-all duration-300 ${
open ? "max-h-[500px] opacity-100" : "max-h-0 opacity-0"
}`}
>
{topics ? (
<div className="mt-4 text-sm leading-normal text-ma-text sm:text-[15px]">
<p>Topics:</p>
<ul className="list-disc pl-5">
{topics.map((topic) => (
<li key={topic}>{topic}</li>
))}
</ul>
</div>
) : null}
</div>
</div>
)
}
Comment on lines 156 to 209

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Custom accordion drops native disclosure semantics — add aria-expanded/aria-controls.

The previous <details>/<summary> implementation was natively accessible (announces expanded/collapsed state). The new <button>-driven toggle has no aria-expanded on the button and no aria-controls/id linking it to the content panel, so screen reader users get no indication of state.

♿ Proposed fix
+      <button
+        type="button"
+        onClick={() => setOpen(!open)}
+        aria-expanded={open}
+        aria-controls={`module-panel-${title}`}
+        className="flex w-full cursor-pointer items-center justify-between gap-4 text-left"
+      >
-      <button
-        type="button"
-        onClick={() => setOpen(!open)}
-        className="flex w-full cursor-pointer items-center justify-between gap-4 text-left"
-      >
@@
-      <div
+      <div
+        id={`module-panel-${title}`}
         className={`overflow-hidden transition-all duration-300 ${
📝 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
function CourseModule({
title,
topics,
open = false,
open: defaultOpen = false,
}: {
title: string
topics?: string[]
open?: boolean
}) {
const [open, setOpen] = useState(defaultOpen)
return (
<details
open={open}
className="group rounded-2xl border border-[#d9d9d9] bg-white px-5 pt-[17px] pb-5 open:bg-[#f5f5f5]"
<div
className={`rounded-2xl border border-[#d9d9d9] px-5 pt-[17px] pb-5 transition-colors ${
open ? "bg-[#f5f5f5]" : "bg-white"
}`}
>
<summary className="flex cursor-pointer list-none items-center justify-between gap-4 [&::-webkit-details-marker]:hidden">
<button
type="button"
onClick={() => setOpen(!open)}
className="flex w-full cursor-pointer items-center justify-between gap-4 text-left"
>
<h3 className="text-sm/[100%] leading-normal font-bold text-ma-text sm:text-base">
{title}
</h3>
<span className="inline-flex size-7 shrink-0 items-center justify-center rounded-[15px] border border-[#d9d9d9] bg-white">
<ChevronDown
className="size-3.5 group-open:hidden"
aria-hidden="true"
/>
<ChevronUp
className="hidden size-3.5 group-open:block"
className={`size-3.5 transition-transform duration-600 ${
open ? "rotate-180" : ""
}`}
aria-hidden="true"
/>
</span>
</summary>
</button>
{topics ? (
<div className="mt-4 text-sm leading-normal text-ma-text sm:text-[15px]">
<p>Topics:</p>
<ul className="list-disc pl-5">
{topics.map((topic) => (
<li key={topic}>{topic}</li>
))}
</ul>
</div>
) : null}
</details>
<div
className={`overflow-hidden transition-all duration-300 ${
open ? "max-h-[500px] opacity-100" : "max-h-0 opacity-0"
}`}
>
{topics ? (
<div className="mt-4 text-sm leading-normal text-ma-text sm:text-[15px]">
<p>Topics:</p>
<ul className="list-disc pl-5">
{topics.map((topic) => (
<li key={topic}>{topic}</li>
))}
</ul>
</div>
) : null}
</div>
</div>
)
}
function CourseModule({
title,
topics,
open: defaultOpen = false,
}: {
title: string
topics?: string[]
open?: boolean
}) {
const [open, setOpen] = useState(defaultOpen)
return (
<div
className={`rounded-2xl border border-[`#d9d9d9`] px-5 pt-[17px] pb-5 transition-colors ${
open ? "bg-[`#f5f5f5`]" : "bg-white"
}`}
>
<button
type="button"
onClick={() => setOpen(!open)}
aria-expanded={open}
aria-controls={`module-panel-${title}`}
className="flex w-full cursor-pointer items-center justify-between gap-4 text-left"
>
<h3 className="text-sm/[100%] leading-normal font-bold text-ma-text sm:text-base">
{title}
</h3>
<span className="inline-flex size-7 shrink-0 items-center justify-center rounded-[15px] border border-[`#d9d9d9`] bg-white">
<ChevronDown
className={`size-3.5 transition-transform duration-600 ${
open ? "rotate-180" : ""
}`}
aria-hidden="true"
/>
</span>
</button>
<div
id={`module-panel-${title}`}
className={`overflow-hidden transition-all duration-300 ${
open ? "max-h-[500px] opacity-100" : "max-h-0 opacity-0"
}`}
>
{topics ? (
<div className="mt-4 text-sm leading-normal text-ma-text sm:text-[15px]">
<p>Topics:</p>
<ul className="list-disc pl-5">
{topics.map((topic) => (
<li key={topic}>{topic}</li>
))}
</ul>
</div>
) : null}
</div>
</div>
)
}
🤖 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/marketing/components/course-detail-content-section.tsx` around
lines 156 - 209, The custom accordion in CourseModule no longer exposes native
disclosure state, so add accessible toggle semantics to the button and panel.
Update the button in CourseModule to include aria-expanded reflecting the open
state and aria-controls pointing to the collapsible content, and give the
content container a stable id that matches it. Keep the existing open state
logic and ChevronDown rotation, but ensure the button/content pairing in
CourseModule preserves screen reader announcements for expanded/collapsed state.


function TutorCard() {
return (
<article className="flex gap-5 rounded-2xl bg-[#f5f5f5] p-4 sm:flex-row lg:flex-col">
<div className="relative h-[190px] min-w-[106px] shrink-0 overflow-hidden rounded-[10px] sm:w-[190px] lg:w-full">
<article className="flex gap-5 rounded-2xl bg-[#f5f5f5] p-4">
<div className="relative h-[190px] min-w-[106px] shrink-0 overflow-hidden rounded-[10px] sm:w-[190px]">
<Image
src="/figma-courses/tutor-maxwell.png"
alt="Mr. Maxwell"
Expand Down Expand Up @@ -157,7 +258,7 @@ function ReviewCard({ review }: { review: (typeof reviews)[number] }) {
<article className="flex flex-col gap-[22px] rounded-2xl border border-[#d9d9d9] p-5">
<p className="text-[15px] leading-normal text-ma-text">{review.text}</p>

<div className="flex gap-4 sm:flex-row sm:items-end lg:flex-col">
<div className="flex gap-4 sm:flex-row sm:items-end">
<div className="flex flex-1 items-end gap-2.5">
<Image
src={review.image}
Expand Down Expand Up @@ -215,16 +316,20 @@ function CourseInformationCard() {
</div>
))}

<Button
asChild
variant="outline"
className="mt-6 h-[53px] w-full gap-2.5 rounded-[60px] border-[#e5e7eb] bg-white px-5 py-4 text-base font-semibold text-ma-text hover:bg-[#f5f5f5]"
>
<Link href="/signup">
Enroll Now
<ArrowRight className="size-5" aria-hidden="true" />
</Link>
</Button>
<div className="group relative mt-6">
<Button asChild className="w-full rounded-[60px]" variant={"outline"}>
<Link
href="/signup"
className="flex h-[53px] w-full items-center justify-center gap-2.5 rounded-[60px] border border-[#e5e7eb] bg-white px-5 py-4 text-base font-semibold text-primary transition-colors duration-300 group-hover:border-transparent group-hover:bg-transparent"
>
Enroll Now
<ArrowRight
className="size-5 transition-transform duration-300 group-hover:rotate-[-30deg]"
aria-hidden="true"
/>
</Link>
</Button>
</div>
</div>
</aside>
)
Expand Down
Loading