feat: animations, transitions, and UI enhancements - #24
Conversation
… border by default
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR adds ChangesMarketing UI Interaction Updates
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 11
🧹 Nitpick comments (4)
src/features/marketing/components/faq.tsx (1)
68-94: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAdd ARIA attributes for accordion accessibility.
The trigger button and answer panel lack
aria-expanded,aria-controls/idlinkage, and the panel lacksrole="region". Screen readers can't determine the expanded/collapsed state or the relationship between trigger and content.♿ Proposed fix
<button type="button" onClick={() => toggle(i)} + aria-expanded={openIndex === i} + aria-controls={`faq-panel-${i}`} className="flex w-full items-start gap-4 text-left text-primary" > ... </button> <div + id={`faq-panel-${i}`} + role="region" className={`overflow-hidden transition-all duration-300 ${ openIndex === i ? "max-h-[500px] opacity-100" : "max-h-0 opacity-0" }`} >🤖 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/faq.tsx` around lines 68 - 94, The FAQ accordion in the faq component is missing accessibility wiring between the trigger and panel. Update the button in the toggle(i) block to expose the expanded state with aria-expanded and link it to the answer panel using aria-controls, then give the panel a stable id and role="region" so screen readers can associate the trigger with its content. Use the existing openIndex state and the faq item render in faq.tsx to wire these attributes consistently for each item.src/features/marketing/components/mission-sections.tsx (3)
87-91: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRedundant
sm:flexclass.
flexis already applied unconditionally, sosm:flexhas no effect.🤖 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/mission-sections.tsx` around lines 87 - 91, The div in MissionSections has a redundant responsive class because it already uses flex unconditionally, so remove the extra sm:flex from the hovered section container in mission-sections.tsx. Update the JSX for this block so the className only keeps the non-duplicative layout classes around the div with the onMouseEnter/onMouseLeave handlers.
7-9: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
hoveredstate distinguishes "first" fromnull, but no rendering branch uses that distinction.All three conditional styles (
gridTemplateColumnsat line 46, image width at line 73, image width at line 111) only checkhovered === "second";"first"andnullalways produce the same output. Tracking three states instead of a boolean (isSecondHovered) adds unnecessary complexity for no behavioral gain.Suggested simplification
- const [hovered, setHovered] = useState<"first" | "second" | null>(null) + const [isSecondHovered, setIsSecondHovered] = useState(false)Then replace
hovered === "second"checks withisSecondHovered, and theonMouseEnter/onMouseLeavehandlers withsetIsSecondHovered(true/false)accordingly.Also applies to: 46-46, 73-73, 111-111
🤖 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/mission-sections.tsx` around lines 7 - 9, Simplify MissionBridgeSection by replacing the unused three-state hovered union with a boolean state like isSecondHovered. Update the state declaration in MissionBridgeSection, then change all conditional branches that currently check hovered === "second" to use the boolean directly for gridTemplateColumns and both image width styles. Also replace the onMouseEnter/onMouseLeave handlers so they set true/false instead of "first"/"second", and remove any remaining unused distinction for "first" versus null.
70-84: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDuplicated width/height literals and wrapper structure between the two image containers.
Both panels repeat
width={292}/height={318}and an almost identical wrapper class string. A small helper (e.g.<ExpandableImage src=... expanded={...} />) would remove the duplication and make future width/height adjustments single-sourced.Also applies to: 108-122
🤖 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/mission-sections.tsx` around lines 70 - 84, The two image blocks in mission-sections.tsx duplicate the same wrapper logic and fixed dimensions, so extract the shared markup into a reusable component or helper such as ExpandableImage and pass src/alt/hover state into it. Centralize the repeated wrapper className and the width/height values there so both panels share one source of truth and future size changes only need to be made once.
🤖 Prompt for all review comments with 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.
Inline comments:
In `@src/features/marketing/components/course-detail-content-section.tsx`:
- Around line 218-230: The hover border gradient on the Link inside
CourseDetailContentSection uses an outdated Tailwind utility, so the gradient
won’t render in v4. Update the pseudo-element styling on the signup CTA to use
the Tailwind v4 linear gradient utility instead of before:bg-gradient-to-r,
keeping the rest of the Link/Button composition and class names in
course-detail-content-section.tsx unchanged.
In `@src/features/marketing/components/course-detail-hero-section.tsx`:
- Around line 80-91: The hover glow overlay in the course detail hero CTA is
using a deprecated Tailwind gradient class, so update the gradient background on
the Link’s overlay element inside course-detail-hero-section.tsx from the old
bg-gradient-to-r pattern to the Tailwind v4 bg-linear-to-r equivalent; keep the
same from/to color stops and leave the Button, Link, and ArrowRight structure
unchanged.
In `@src/features/marketing/components/footer.tsx`:
- Around line 81-84: The submit button in the footer form is scaling too
aggressively on hover and can overflow the pill container. Update the button
styles in footer.tsx so the hover effect in the submit button uses a more subtle
scale or a non-overlapping interaction, and make sure the surrounding form row
can accommodate the animation without encroaching on the email input. Locate
this in the footer form’s submit <button> markup and adjust the hover transform
accordingly.
- Around line 81-90: The footer form button overlay is using the old Tailwind
gradient utility and the hover scale is too aggressive for this compact layout.
Update the button in Footer’s submit markup to use the Tailwind v4
`bg-linear-to-r` utility on the gradient overlay, and reduce or remove the
`hover:scale-[1.5]` transform so the `Join` button doesn’t crowd the email field
in the form row.
In `@src/features/marketing/components/hero-section.tsx`:
- Around line 60-73: The CTA overlay in hero-section is using the old Tailwind
gradient utility, so update the Link’s gradient background on the floating
overlay to the v4 `bg-linear-to-r` equivalent. Use the existing hero-section
Link/overlay markup and replace the legacy gradient class while keeping the rest
of the CTA styling unchanged so the gradient renders correctly.
In `@src/features/marketing/components/mission-sections.tsx`:
- Around line 49-53: The hover-only expansion in the mission section panels is
hiding the second image from keyboard and touch users. Update the panel
container in mission-sections.tsx (the blocks using setHovered with
onMouseEnter/onMouseLeave, including the repeated panels) to support focus and
non-hover devices by adding onFocus/onBlur with a focusable target such as
tabIndex={0}, or by providing a hover-aware/touch fallback so the image is not
permanently collapsed when hover is unavailable.
- Around line 43-48: The hover layout in mission-sections is overriding the
responsive md grid with an unconditional inline gridTemplateColumns style, and
the width toggles are also applied at all breakpoints. Update the affected
section/component logic in mission-sections to drive the hover swap through
Tailwind classes or breakpoint-scoped conditional classes instead of inline
style, so the alternate column layout only activates at md and above. Make the
same responsive fix for the repeated panel width changes referenced in the same
component so they do not affect small screens.
In `@src/features/marketing/components/navbar.tsx`:
- Around line 49-64: The CTA overlay in this Navbar button still uses the
Tailwind v3 gradient utility, so update the overlay class in this Button/Link
CTA to the v4 equivalent and apply the same change to the mobile CTA below.
Locate the gradient overlay divs inside the navbar component and replace the old
gradient direction utility with bg-linear-to-r so both CTA backgrounds render
correctly.
- Around line 104-120: The mobile Consultation CTA in navbar should be aligned
with the Tailwind v4 button styles used elsewhere. Update the gradient utility
on the Link background in the mobile Button/Link block from the old directional
class to the Tailwind v4 linear variant, and keep the ArrowRight hover transform
consistent with the desktop CTA by using the negative 30deg rotation in the same
className.
In `@src/features/marketing/components/testimonials.tsx`:
- Line 73: The testimonials carousel container in testimonials.tsx is using
overflow-x-hidden, which prevents user-driven horizontal scrolling. Update the
scrollable wrapper in the testimonials component to keep horizontal scrolling
enabled (for example by restoring overflow-x-auto or overflow-x-scroll, with
hide-scrollbar if needed) while preserving the existing testimonial navigation
behavior in scrollReviews and the prev/next controls.
- Around line 29-36: The scrollReviews helper in testimonials.tsx is jumping
directly to the absolute start/end instead of moving one card at a time. Update
the scrollRef-based logic in scrollReviews so "next" and "previous" advance by a
single card/viewport increment relative to the current scroll position, rather
than using scrollWidth - clientWidth and 0. Keep the behavior anchored in
scrollRef.current and the scrollReviews direction argument, but compute the
target offset from the current scrollLeft so the carousel behaves as a true
stepwise previous/next control.
---
Nitpick comments:
In `@src/features/marketing/components/faq.tsx`:
- Around line 68-94: The FAQ accordion in the faq component is missing
accessibility wiring between the trigger and panel. Update the button in the
toggle(i) block to expose the expanded state with aria-expanded and link it to
the answer panel using aria-controls, then give the panel a stable id and
role="region" so screen readers can associate the trigger with its content. Use
the existing openIndex state and the faq item render in faq.tsx to wire these
attributes consistently for each item.
In `@src/features/marketing/components/mission-sections.tsx`:
- Around line 87-91: The div in MissionSections has a redundant responsive class
because it already uses flex unconditionally, so remove the extra sm:flex from
the hovered section container in mission-sections.tsx. Update the JSX for this
block so the className only keeps the non-duplicative layout classes around the
div with the onMouseEnter/onMouseLeave handlers.
- Around line 7-9: Simplify MissionBridgeSection by replacing the unused
three-state hovered union with a boolean state like isSecondHovered. Update the
state declaration in MissionBridgeSection, then change all conditional branches
that currently check hovered === "second" to use the boolean directly for
gridTemplateColumns and both image width styles. Also replace the
onMouseEnter/onMouseLeave handlers so they set true/false instead of
"first"/"second", and remove any remaining unused distinction for "first" versus
null.
- Around line 70-84: The two image blocks in mission-sections.tsx duplicate the
same wrapper logic and fixed dimensions, so extract the shared markup into a
reusable component or helper such as ExpandableImage and pass src/alt/hover
state into it. Centralize the repeated wrapper className and the width/height
values there so both panels share one source of truth and future size changes
only need to be made once.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: aed05024-6c9d-40bb-9198-0984ba37aa11
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (11)
package.jsonsrc/features/marketing/components/course-detail-content-section.tsxsrc/features/marketing/components/course-detail-hero-section.tsxsrc/features/marketing/components/courses-hero-section.tsxsrc/features/marketing/components/cta-section.tsxsrc/features/marketing/components/faq.tsxsrc/features/marketing/components/footer.tsxsrc/features/marketing/components/hero-section.tsxsrc/features/marketing/components/mission-sections.tsxsrc/features/marketing/components/navbar.tsxsrc/features/marketing/components/testimonials.tsx
| <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]" | ||
| className="group relative mt-6 bg-transparent" | ||
| > | ||
| <Link href="/signup"> | ||
| <Link | ||
| href="/signup" | ||
| className="relative isolate 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-ma-text transition-colors duration-300 before:absolute before:-inset-[2px] before:rounded-[60px] before:bg-gradient-to-r before:from-ma-glow-blue before:to-ma-glow-violet before:z-[-1] before:opacity-0 before:transition-opacity before:duration-300 group-hover:border-transparent group-hover:before:opacity-100" | ||
| > | ||
| Enroll Now | ||
| <ArrowRight className="size-5" aria-hidden="true" /> | ||
| <ArrowRight className="size-5 transition-transform duration-300 group-hover:rotate-[-30deg]" aria-hidden="true" /> | ||
| </Link> | ||
| </Button> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== package files ==\n'
git ls-files 'package.json' 'pnpm-lock.yaml' 'yarn.lock' 'package-lock.json' 'src/**/package.json' | sed -n '1,120p'
printf '\n== tailwind references ==\n'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' 'tailwindcss|bg-gradient-to-r|bg-linear-to-r' .
printf '\n== file under review context ==\n'
sed -n '210,235p' src/features/marketing/components/course-detail-content-section.tsxRepository: Smartlify07/Modern-Advocates
Length of output: 6980
🌐 Web query:
Tailwind CSS v4 bg-gradient-to-r removed alias bg-linear-to-r documentation
💡 Result:
In Tailwind CSS v4, the former bg-gradient-to-* utilities have been renamed to bg-linear-to-* [1][2][3]. This was a breaking change introduced to align class names with the native CSS linear-gradient function and to make room for new gradient primitives, specifically radial and conic gradients [1][2][3]. There is no alias or legacy support for the old bg-gradient-to-* class names in v4; they have been completely replaced by the new bg-linear-* syntax [2][4]. Key points regarding this change: - Renaming: Classes like bg-gradient-to-r have become bg-linear-to-r [2][4]. - Expanded Functionality: The new naming structure accommodates additional types, such as bg-radial and bg-conic [2][3]. - Gradient Stops: The existing color stop utilities (from-, via-, to-*) remain compatible and function identically with the new linear gradient classes [2][4]. - Migration: Official documentation provides guidance on updating these classes, and automated migration tools are available to help transition existing projects from the v3 syntax to the v4 syntax [1][5]. Because these changes involve class names, they may need to be manually updated in dynamic string concatenations that automated tools might miss [2].
Citations:
- 1: Template migrations: Migrate
bg-gradient-*utilities tobg-linear-*tailwindlabs/tailwindcss#14537 - 2: https://richdynamix.com/articles/tailwind-v4-gradient-utilities-bg-linear-radial-conic
- 3: https://tailwindcss.com/blog/tailwindcss-v4
- 4: https://capytoolkit.com/tools/design/gradient-builder/tailwind-v4-gradients/
- 5: https://tailwindcss.com/docs/upgrade-guide
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import json, os, re
for p in ['package.json','pnpm-lock.yaml','yarn.lock','package-lock.json']:
if os.path.exists(p):
print(f'== {p} ==')
if p.endswith('.json'):
data=json.load(open(p))
for k in ['dependencies','devDependencies','peerDependencies']:
if k in data and 'tailwindcss' in data[k]:
print(k, data[k]['tailwindcss'])
else:
# show tailwind version mentions around first occurrences
with open(p, 'r', encoding='utf-8', errors='ignore') as f:
txt=f.read()
for m in re.finditer(r'tailwindcss@[^:\n ]+|tailwindcss[^@\n ]*@[^:\n ]+', txt):
print(m.group(0))
break
PYRepository: Smartlify07/Modern-Advocates
Length of output: 249
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Minimal, read-only checks for Tailwind version and relevant utility usage.
if [ -f package.json ]; then
echo '== package.json =='
cat package.json | python3 - <<'PY'
import json, sys
data=json.load(sys.stdin)
for k in ['dependencies','devDependencies','peerDependencies']:
if k in data and 'tailwindcss' in data[k]:
print(k, data[k]['tailwindcss'])
PY
fi
echo '== matches =='
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' 'bg-gradient-to-r|bg-linear-to-r|tailwindcss' .Repository: Smartlify07/Modern-Advocates
Length of output: 906
🌐 Web query:
Tailwind CSS v4 bg-gradient-to-r alias removed bg-linear-to-r documentation "legacy class aliases"
💡 Result:
In Tailwind CSS v4, the bg-gradient-* class aliases used in v3 were removed and replaced with the bg-linear-* naming convention [1][2][3]. This change was implemented to better align Tailwind’s utility naming with native CSS functions (such as linear-gradient()) and to accommodate new gradient types, specifically bg-radial and bg-conic [2][3]. Key points regarding this change: - Renaming: Classes such as bg-gradient-to-r have been replaced by bg-linear-to-r [1][4]. - Migration: Tailwind provides an official upgrade tool, @tailwindcss/upgrade, which automatically updates legacy v3 class names (including gradient utilities) to their v4 equivalents during the migration process [1][5][6]. - Reasoning: Beyond simple renaming, v4 introduces expanded gradient capabilities, including support for arbitrary linear gradient angles (e.g., bg-linear-[125deg]) and gradient interpolation modifiers (e.g., /srgb, /oklch), which are conceptually clearer under the bg-linear-* namespace [7][2][3]. Documentation for these utilities can be found in the official Tailwind CSS background-image documentation, which lists the modern bg-linear-* utilities [8].
Citations:
- 1: Template migrations: Migrate
bg-gradient-*utilities tobg-linear-*tailwindlabs/tailwindcss#14537 - 2: https://tailwindcss.com/blog/tailwindcss-v4
- 3: https://richdynamix.com/articles/tailwind-v4-gradient-utilities-bg-linear-radial-conic
- 4: https://designrevision.com/blog/tailwind-4-migration
- 5: Ensure
@tailwindcss/upgraderuns on Tailwind CSS v4 projects and is idempotent tailwindlabs/tailwindcss#17717 - 6: https://blog.elunari.uk/tailwind-css-v4-migration-guide
- 7: tailwindlabs/tailwindcss@7b63886
- 8: https://tailwindcss.com/docs/background-image
🌐 Web query:
site:tailwindcss.com bg-gradient-to-r bg-linear-to-r Tailwind v4 legacy class aliases removed
💡 Result:
In Tailwind CSS v4, the class naming convention for gradients has been updated. The previous bg-gradient-* utility classes have been renamed to bg-linear-* [1][2]. Specifically, the bg-gradient-to-r class from Tailwind v3 has been replaced by bg-linear-to-r in v4 [3][1]. While v4 introduces these updated names to support expanded gradient functionality—such as linear gradient angles (e.g., bg-linear-45) and interpolation modifiers (e.g., bg-linear-to-r/oklch)—it does not necessarily imply a blanket removal of all legacy aliases in the framework's core; however, for gradients specifically, the documentation emphasizes the use of the new bg-linear-* naming convention [3][1]. You should update your codebase to use the bg-linear-* variants to benefit from the new API features and ensure consistency with v4 [1][2].
Citations:
- 1: https://tailwindcss.com/blog/tailwindcss-v4
- 2: https://v3.tailwindcss.com/docs/v4-beta
- 3: https://tailwindcss.com/docs/background-image
Swap before:bg-gradient-to-r to before:bg-linear-to-r Tailwind v4 uses the bg-linear-* gradient utilities, so this hover border gradient won’t render as written.
🤖 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 218 - 230, The hover border gradient on the Link inside
CourseDetailContentSection uses an outdated Tailwind utility, so the gradient
won’t render in v4. Update the pseudo-element styling on the signup CTA to use
the Tailwind v4 linear gradient utility instead of before:bg-gradient-to-r,
keeping the rest of the Link/Button composition and class names in
course-detail-content-section.tsx unchanged.
| <Button | ||
| asChild | ||
| className="mt-3 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-3 overflow-hidden rounded-[60px]" | ||
| > | ||
| <Link href="/signup"> | ||
| Enroll Now | ||
| <ArrowRight className="size-5" aria-hidden="true" /> | ||
| <Link href="/signup" className="flex h-[53px] w-full items-center justify-center gap-2.5 rounded-[60px] bg-ma-text px-5 py-4 text-base font-semibold text-white"> | ||
| <span className="relative z-10 inline-flex items-center gap-2.5"> | ||
| Enroll Now | ||
| <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" /> | ||
| </Link> | ||
| </Button> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== package manifests ==\n'
git ls-files 'package.json' 'pnpm-lock.yaml' 'yarn.lock' 'package-lock.json' 'src/**/package.json' | sed 's#^`#-` #'
printf '\n== tailwind references ==\n'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' 'tailwindcss|bg-gradient-to-|bg-linear-to-' .
printf '\n== target file excerpt ==\n'
sed -n '70,100p' src/features/marketing/components/course-detail-hero-section.tsxRepository: Smartlify07/Modern-Advocates
Length of output: 8023
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== package.json ==\n'
sed -n '1,220p' package.json
printf '\n== lockfile hits ==\n'
rg -n 'tailwindcss@|tailwindcss' pnpm-lock.yaml package-lock.json yarn.lock 2>/dev/null || trueRepository: Smartlify07/Modern-Advocates
Length of output: 5520
🌐 Web query:
Tailwind CSS v4 gradient utilities bg-gradient-to-r bg-linear-to-r documentation
💡 Result:
In Tailwind CSS v4, the gradient system has been overhauled to align with native CSS syntax, resulting in a breaking change where the former bg-gradient-to-* utilities have been replaced by bg-linear-to-* [1][2][3]. Key changes and usage in v4: 1. Renamed Utilities: The bg-gradient-to-* prefix used in v3 is removed [3]. You must now use bg-linear-to-* for linear gradients (e.g., bg-linear-to-r for a left-to-right gradient) [4][1][2]. 2. Directional and Angle Support: - Predefined cardinal and diagonal directions remain available (e.g., bg-linear-to-t, bg-linear-to-br, bg-linear-to-l) [4][5]. - You can now specify explicit angles directly using the bg-linear-* utility (e.g., bg-linear-45 for a 45-degree angle) [1][5][2]. - Arbitrary angle values are supported via square bracket syntax (e.g., bg-linear-[125deg]) [6][7]. 3. Gradient Stops: The color stop utilities (from-*, via-*, and to-*) function identically to v3 [1][3]. You combine them with the base gradient utility to define the colors and their positions (e.g., bg-linear-to-r from-indigo-500 via-purple-500 to-pink-500) [4][7][5]. 4. Interpolation Modes: Tailwind v4 defaults to oklab color interpolation, which provides smoother, more vibrant gradients compared to traditional sRGB [1][7][2]. You can override this using interpolation modifiers on the utility class, such as bg-linear-to-r/srgb, bg-linear-to-r/oklch, or bg-linear-to-r/hsl [4][7][2]. 5. Expanded Gradient Types: In addition to linear gradients, v4 introduces bg-radial and bg-conic utilities to support radial and conic gradients, respectively [1][2][3]. To migrate from v3, you can perform a search-and-replace for bg-gradient-to- with bg-linear-to- across your project [3].
Citations:
- 1: https://richdynamix.com/articles/tailwind-v4-gradient-utilities-bg-linear-radial-conic
- 2: https://tailwindcss.com/blog/tailwindcss-v4
- 3: https://capytoolkit.com/tools/design/gradient-builder/tailwind-v4-gradients/
- 4: https://tailwindcss.com/docs/background-image
- 5: https://windybase.com/blog/how-to-use-gradients-in-tailwind-css
- 6: tailwindlabs/tailwindcss@7b63886
- 7: https://stevekinney.com/courses/tailwind/gradients
Use bg-linear-to-r for this gradient overlay. Tailwind v4 no longer emits bg-gradient-to-*, so this hover glow won’t render with bg-gradient-to-r here.
🛠️ Proposed fix
- <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" />
+ <div className="pointer-events-none absolute inset-0 rounded-[60px] bg-linear-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />📝 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.
| <Button | |
| asChild | |
| className="mt-3 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-3 overflow-hidden rounded-[60px]" | |
| > | |
| <Link href="/signup"> | |
| Enroll Now | |
| <ArrowRight className="size-5" aria-hidden="true" /> | |
| <Link href="/signup" className="flex h-[53px] w-full items-center justify-center gap-2.5 rounded-[60px] bg-ma-text px-5 py-4 text-base font-semibold text-white"> | |
| <span className="relative z-10 inline-flex items-center gap-2.5"> | |
| Enroll Now | |
| <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" /> | |
| </Link> | |
| </Button> | |
| <Button | |
| asChild | |
| className="group relative mt-3 overflow-hidden rounded-[60px]" | |
| > | |
| <Link href="/signup" className="flex h-[53px] w-full items-center justify-center gap-2.5 rounded-[60px] bg-ma-text px-5 py-4 text-base font-semibold text-white"> | |
| <span className="relative z-10 inline-flex items-center gap-2.5"> | |
| Enroll Now | |
| <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-linear-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" /> | |
| </Link> | |
| </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/marketing/components/course-detail-hero-section.tsx` around
lines 80 - 91, The hover glow overlay in the course detail hero CTA is using a
deprecated Tailwind gradient class, so update the gradient background on the
Link’s overlay element inside course-detail-hero-section.tsx from the old
bg-gradient-to-r pattern to the Tailwind v4 bg-linear-to-r equivalent; keep the
same from/to color stops and leave the Button, Link, and ArrowRight structure
unchanged.
| <button | ||
| type="submit" | ||
| className="inline-flex items-center justify-center gap-2 rounded-[60px] bg-ma-text px-[15px] py-3 text-[12.31px] font-semibold text-white transition-colors hover:bg-ma-text/90" | ||
| className="group relative inline-flex items-center justify-center gap-2 overflow-hidden rounded-[60px] bg-ma-text px-[15px] py-3 text-[12.31px] font-semibold text-white transition-transform duration-300 hover:scale-[1.5]" | ||
| > | ||
| Join | ||
| <ArrowRight className="size-[15px]" aria-hidden="true" /> | ||
| <span className="relative z-10 inline-flex items-center gap-2"> | ||
| Join | ||
| <ArrowRight className="size-[15px] 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> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== footer.tsx excerpt ==\n'
sed -n '1,180p' src/features/marketing/components/footer.tsx
printf '\n== Tailwind references ==\n'
rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' 'tailwind|bg-gradient-to-r|bg-linear-to-r|`@tailwind`|tailwindcss' .
printf '\n== package manifests ==\n'
for f in package.json pnpm-lock.yaml yarn.lock package-lock.json; do
if [ -f "$f" ]; then
printf '\n-- %s --\n' "$f"
sed -n '1,220p' "$f"
fi
doneRepository: Smartlify07/Modern-Advocates
Length of output: 21473
🌐 Web query:
Tailwind CSS v4 gradient direction utility bg-gradient-to-r vs bg-linear-to-r official docs
💡 Result:
In Tailwind CSS v4, the bg-gradient-to-* utility family has been renamed to bg-linear-to-* [1][2]. This change was implemented to better align the utility names with the underlying native CSS linear-gradient() function and to support a broader suite of gradient types, including the new bg-radial and bg-conic utilities [1][3]. Key points regarding the transition: - Replacement: bg-linear-to-r is the canonical v4 equivalent of the legacy v3 bg-gradient-to-r [1][2]. The bg-gradient-to-* classes no longer exist in v4 [1][4]. - Functionality: Both utilities produce identical CSS output [1]. The color stop utilities (from-*, via-*, and to-*) remain unchanged and function exactly as they did in v3 [1][4]. - Enhanced Features: Tailwind v4 introduces new gradient capabilities, such as arbitrary angles (e.g., bg-linear-45) [1][3] and color interpolation modifiers (e.g., bg-linear-to-r/oklch or bg-linear-to-r/srgb) [5][3], which work seamlessly with the bg-linear-* syntax. If you are migrating a codebase, the official Tailwind CSS upgrade tool automatically handles the renaming of bg-gradient-to-* to bg-linear-to-* for statically parseable class strings [1][2].
Citations:
- 1: https://richdynamix.com/articles/tailwind-v4-gradient-utilities-bg-linear-radial-conic
- 2: https://www.digitalapplied.com/blog/tailwind-css-v4-2026-migration-best-practices
- 3: https://tailwindcss.com/blog/tailwindcss-v4
- 4: https://capytoolkit.com/tools/design/gradient-builder/tailwind-v4-gradients/
- 5: https://tailwindcss.com/docs/background-image
🏁 Script executed:
rg -n 'hover:scale-\[1\.5\]' srcRepository: Smartlify07/Modern-Advocates
Length of output: 452
Use bg-linear-to-r for this overlay. bg-gradient-to-r is the Tailwind v4 rename, so the hover gradient won’t render here. The hover:scale-[1.5] button also crowds the email field in this tight form row.
🤖 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/footer.tsx` around lines 81 - 90, The
footer form button overlay is using the old Tailwind gradient utility and the
hover scale is too aggressive for this compact layout. Update the button in
Footer’s submit markup to use the Tailwind v4 `bg-linear-to-r` utility on the
gradient overlay, and reduce or remove the `hover:scale-[1.5]` transform so the
`Join` button doesn’t crowd the email field in the form row.
| <div className="mt-10 flex items-center gap-5"> | ||
| <Link | ||
| href="/contact" | ||
| className="inline-flex items-center justify-center gap-1.5 rounded-[60px] bg-ma-text px-5 py-4 text-xs font-semibold text-nowrap text-white transition-colors hover:bg-ma-text/90 sm:gap-2.5 sm:text-base" | ||
| className="group relative inline-flex items-center justify-center overflow-hidden rounded-[60px] bg-ma-text px-5 py-4 sm:gap-2.5 sm:text-base" | ||
| > | ||
| Book consultation | ||
| <ArrowRight className="size-5" aria-hidden="true" /> | ||
| <span className="relative z-10 inline-flex items-center justify-center gap-1.5 text-xs font-semibold text-nowrap text-white sm:gap-2.5 sm:text-base"> | ||
| Book consultation | ||
| <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" /> | ||
| </Link> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use bg-linear-to-r here. Tailwind v4 renamed the legacy bg-gradient-to-r utility, so this CTA overlay won't render as intended until it's updated.
🛠️ Proposed fix
- <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" />
+ <div className="pointer-events-none absolute inset-0 rounded-[60px] bg-linear-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />📝 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.
| <div className="mt-10 flex items-center gap-5"> | |
| <Link | |
| href="/contact" | |
| className="inline-flex items-center justify-center gap-1.5 rounded-[60px] bg-ma-text px-5 py-4 text-xs font-semibold text-nowrap text-white transition-colors hover:bg-ma-text/90 sm:gap-2.5 sm:text-base" | |
| className="group relative inline-flex items-center justify-center overflow-hidden rounded-[60px] bg-ma-text px-5 py-4 sm:gap-2.5 sm:text-base" | |
| > | |
| Book consultation | |
| <ArrowRight className="size-5" aria-hidden="true" /> | |
| <span className="relative z-10 inline-flex items-center justify-center gap-1.5 text-xs font-semibold text-nowrap text-white sm:gap-2.5 sm:text-base"> | |
| Book consultation | |
| <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" /> | |
| </Link> | |
| <div className="mt-10 flex items-center gap-5"> | |
| <Link | |
| href="/contact" | |
| className="group relative inline-flex items-center justify-center overflow-hidden rounded-[60px] bg-ma-text px-5 py-4 sm:gap-2.5 sm:text-base" | |
| > | |
| <span className="relative z-10 inline-flex items-center justify-center gap-1.5 text-xs font-semibold text-nowrap text-white sm:gap-2.5 sm:text-base"> | |
| Book consultation | |
| <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-linear-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" /> | |
| </Link> |
🤖 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/hero-section.tsx` around lines 60 - 73, The
CTA overlay in hero-section is using the old Tailwind gradient utility, so
update the Link’s gradient background on the floating overlay to the v4
`bg-linear-to-r` equivalent. Use the existing hero-section Link/overlay markup
and replace the legacy gradient class while keeping the rest of the CTA styling
unchanged so the gradient renders correctly.
| <div | ||
| onMouseEnter={() => setHovered("first")} | ||
| onMouseLeave={() => setHovered(null)} | ||
| className="flex flex-col gap-5 rounded-2xl bg-white p-5 sm:flex-row" | ||
| > |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Second panel's image is gated entirely behind :hover, with no keyboard or touch fallback.
onMouseEnter/onMouseLeave are the only triggers for expanding the second image; there's no onFocus/onBlur/tabIndex equivalent, and devices without reliable hover (touch/tablet) will likely never reveal this image since it defaults to w-0. This permanently hides content for a meaningful chunk of users with no fallback path.
Consider:
- Adding
onFocus/onBluralongside the mouse handlers and making the panel focusable (tabIndex={0}) for keyboard parity. - Or using
@media (hover: hover)/ a touch-aware fallback so the image isn't unconditionally collapsed on devices that can't hover.
Also applies to: 87-91, 108-122
🤖 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/mission-sections.tsx` around lines 49 - 53,
The hover-only expansion in the mission section panels is hiding the second
image from keyboard and touch users. Update the panel container in
mission-sections.tsx (the blocks using setHovered with
onMouseEnter/onMouseLeave, including the repeated panels) to support focus and
non-hover devices by adding onFocus/onBlur with a focusable target such as
tabIndex={0}, or by providing a hover-aware/touch fallback so the image is not
permanently collapsed when hover is unavailable.
| <Button | ||
| asChild | ||
| className="hidden h-13 w-[157px] gap-[6px] rounded-[60px] px-5 py-4 md:inline-flex" | ||
| className="group relative hidden overflow-hidden rounded-[60px] md:inline-flex" | ||
| > | ||
| <Link href="/contact"> | ||
| Consultation | ||
| <ArrowRight className="size-3.5" aria-hidden="true" /> | ||
| <Link | ||
| href="/contact" | ||
| className="flex h-13 w-[157px] items-center justify-center gap-[6px] rounded-[60px] px-5 py-4 text-base font-semibold" | ||
| > | ||
| <span className="relative z-10">Consultation</span> | ||
| <ArrowRight | ||
| className="relative z-10 size-5 transition-transform duration-300 group-hover:rotate-[-30deg]" | ||
| aria-hidden="true" | ||
| /> | ||
| <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" /> | ||
| </Link> | ||
| </Button> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use bg-linear-to-r for both CTA overlays
bg-gradient-to-r is a Tailwind v3 class; in v4 this should be bg-linear-to-r, otherwise the gradient overlay won't render. The same fix applies to the mobile CTA below.
🤖 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/navbar.tsx` around lines 49 - 64, The CTA
overlay in this Navbar button still uses the Tailwind v3 gradient utility, so
update the overlay class in this Button/Link CTA to the v4 equivalent and apply
the same change to the mobile CTA below. Locate the gradient overlay divs inside
the navbar component and replace the old gradient direction utility with
bg-linear-to-r so both CTA backgrounds render correctly.
| <Button | ||
| asChild | ||
| className="mt-2 h-13 w-full gap-[6px] rounded-[60px] px-5 py-4" | ||
| className="group relative mt-2 overflow-hidden rounded-[60px]" | ||
| > | ||
| <Link href="/contact" onClick={() => setMobileOpen(false)}> | ||
| Consultation | ||
| <ArrowRight className="size-3.5" aria-hidden="true" /> | ||
| <Link | ||
| href="/contact" | ||
| onClick={() => setMobileOpen(false)} | ||
| className="flex h-13 w-full items-center justify-center gap-[6px] rounded-[60px] px-5 py-4" | ||
| > | ||
| <span className="relative z-10">Consultation</span> | ||
| <ArrowRight | ||
| className="relative z-10 size-3.5 transition-transform duration-300 group-hover:rotate-[30deg]" | ||
| aria-hidden="true" | ||
| /> | ||
| <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" /> | ||
| </Link> | ||
| </Button> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== navbar snippet ==\n'
sed -n '45,130p' src/features/marketing/components/navbar.tsx
printf '\n== gradient utility search ==\n'
rg -n "bg-(gradient-to-r|linear-to-r)" src/features/marketing -g '*.tsx' -g '*.ts'
printf '\n== ArrowRight rotation search ==\n'
rg -n "rotate-\[-?30deg\]" src/features/marketing -g '*.tsx' -g '*.ts'Repository: Smartlify07/Modern-Advocates
Length of output: 6440
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== package.json tailwind deps ==\n'
sed -n '1,220p' package.json
printf '\n== tailwind-related files ==\n'
fd -a 'tailwind*' .
printf '\n== tailwind config contents (if any) ==\n'
for f in $(fd -a 'tailwind.*(js|cjs|mjs|ts|config.*)' .); do
echo "--- $f ---"
sed -n '1,220p' "$f"
doneRepository: Smartlify07/Modern-Advocates
Length of output: 2351
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import json, pathlib
p = pathlib.Path('package.json')
data = json.loads(p.read_text())
for key in ('dependencies','devDependencies','peerDependencies','optionalDependencies'):
deps = data.get(key, {})
if any('tailwind' in k.lower() for k in deps):
print(f'[{key}]')
for k,v in deps.items():
if 'tailwind' in k.lower():
print(f'{k}: {v}')
PYRepository: Smartlify07/Modern-Advocates
Length of output: 299
🌐 Web query:
Tailwind CSS v4 directional gradient utility bg-gradient-to-r bg-linear-to-r docs migration
💡 Result:
In Tailwind CSS v4, the directional gradient utilities have been renamed from bg-gradient-to-* to bg-linear-to-* to align with the underlying CSS linear-gradient() function and to accommodate new gradient types like bg-radial and bg-conic [1][2][3]. Migration details: - Renaming: All existing v3 bg-gradient-to-* classes must be updated to bg-linear-to-* (e.g., bg-gradient-to-r becomes bg-linear-to-r) [2][4]. - Automation: The official Tailwind CSS upgrade tool (npx @tailwindcss/upgrade``) automatically detects and rewrites these class names in your project files [1][2][3][5]. - Color Stops: The color stop utilities (from-*, `via-`, `to-`) and their modifiers (positions, opacity) remain unchanged and function exactly as they did in v3 [2][4][6]. - New Features: v4 introduces expanded capabilities for linear gradients, including support for arbitrary angles (e.g., `bg-linear-45`), new color interpolation modifiers (e.g., `/srgb`, `/oklch`), and support for radial and conic gradients [2][3][7][8]. It is recommended to run the automated upgrade command to handle these changes, as manual updates may miss dynamic or concatenated class strings [2][5].
Citations:
- 1: Template migrations: Migrate
bg-gradient-*utilities tobg-linear-*tailwindlabs/tailwindcss#14537 - 2: https://richdynamix.com/articles/tailwind-v4-gradient-utilities-bg-linear-radial-conic
- 3: https://tailwindcss.com/blog/tailwindcss-v4
- 4: https://capytoolkit.com/tools/design/gradient-builder/tailwind-v4-gradients/
- 5: https://blog.elunari.uk/tailwind-css-v4-migration-guide
- 6: https://stackoverflow.com/questions/71120394/is-there-a-way-to-adjust-the-angle-of-the-linear-gradient
- 7: https://designrevision.com/blog/tailwind-4-migration
- 8: https://raw.githubusercontent.com/tailwindlabs/tailwindcss.com/main/src/docs/background-image.mdx
Update the mobile Consultation CTA to match Tailwind v4 and the other CTAs
bg-gradient-to-r should be bg-linear-to-r here, and the arrow hover rotation should stay -30deg to match the desktop CTA and the rest of the marketing buttons.
🤖 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/navbar.tsx` around lines 104 - 120, The
mobile Consultation CTA in navbar should be aligned with the Tailwind v4 button
styles used elsewhere. Update the gradient utility on the Link background in the
mobile Button/Link block from the old directional class to the Tailwind v4
linear variant, and keep the ArrowRight hover transform consistent with the
desktop CTA by using the negative 30deg rotation in the same className.
| function scrollReviews(direction: "previous" | "next") { | ||
| scrollRef.current?.scrollBy({ | ||
| left: direction === "next" ? 360 : -360, | ||
| const el = scrollRef.current | ||
| if (!el) return | ||
| el.scrollTo({ | ||
| left: direction === "next" ? el.scrollWidth - el.clientWidth : 0, | ||
| behavior: "smooth", | ||
| }) | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
scrollReviews no longer steps incrementally — it jumps straight to start/end.
next always scrolls to scrollWidth - clientWidth (the absolute end) and previous always scrolls to 0 (the absolute start), regardless of current scroll position. With more than two cards visible, clicking "next" repeatedly does nothing after the first click (already at the end), and there's no way to advance through cards one at a time — the buttons effectively become a binary "jump to start/jump to end" toggle rather than a carousel previous/next control.
🔧 Possible fix: step by one card width
function scrollReviews(direction: "previous" | "next") {
const el = scrollRef.current
if (!el) return
+ const cardWidth = 330 + 30 // card width + gap
el.scrollTo({
- left: direction === "next" ? el.scrollWidth - el.clientWidth : 0,
+ left:
+ direction === "next"
+ ? Math.min(el.scrollLeft + cardWidth, el.scrollWidth - el.clientWidth)
+ : Math.max(el.scrollLeft - cardWidth, 0),
behavior: "smooth",
})
}📝 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.
| function scrollReviews(direction: "previous" | "next") { | |
| scrollRef.current?.scrollBy({ | |
| left: direction === "next" ? 360 : -360, | |
| const el = scrollRef.current | |
| if (!el) return | |
| el.scrollTo({ | |
| left: direction === "next" ? el.scrollWidth - el.clientWidth : 0, | |
| behavior: "smooth", | |
| }) | |
| } | |
| function scrollReviews(direction: "previous" | "next") { | |
| const el = scrollRef.current | |
| if (!el) return | |
| const cardWidth = 330 + 30 // card width + gap | |
| el.scrollTo({ | |
| left: | |
| direction === "next" | |
| ? Math.min(el.scrollLeft + cardWidth, el.scrollWidth - el.clientWidth) | |
| : Math.max(el.scrollLeft - cardWidth, 0), | |
| behavior: "smooth", | |
| }) | |
| } |
🤖 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/testimonials.tsx` around lines 29 - 36, The
scrollReviews helper in testimonials.tsx is jumping directly to the absolute
start/end instead of moving one card at a time. Update the scrollRef-based logic
in scrollReviews so "next" and "previous" advance by a single card/viewport
increment relative to the current scroll position, rather than using scrollWidth
- clientWidth and 0. Keep the behavior anchored in scrollRef.current and the
scrollReviews direction argument, but compute the target offset from the current
scrollLeft so the carousel behaves as a true stepwise previous/next control.
| <div | ||
| ref={scrollRef} | ||
| className="hide-scrollbar mt-[86px] flex gap-[30px] overflow-x-auto scroll-smooth px-4 pb-2 xl:px-25 2xl:pl-50" | ||
| className="relative mt-[86px] flex gap-[30px] overflow-x-hidden px-4 pb-2 xl:px-25 2xl:pl-50" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
overflow-x-hidden disables user-driven scrolling (touch/trackpad/scrollbar drag).
Switching from overflow-x-auto to overflow-x-hidden means the element can still be scrolled programmatically via scrollTo, but end users can no longer swipe/drag or use a trackpad/scrollbar to browse testimonials — they're now fully dependent on the prev/next buttons. Combined with the binary start/end jump in scrollReviews above, this significantly limits how users can browse the testimonials carousel, especially on touch devices.
hide-scrollbar (referenced in src/app/globals.css) was removed since overflow-x-hidden already suppresses the scrollbar, so that part is fine — but consider keeping overflow-x-auto hide-scrollbar (or overflow-x-scroll) if touch/swipe scrolling should remain available.
🤖 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/testimonials.tsx` at line 73, The
testimonials carousel container in testimonials.tsx is using overflow-x-hidden,
which prevents user-driven horizontal scrolling. Update the scrollable wrapper
in the testimonials component to keep horizontal scrolling enabled (for example
by restoring overflow-x-auto or overflow-x-scroll, with hide-scrollbar if
needed) while preserving the existing testimonial navigation behavior in
scrollReviews and the prev/next controls.
…contact/donation buttons, and polish
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
src/features/marketing/components/course-detail-content-section.tsx (3)
191-206: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffFixed
max-h-[500px]is a brittle animation approach.If topic list content ever exceeds 500px it will clip abruptly, and short content still animates over the full fixed duration disproportionately. Since
motionwas just added to this PR's dependencies for the hero animation, using it here (e.g.AnimatePresence/motion.divwithheight: auto) would be more consistent and robust than the max-height hack.🤖 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 191 - 206, The topics panel in course-detail-content-section.tsx still uses a brittle fixed max-height transition, which can clip longer content and animate short content poorly. Update the open/close behavior in the course detail section to use motion-based expansion instead of the max-h-[500px] hack, ideally with AnimatePresence and a motion.div that animates height to auto. Keep the existing open state and topics rendering logic, but replace the overflow/transition class approach with the new motion animation for the topics container.
168-194: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider
cn()for conditional classes instead of template-literal concatenation.Elsewhere in the codebase (e.g.,
Button) conditional class composition goes throughcn(); using raw template literals here is inconsistent and harder to maintain/merge safely.🤖 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 168 - 194, The conditional class composition in the course detail accordion should use the shared cn() helper instead of inline template-literal concatenation. Update the wrapper, ChevronDown, and open-state container class handling in the component that renders the title/button toggle so the conditional styles are merged through cn(), matching the pattern used elsewhere like Button and keeping class composition consistent and safer to extend.
319-332: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffEnroll button:
variant="outline"is fully overridden by the childLink's own classes — verify merge behavior.
Buttonrenders via RadixSlot.RootwhenasChildis set, mergingbuttonVariants({variant: "outline", ...})output into theLink. TheLinkhere re-declares border/background/padding/height directly, which likely wins or conflicts with the outline variant depending oncn/tailwind-mergeclass-merge order — making thevariant="outline"prop effectively dead weight, or worse, an unpredictable visual result depending on class merge order.Simplify by dropping the redundant
Buttonwrapper/variant if theLinkalready fully defines the visual style, or move all styling into theButton'sclassNameand letLinkstay unstyled.🤖 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 319 - 332, The enroll CTA styling is duplicating and conflicting between Button’s outline variant and the nested Link classes, so the variant on Button is effectively redundant. Update the CourseDetailContentSection enroll block to either remove the Button/asChild wrapper and keep the Link fully styled, or move the full styling into Button and leave Link unstyled; use Button, ButtonVariants, and the Link inside this enroll action as the key points to adjust.
🤖 Prompt for all review comments with 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.
Inline comments:
In `@src/features/marketing/components/course-detail-content-section.tsx`:
- Around line 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.
In `@src/features/marketing/components/donation-support-section.tsx`:
- Line 131: The overlay in donation-support-section still uses the removed
Tailwind v3 gradient utility, so update the gradient class on the highlighted
absolute div to the Tailwind v4 equivalent. Keep the existing styling and
behavior intact, but replace bg-gradient-to-r with bg-linear-to-r so the hover
overlay renders correctly in the component.
---
Nitpick comments:
In `@src/features/marketing/components/course-detail-content-section.tsx`:
- Around line 191-206: The topics panel in course-detail-content-section.tsx
still uses a brittle fixed max-height transition, which can clip longer content
and animate short content poorly. Update the open/close behavior in the course
detail section to use motion-based expansion instead of the max-h-[500px] hack,
ideally with AnimatePresence and a motion.div that animates height to auto. Keep
the existing open state and topics rendering logic, but replace the
overflow/transition class approach with the new motion animation for the topics
container.
- Around line 168-194: The conditional class composition in the course detail
accordion should use the shared cn() helper instead of inline template-literal
concatenation. Update the wrapper, ChevronDown, and open-state container class
handling in the component that renders the title/button toggle so the
conditional styles are merged through cn(), matching the pattern used elsewhere
like Button and keeping class composition consistent and safer to extend.
- Around line 319-332: The enroll CTA styling is duplicating and conflicting
between Button’s outline variant and the nested Link classes, so the variant on
Button is effectively redundant. Update the CourseDetailContentSection enroll
block to either remove the Button/asChild wrapper and keep the Link fully
styled, or move the full styling into Button and leave Link unstyled; use
Button, ButtonVariants, and the Link inside this enroll action as the key points
to adjust.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: b60dd4a3-4bdc-49b0-8907-c9d0f4ab0297
📒 Files selected for processing (7)
src/features/marketing/components/contact-hero-section.tsxsrc/features/marketing/components/course-detail-content-section.tsxsrc/features/marketing/components/cta-section.tsxsrc/features/marketing/components/donation-support-section.tsxsrc/features/marketing/components/footer.tsxsrc/features/marketing/components/hero-section.tsxsrc/features/marketing/components/testimonials.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
- src/features/marketing/components/footer.tsx
- src/features/marketing/components/cta-section.tsx
- src/features/marketing/components/testimonials.tsx
- src/features/marketing/components/hero-section.tsx
| 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> | ||
| ) | ||
| } |
There was a problem hiding this comment.
🩺 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.
| 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.
| Donate Now | ||
| <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" /> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Tailwind-related files =="
git ls-files | rg 'tailwind|postcss|css$|package.json$|donut|marketing/components/(donation-support-section|contact-form-button)'
echo
echo "== Search for gradient utilities =="
rg -n --hidden --no-ignore-vcs 'bg-gradient-to-r|bg-linear-to-r|tailwind' src . -g '!node_modules' -g '!dist' -g '!build'
echo
echo "== Inspect package.json and Tailwind config files =="
for f in package.json tailwind.config.* postcss.config.* src/**/*.css src/**/*.tsx; do
if [ -f "$f" ]; then
echo "--- $f ---"
sed -n '1,220p' "$f"
fi
doneRepository: Smartlify07/Modern-Advocates
Length of output: 19289
🌐 Web query:
Tailwind CSS v4 bg-gradient-to-r bg-linear-to-r renamed gradient utilities alias removed
💡 Result:
In Tailwind CSS v4, the bg-gradient-to-* utilities have been replaced by bg-linear-to-* to better align with the underlying CSS linear-gradient() function [1][2]. Key changes in v4 include: 1. Renaming: All linear gradient utilities have been renamed from bg-gradient-to-* to bg-linear-to-* (e.g., bg-gradient-to-r becomes bg-linear-to-r) [1][3]. The legacy bg-gradient-* alias has been removed in the v4 release [1][3]. 2. Expanded API: In addition to the standard directional utilities (like bg-linear-to-r or bg-linear-to-tl), v4 introduces support for explicit angles (e.g., bg-linear-45) and arbitrary values (e.g., bg-linear-[125deg]) [1][4][2]. 3. Consistency: These changes are part of a broader expansion of gradient utilities, which now also include bg-radial and bg-conic [1][2]. 4. Functionality: The associated color stop utilities—from-*, via-*, and to-*—remain functionally identical to their v3 counterparts [1][3]. Additionally, v4 introduces modifiers for color interpolation (e.g., /srgb, /oklch), which can be appended to the gradient utility [5][2]. For those migrating from v3, replacing the bg-gradient-to- prefix with bg-linear-to- is required, as the old class names are no longer supported [1][3].
Citations:
- 1: https://richdynamix.com/articles/tailwind-v4-gradient-utilities-bg-linear-radial-conic
- 2: https://tailwindcss.com/blog/tailwindcss-v4
- 3: https://capytoolkit.com/tools/design/gradient-builder/tailwind-v4-gradients/
- 4: tailwindlabs/tailwindcss@7b63886
- 5: https://tailwindcss.com/docs/background-image
Use bg-linear-to-r here. This overlay still uses the removed v3 bg-gradient-to-r utility, so the gradient won’t apply in Tailwind v4.
🤖 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/donation-support-section.tsx` at line 131,
The overlay in donation-support-section still uses the removed Tailwind v3
gradient utility, so update the gradient class on the highlighted absolute div
to the Tailwind v4 equivalent. Keep the existing styling and behavior intact,
but replace bg-gradient-to-r with bg-linear-to-r so the hover overlay renders
correctly in the component.
Summary
Summary by CodeRabbit
motiondependency for animation support.