-
Notifications
You must be signed in to change notification settings - Fork 339
Feature: Subscription page uplift #2425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feature: Subscription page uplift #2425
Conversation
📝 WalkthroughWalkthroughAdds two new UI components (LogosCarousel, ServiceFAQ) and a large subscription/home UI overhaul that replaces the hero, adds the carousel and FAQ, and refactors pricing/subscribe cards and related presentation logic. Changes
Sequence Diagram(s)(omitted) Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In @src/components/ServiceFAQ.tsx:
- Around line 100-109: The FAQ answer wrapper has a duplicate/contradicting
padding classes on the inner div ("pt-4 pb-4 pt-0") and a hard-coded maxHeight
of '200px' that can truncate content; update the inner div to use a single,
consistent padding class (e.g., remove the redundant "pt-4" or "pt-0" so only
one top padding remains) and change the collapsing strategy used with
expandedId/item.id so the max-height is not an arbitrary fixed 200px — either
use a larger sensible limit or switch to dynamic sizing (e.g., transition to
auto-height or calculate content height of item.answer) so long answers aren’t
clipped.
In @src/components/SubscribeCards/SubscribeEnterpriseCard.tsx:
- Around line 8-16: Remove the ineffective Tailwind
"disabled:cursor-not-allowed" and "disabled:opacity-70" variants from the <a>
element in SubscribeEnterpriseCard (the anchor with className starting "group
mt-auto..."); update the className to drop those two variants, and if you need a
visual disabled state or semantics instead convert the anchor to a <button> or
add aria-disabled and conditional classes (e.g., "cursor-not-allowed opacity-70"
applied conditionally) where appropriate.
In @src/containers/Subscribtion/Home.tsx:
- Around line 255-264: The JSX contains a redundant ternary in the outer div's
className using isAuthenticated (isAuthenticated ? 'lg:order-1' : 'lg:order-1');
remove the unnecessary conditional and replace it with the plain class string
'lg:order-1' (or implement the intended alternate ordering if authentication
should change order) in the component that renders <FreeCard />; also apply the
same cleanup to the other occurrence that uses lg:order-3 so both locations use
a single class string or the correct conditional value.
🧹 Nitpick comments (4)
src/components/SubscribeCards/SubscribeEnterpriseCard.tsx (1)
40-65: Consider extracting features to a data array to reduce repetition.The six feature items share identical markup. Extracting them to an array would improve maintainability and make future updates easier.
Suggested refactor
const ENTERPRISE_FEATURES = [ 'All features included in Pro and API tiers', 'Hourly data', 'Direct raw access to our database', 'Access to non-public data, such as TVL breakdowns by token address', 'Custom bespoke solutions that fit your needs', 'Custom data licensing agreements', ] // Then in the component: <div className="grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-3 mb-8"> {ENTERPRISE_FEATURES.map((feature) => ( <div key={feature} className="flex items-start gap-3"> <div className="flex-shrink-0 w-1.5 h-1.5 rounded-full bg-[#5C5CF9] mt-1.5" /> <span className="text-sm text-white">{feature}</span> </div> ))} </div>src/components/LogosCarousel.tsx (2)
57-77: Consider extracting inline styles to avoid SSR/CSR mismatch risks.Injecting
<style>tags inside JSX can cause hydration warnings in Next.js if the content differs between server and client renders. While this implementation should be stable (duration is derived from props), consider moving these keyframes to a global CSS file or using CSS-in-JS solutions that handle SSR properly.
86-98: Adddraggable="false"to prevent unintended drag behavior on logos.Images in a scrolling carousel can be accidentally dragged by users, which may interfere with the hover-to-pause UX.
Suggested improvement
<img src={logo.src} alt={logo.alt} className="max-h-full max-w-full object-contain object-center opacity-70 hover:opacity-100 transition-opacity duration-300 filter grayscale hover:grayscale-0" loading="lazy" + draggable="false" />src/containers/Subscribtion/Home.tsx (1)
123-136: Prefer React refs over direct DOM queries.Using
document.querySelector('[data-plan="pro"]')breaks React's declarative paradigm and may fail if the element hasn't mounted. Consider using the existingpricingContainerref or creating a dedicated ref for the Pro card.Suggested ref-based approach
+ const proCardRef = useRef<HTMLDivElement>(null) <button onClick={() => { - const proCardElement = document.querySelector('[data-plan="pro"]') - if (proCardElement) { - proCardElement.scrollIntoView({ behavior: 'smooth', block: 'center' }) - } + proCardRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' }) }} ... > // Then on the Pro card div: - data-plan="pro" + ref={proCardRef}
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/components/LogosCarousel.tsxsrc/components/ServiceFAQ.tsxsrc/components/SubscribeCards/SubscribeAPICard.tsxsrc/components/SubscribeCards/SubscribeEnterpriseCard.tsxsrc/components/SubscribeCards/SubscribeProCard.tsxsrc/containers/Subscribtion/Home.tsx
🧰 Additional context used
🧬 Code graph analysis (5)
src/components/ServiceFAQ.tsx (2)
src/components/Icon.tsx (1)
Icon(108-114)src/utils/index.js (1)
a(893-893)
src/components/SubscribeCards/SubscribeEnterpriseCard.tsx (1)
src/components/Icon.tsx (1)
Icon(108-114)
src/containers/Subscribtion/Home.tsx (5)
src/components/Icon.tsx (1)
Icon(108-114)src/containers/Subscribtion/SignIn.tsx (1)
SignInModal(12-83)src/components/LogosCarousel.tsx (1)
LogosCarousel(15-104)src/components/SubscribeCards/FreeCard.tsx (1)
FreeCard(3-49)src/components/ServiceFAQ.tsx (1)
ServiceFAQ(55-142)
src/components/SubscribeCards/SubscribeAPICard.tsx (1)
src/containers/Subscribtion/SignIn.tsx (1)
SignInModal(12-83)
src/components/SubscribeCards/SubscribeProCard.tsx (1)
src/containers/Subscribtion/SignIn.tsx (1)
SignInModal(12-83)
🔇 Additional comments (13)
src/components/SubscribeCards/SubscribeEnterpriseCard.tsx (2)
1-3: LGTM!The function signature is clean with well-typed optional props and sensible defaults.
27-85: Verify:activeprop is unused in full card mode.The
activeprop triggers the "Current Plan" indicator in button mode but has no effect when rendering the full card. Confirm this is intentional, or add the indicator to the full card layout if needed.src/components/LogosCarousel.tsx (1)
1-35: Well-structured carousel component with good performance considerations.The component is well-designed with proper TypeScript interfaces, configurable props, and correct
useMemodependency tracking. The 3x logo duplication strategy for seamless infinite scrolling is appropriate.src/components/ServiceFAQ.tsx (2)
1-53: LGTM - Well-structured FAQ data and component setup.The FAQ items are well-organized with unique IDs, clear questions, and comprehensive answers. The useState hook for tracking expansion state is appropriate for this single-accordion pattern.
117-138: CTA section looks good with proper accessibility attributes.External links correctly use
target="_blank"withrel="noopener noreferrer"for security. The gradient styling and hover effects are consistent with the design system.src/components/SubscribeCards/SubscribeProCard.tsx (2)
57-59: Visually appealing trial badge with gradient styling.The new badge design uses a gradient background with appropriate contrast and shadow effects. The styling is consistent with the premium branding theme of the PR.
174-174: SignInModal className usage is correct.The
classNameprop properly overrides the default button styling as per the SignInModal component interface (fromsrc/containers/Subscribtion/SignIn.tsxlines 11-82). The styling is consistent with other card components in this PR.src/components/SubscribeCards/SubscribeAPICard.tsx (2)
71-95: Informative rate limits card with clear visual hierarchy.The new info card effectively communicates API limits (1000 req/min, 1M calls/month, $0.60/1K overage) in a compact, scannable format. The styling is consistent with the overall design system, and the docs link properly uses
rel="noreferrer noopener".
137-137: Consistent SignInModal styling across subscription cards.The
classNameprop usage matches the pattern inSubscribeProCard.tsx, ensuring visual consistency across the pricing page.src/containers/Subscribtion/Home.tsx (4)
5-6: New component imports align with the PR objectives.The
LogosCarouselandServiceFAQimports integrate the newly created reusable components into the subscription home page.
195-216: LogosCarousel integration looks good.The institutional logos carousel effectively showcases trusted partners. The hardcoded logo array is acceptable for this use case since these are static brand assets.
218-250: Clean billing toggle implementation.The monthly/yearly toggle with the "Save 17%" badge is well-implemented. The gradient styling and transitions provide good visual feedback for the selected state.
341-342: ServiceFAQ integration completes the page structure.The FAQ section is appropriately placed after the pricing cards, providing users with answers to common questions before making a purchase decision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@src/containers/Subscribtion/Home.tsx`:
- Around line 76-77: The JSX in the Home component has five missing closing div
tags starting from the wrapper div with className "relative mx-auto flex w-full
max-w-6xl flex-col gap-12 px-5 pb-[64px] xl:max-w-7xl 2xl:max-w-[1440px]";
locate that outer <div> in src/containers/Subscribtion/Home.tsx and add the five
corresponding </div> endings to properly close the nested JSX blocks (matching
each opened <div> used for sections like the Premium Hero Section and subsequent
nested containers), then re-run the JSX/TSX linter or TypeScript compiler to
confirm tag balance and ensure no other unclosed tags remain.
- Around line 81-84: Add the missing `@keyframes` for the animations named
fadeInDown and fadeInUp into your global Tailwind CSS file (the project's
tailwind.css) using the provided keyframe definitions so the utility classes
like animate-[fadeInDown_0.8s_ease-out] and animate-[fadeInUp_0.8s_ease-out]
actually animate; after adding the keyframes, rebuild/restart the dev server so
the new animations are picked up.
🧹 Nitpick comments (2)
src/components/SubscribeCards/SubscribeEnterpriseCard.tsx (1)
39-65: Consider extracting feature items to reduce repetition.The features list has repeated markup. Extracting to a data array and mapping would improve maintainability.
♻️ Optional refactor
const enterpriseFeatures = [ 'All features included in Pro and API tiers', 'Hourly data', 'Direct raw access to our database', 'Access to non-public data, such as TVL breakdowns by token address', 'Custom bespoke solutions that fit your needs', 'Custom data licensing agreements' ] // In render: <div className="grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-3 mb-8"> {enterpriseFeatures.map((feature, index) => ( <div key={index} className="flex items-start gap-3"> <div className="flex-shrink-0 w-1.5 h-1.5 rounded-full bg-[`#5C5CF9`] mt-1.5" /> <span className="text-sm text-white">{feature}</span> </div> ))} </div>src/containers/Subscribtion/Home.tsx (1)
194-216: Consider extracting logo data to a constant.The inline logos array is 12 items long and spans multiple lines. Moving it to a constant at the top of the file would improve readability and make the component structure cleaner, especially if the logo set may need updates in the future.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/components/ServiceFAQ.tsxsrc/components/SubscribeCards/SubscribeEnterpriseCard.tsxsrc/containers/Subscribtion/Home.tsx
🧰 Additional context used
🧬 Code graph analysis (3)
src/containers/Subscribtion/Home.tsx (6)
src/containers/Subscribtion/SignIn.tsx (1)
SignInModal(12-83)src/components/LogosCarousel.tsx (1)
LogosCarousel(15-104)src/components/SubscribeCards/FreeCard.tsx (1)
FreeCard(3-49)src/components/SubscribeCards/SubscribeAPICard.tsx (1)
SubscribeAPICard(11-165)src/components/SubscribeCards/SubscribeEnterpriseCard.tsx (1)
SubscribeEnterpriseCard(3-87)src/components/ServiceFAQ.tsx (1)
ServiceFAQ(55-142)
src/components/ServiceFAQ.tsx (2)
src/components/Icon.tsx (1)
Icon(108-114)src/utils/index.js (1)
a(893-893)
src/components/SubscribeCards/SubscribeEnterpriseCard.tsx (1)
src/components/Icon.tsx (1)
Icon(108-114)
🔇 Additional comments (13)
src/components/ServiceFAQ.tsx (5)
1-9: LGTM!Clean imports and well-defined TypeScript interface for FAQ items.
10-53: LGTM!FAQ content is well-structured with unique IDs and clear questions/answers covering key subscription topics.
78-97: LGTM!The accordion toggle logic is clean. The chevron rotation animation provides good visual feedback for the expand/collapse state.
99-109: Previous feedback addressed.The padding classes are now clean (
px-6 py-4) and themaxHeightincreased to 500px, which should accommodate the current FAQ answer lengths.
117-138: LGTM!CTA footer is well-implemented with proper security attributes on external links (
rel="noopener noreferrer"). The layout adapts responsively withflex-col sm:flex-row.src/components/SubscribeCards/SubscribeEnterpriseCard.tsx (2)
3-24: Previous feedback addressed - LGTM!The
isButtonprop creates a clean conditional rendering pattern. Thedisabled:classes have been removed from the anchor element as previously flagged.
67-85: Previous feedback addressed - LGTM!The pricing section CTA no longer has the ineffective
disabled:classes on the anchor element.src/containers/Subscribtion/Home.tsx (6)
5-6: LGTM!New component imports are properly structured.
123-129: LGTM!The scroll-to-section approach using
data-planattribute andscrollIntoViewis clean and functional.
221-250: LGTM!The billing toggle implementation is clean with proper state management. The "Save 17%" calculation aligns with the yearly pricing (10 months for price of 12).
255-264: Previous feedback addressed - LGTM!The redundant conditional has been fixed. The order now correctly differs based on authentication state (
lg:order-1vslg:order-2).
296-298: Previous feedback addressed.The redundant conditional on the API card's order class has also been simplified to just
lg:order-3.
339-341: LGTM!Clean integration of the ServiceFAQ component at the appropriate position in the page layout.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| <div className="relative mx-auto flex w-full max-w-6xl flex-col gap-12 px-5 pb-[64px] xl:max-w-7xl 2xl:max-w-[1440px]"> | ||
| {/* Premium Hero Section */} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
FILE="src/containers/Subscribtion/Home.tsx"
echo "=== DIV Tag Analysis ==="
OPEN_DIVS=$(grep -o '<div' "$FILE" | wc -l)
CLOSE_DIVS=$(grep -o '</div>' "$FILE" | wc -l)
echo "Opening <div tags: $OPEN_DIVS"
echo "Closing </div> tags: $CLOSE_DIVS"
if [ "$OPEN_DIVS" -eq "$CLOSE_DIVS" ]; then
echo "✓ Total div tags are balanced"
else
echo "⚠ Total div tags are imbalanced (difference: $((OPEN_DIVS - CLOSE_DIVS)))"
fiRepository: DefiLlama/defillama-app
Length of output: 185
Fix 5 unclosed div tags in the JSX structure.
The div tag balance is broken: 35 opening tags vs. 30 closing tags. The missing 5 closing </div> tags must be added to complete the JSX structure. This is critical for proper rendering.
🤖 Prompt for AI Agents
In `@src/containers/Subscribtion/Home.tsx` around lines 76 - 77, The JSX in the
Home component has five missing closing div tags starting from the wrapper div
with className "relative mx-auto flex w-full max-w-6xl flex-col gap-12 px-5
pb-[64px] xl:max-w-7xl 2xl:max-w-[1440px]"; locate that outer <div> in
src/containers/Subscribtion/Home.tsx and add the five corresponding </div>
endings to properly close the nested JSX blocks (matching each opened <div> used
for sections like the Premium Hero Section and subsequent nested containers),
then re-run the JSX/TSX linter or TypeScript compiler to confirm tag balance and
ensure no other unclosed tags remain.
| <div className="animate-[fadeInDown_0.8s_ease-out] flex items-center gap-2 rounded-full border border-[#5C5CF9]/30 bg-[#5C5CF9]/5 px-4 py-2 backdrop-blur-sm"> | ||
| <div className="h-2 w-2 rounded-full bg-[#5C5CF9] animate-pulse" /> | ||
| <span className="text-xs font-medium text-[#5C5CF9]">Unlock unlimited potential</span> | ||
| </div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for keyframe definitions in the codebase
echo "=== Searching for fadeInDown keyframe ==="
rg -n '@keyframes fadeInDown' --type css --type scss
echo "=== Searching for fadeInUp keyframe ==="
rg -n '@keyframes fadeInUp' --type css --type scss
echo "=== Searching for pulse keyframe ==="
rg -n '@keyframes pulse' --type css --type scss
echo "=== Searching for fadeInDown in all files ==="
rg -n 'fadeInDown' --type css --type scss -i
echo "=== Check Tailwind config file ==="
fd -e 'js' -e 'ts' | grep -E 'tailwind|config' | head -20
echo "=== Global CSS files ==="
fd -e css -e scss | grep -E 'global|index|main|style'Repository: DefiLlama/defillama-app
Length of output: 751
🏁 Script executed:
#!/bin/bash
echo "=== Search all files for `@keyframes` ==="
rg -n '@keyframes' --max-count 20
echo "=== Search for fadeInDown/fadeInUp/pulse in all files ==="
rg -n 'fadeInDown|fadeInUp' --max-count 20
echo "=== Check Home.tsx file around lines 81-84 ==="
wc -l src/containers/Subscribtion/Home.tsx
head -100 src/containers/Subscribtion/Home.tsx | tail -25
echo "=== Look for tailwind config ==="
fd 'tailwind.config' | head -5
echo "=== Check for CSS files in src ==="
fd -e css | head -20Repository: DefiLlama/defillama-app
Length of output: 3479
🏁 Script executed:
#!/bin/bash
echo "=== Find tailwind config file ==="
find . -name "tailwind.config.*" -type f 2>/dev/null
echo "=== Check if tailwind.config exists at root ==="
ls -la | grep -E 'tailwind|config'
echo "=== Search for animation configuration in next.config ==="
rg -n 'animation|keyframes' next.config.ts -A 5 -B 2
echo "=== Check tailwind.css for animation definitions ==="
rg -n '@keyframes (fadeInDown|fadeInUp|pulse)' src/tailwind.css -iRepository: DefiLlama/defillama-app
Length of output: 599
🏁 Script executed:
#!/bin/bash
echo "=== Check postcss config ==="
cat postcss.config.mjs
echo "=== Double check: List all `@keyframes` in tailwind.css ==="
rg -n '@keyframes' src/tailwind.cssRepository: DefiLlama/defillama-app
Length of output: 534
Add missing CSS keyframe definitions for fadeInDown and fadeInUp animations.
The animations fadeInDown and fadeInUp are used extensively in this component (lines 81, 88, 108, 112, 120, 165, 175) but their @keyframes definitions do not exist in the codebase. Add them to src/tailwind.css:
Suggested keyframe definitions
`@keyframes` fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
`@keyframes` fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}Without these definitions, the animations will silently fail and elements will appear instantly without the intended entrance effects.
🤖 Prompt for AI Agents
In `@src/containers/Subscribtion/Home.tsx` around lines 81 - 84, Add the missing
`@keyframes` for the animations named fadeInDown and fadeInUp into your global
Tailwind CSS file (the project's tailwind.css) using the provided keyframe
definitions so the utility classes like animate-[fadeInDown_0.8s_ease-out] and
animate-[fadeInUp_0.8s_ease-out] actually animate; after adding the keyframes,
rebuild/restart the dev server so the new animations are picked up.
Redesign of the /subscription page to make it sexier and more UX-friendly, with the goal of boosting conversions.
Summary by CodeRabbit
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.