feat(marketing): redesign hero section with Linear-style stacked layout#1452
feat(marketing): redesign hero section with Linear-style stacked layout#1452
Conversation
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughRefactored the HeroSection component to use a centered, mobile-first layout with scroll-driven animations. The ProductDemo component now accepts a scrollYProgress prop and renders scroll-triggered transformations. Updated AppMockup typography and layout dimensions. Adjusted TrustedBySection responsive behavior. Minor styling refinements to SelectorPill. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User<br/>(Scrolling)
participant HS as HeroSection
participant PS as useScroll<br/>(Hook)
participant PD as ProductDemo
participant AM as AppMockup
User->>HS: Scroll on page
HS->>PS: useScroll(demoRef)
PS->>PS: Calculate scrollYProgress
PS->>PD: Pass scrollYProgress
PD->>PD: useTransform:<br/>scale & pillsY
PD->>AM: Render with<br/>animated container
AM->>User: Display scaled mockup<br/>+ repositioned pills
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In
`@apps/marketing/src/app/components/HeroSection/components/AppMockup/AppMockup.tsx`:
- Around line 730-732: The LuGitPullRequest icon inside the AppMockup component
uses an invalid Tailwind class "size-4.5"; replace it with a valid class such as
"size-4" or "size-5" on the LuGitPullRequest element to ensure the icon is
properly sized (adjust to "size-4" for 1rem or "size-5" for 1.25rem depending on
the desired visual).
In `@apps/marketing/src/app/components/HeroSection/HeroSection.tsx`:
- Around line 59-67: Replace the GitHub <button> in the HeroSection component
with a semantic <a> element that points to COMPANY.GITHUB_URL (use
target="_blank" and rel="noopener noreferrer"), keep the same className,
aria-label="View on GitHub", visible text "View on GitHub" and the <FaGithub>
icon so styling and accessibility remain identical but native link behaviors
(middle-click, context menu, crawlers) are preserved.
🧹 Nitpick comments (2)
apps/marketing/src/app/components/HeroSection/components/ProductDemo/ProductDemo.tsx (1)
17-22: Consider extracting animation constants.The scroll-animation tuning values (
0.82,80,0.6) are inline magic numbers. Extracting them to named constants at module top improves readability and makes future tweaks easier to find.♻️ Suggested extraction
+const SCROLL_SCALE_END = 0.82; +const PILLS_Y_OFFSET = 80; +const OVERLAY_FADE_END = 0.6; + export function ProductDemo({ scrollYProgress }: ProductDemoProps) { ... - const scale = useTransform(scrollYProgress, [0, 1], [1, 0.82]); - const pillsY = useTransform(scrollYProgress, [0, 1], [0, 80]); - const overlayOpacity = useTransform(scrollYProgress, [0, 0.6], [1, 0]); + const scale = useTransform(scrollYProgress, [0, 1], [1, SCROLL_SCALE_END]); + const pillsY = useTransform(scrollYProgress, [0, 1], [0, PILLS_Y_OFFSET]); + const overlayOpacity = useTransform(scrollYProgress, [0, OVERLAY_FADE_END], [1, 0]);As per coding guidelines, "Extract hardcoded magic numbers, strings, and enums to named constants at module top instead of leaving them inline in logic".
apps/marketing/src/app/components/HeroSection/components/AppMockup/AppMockup.tsx (1)
408-495: Consider extracting repeated agent tab markup.The four agent tab
motion.divblocks (Claude, Codex, Gemini, Cursor) share identical animation config and structure, differing only insrc,alt, label text, anddelay. A data-driven approach would reduce ~90 lines of duplication.This is pre-existing duplication and not introduced by this PR, so feel free to defer.
♻️ Sketch of a data-driven approach
const AGENT_TABS = [ { src: "/app-icons/codex.svg", alt: "Codex", label: "codex", delay: 0.1 }, { src: "/app-icons/gemini.svg", alt: "Gemini", label: "gemini", delay: 0.25 }, { src: "/app-icons/cursor-agent.svg", alt: "Cursor", label: "cursor", delay: 0.4 }, ]; {AGENT_TABS.map((tab) => ( <motion.div key={tab.label} className="flex items-center gap-1.5 py-1 text-xs text-muted-foreground/60 hover:bg-white/5 rounded-t overflow-hidden" initial={{ opacity: 0, width: 0, paddingLeft: 0, paddingRight: 0 }} animate={{ opacity: activeDemo === "Use Any Agents" ? 1 : 0, width: activeDemo === "Use Any Agents" ? "auto" : 0, paddingLeft: activeDemo === "Use Any Agents" ? 12 : 0, paddingRight: activeDemo === "Use Any Agents" ? 12 : 0, }} transition={{ duration: 0.25, ease: "easeOut", delay: activeDemo === "Use Any Agents" ? tab.delay : 0, }} > <Image src={tab.src} alt={tab.alt} width={14} height={14} /> <span>{tab.label}</span> <LuX className="size-3.5 text-muted-foreground/30" /> </motion.div> ))}
| <div className="flex items-center justify-between px-3 py-2.5 border-b border-white/[0.06]"> | ||
| <div className="flex items-center gap-2"> | ||
| <LuGitPullRequest className="size-4 text-emerald-400/80" /> | ||
| <LuGitPullRequest className="size-4.5 text-emerald-400/80" /> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Search for size-4.5 usage across the codebase
rg -n 'size-4\.5' --type=ts --type=tsx -g '!node_modules'Repository: superset-sh/superset
Length of output: 91
🏁 Script executed:
# Find and inspect Tailwind config files
find . -name 'tailwind.config.*' -o -name 'tailwind.config.ts' | head -5 | xargs -I {} bash -c 'echo "=== {} ===" && head -100 {}'Repository: superset-sh/superset
Length of output: 1003
🏁 Script executed:
# Search for size-4.5 without file type restrictions
rg 'size-4\.5' -g '!node_modules'Repository: superset-sh/superset
Length of output: 214
🏁 Script executed:
# Find tailwind config in apps/marketing
find ./apps/marketing -name 'tailwind.config.*' | xargs -I {} bash -c 'echo "=== {} ===" && cat {}'Repository: superset-sh/superset
Length of output: 46
🏁 Script executed:
# Also check the root tailwind config
cat ./tailwind.config.ts 2>/dev/null || cat ./tailwind.config.js 2>/dev/null || echo "No root tailwind config found"Repository: superset-sh/superset
Length of output: 93
🏁 Script executed:
# Search for all tailwind-related config files
find . -type f \( -name '*tailwind*' -o -name '*postcss*' \) | grep -v node_modules | head -20Repository: superset-sh/superset
Length of output: 228
🏁 Script executed:
# Check if tailwind extends spacing in package.json or other config references
rg 'extend.*spacing|spacing.*4\.5' --type json --type tsRepository: superset-sh/superset
Length of output: 46
🏁 Script executed:
# Check what Tailwind utilities are actually available by looking at size classes used
rg 'size-[0-9]' -o | sort | uniqRepository: superset-sh/superset
Length of output: 29694
Use size-4 or size-5 instead of the invalid size-4.5 Tailwind class.
The size-4.5 utility does not exist in standard Tailwind and no configuration extends the spacing scale to include half-values like 4.5. This class is silently ignored, leaving the LuGitPullRequest icon unsized. Change to size-4 (1rem) or size-5 (1.25rem) depending on the intended visual size.
🤖 Prompt for AI Agents
In
`@apps/marketing/src/app/components/HeroSection/components/AppMockup/AppMockup.tsx`
around lines 730 - 732, The LuGitPullRequest icon inside the AppMockup component
uses an invalid Tailwind class "size-4.5"; replace it with a valid class such as
"size-4" or "size-5" on the LuGitPullRequest element to ensure the icon is
properly sized (adjust to "size-4" for 1rem or "size-5" for 1.25rem depending on
the desired visual).
| <button | ||
| type="button" | ||
| className="px-4 py-2.5 sm:px-6 sm:py-3 text-sm sm:text-base font-normal bg-background border border-border text-foreground hover:bg-muted transition-colors flex items-center gap-2" | ||
| onClick={() => window.open(COMPANY.GITHUB_URL, "_blank")} | ||
| aria-label="View on GitHub" | ||
| > | ||
| View on GitHub | ||
| <FaGithub className="size-4" /> | ||
| </button> |
There was a problem hiding this comment.
Use an <a> tag instead of <button> with window.open for the GitHub link.
A <button> with onClick={() => window.open(...)) loses native link behavior — middle-click to open in new tab, right-click context menu, link preview on hover, and crawler discoverability. An anchor element is semantically correct here.
🔗 Proposed fix
- <button
- type="button"
- className="px-4 py-2.5 sm:px-6 sm:py-3 text-sm sm:text-base font-normal bg-background border border-border text-foreground hover:bg-muted transition-colors flex items-center gap-2"
- onClick={() => window.open(COMPANY.GITHUB_URL, "_blank")}
- aria-label="View on GitHub"
- >
- View on GitHub
- <FaGithub className="size-4" />
- </button>
+ <a
+ href={COMPANY.GITHUB_URL}
+ target="_blank"
+ rel="noopener noreferrer"
+ className="px-4 py-2.5 sm:px-6 sm:py-3 text-sm sm:text-base font-normal bg-background border border-border text-foreground hover:bg-muted transition-colors flex items-center gap-2"
+ >
+ View on GitHub
+ <FaGithub className="size-4" />
+ </a>📝 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 | |
| type="button" | |
| className="px-4 py-2.5 sm:px-6 sm:py-3 text-sm sm:text-base font-normal bg-background border border-border text-foreground hover:bg-muted transition-colors flex items-center gap-2" | |
| onClick={() => window.open(COMPANY.GITHUB_URL, "_blank")} | |
| aria-label="View on GitHub" | |
| > | |
| View on GitHub | |
| <FaGithub className="size-4" /> | |
| </button> | |
| <a | |
| href={COMPANY.GITHUB_URL} | |
| target="_blank" | |
| rel="noopener noreferrer" | |
| className="px-4 py-2.5 sm:px-6 sm:py-3 text-sm sm:text-base font-normal bg-background border border-border text-foreground hover:bg-muted transition-colors flex items-center gap-2" | |
| > | |
| View on GitHub | |
| <FaGithub className="size-4" /> | |
| </a> |
🤖 Prompt for AI Agents
In `@apps/marketing/src/app/components/HeroSection/HeroSection.tsx` around lines
59 - 67, Replace the GitHub <button> in the HeroSection component with a
semantic <a> element that points to COMPANY.GITHUB_URL (use target="_blank" and
rel="noopener noreferrer"), keep the same className, aria-label="View on
GitHub", visible text "View on GitHub" and the <FaGithub> icon so styling and
accessibility remain identical but native link behaviors (middle-click, context
menu, crawlers) are preserved.
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
This PR is being reviewed by Cursor Bugbot
Details
You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
| @@ -1,5 +1,5 @@ | |||
| { | |||
| "$schema": "https://biomejs.dev/schemas/2.3.15/schema.json", | |||
| "$schema": "https://biomejs.dev/schemas/2.3.8/schema.json", | |||
There was a problem hiding this comment.
Biome schema downgraded mismatching installed package version
Low Severity
The $schema URL in biome.jsonc was downgraded from 2.3.15 to 2.3.8, but the project's package.json declares "@biomejs/biome": "^2.3.15" and bun.lock resolves to 2.3.15. This version mismatch is unrelated to the hero section redesign and appears accidental. It could cause IDE schema validation to miss config options available in 2.3.15 or flag valid options as errors.
There was a problem hiding this comment.
🧹 Nitpick comments (2)
apps/marketing/src/app/components/HeroSection/components/AppMockup/AppMockup.tsx (1)
268-281: Duplicated glass-border overlay pattern — consider extracting a shared component.The diagonal gradient glass border (CSS mask-composite trick) is repeated verbatim for the main container and the external IDE popup, with only minor opacity tweaks. A small
<GlassBorder />component acceptingclassNameand gradient values would eliminate the duplication.Also applies to: 855-868
apps/marketing/src/app/components/HeroSection/components/ProductDemo/ProductDemo.tsx (1)
68-76: TypeDEMO_OPTIONSlabels asActiveDemoto enforce compile-time safety.The
DemoOption.labelfield is currently typed asstring, which allows theas ActiveDemocast to bypass TypeScript's type checking. If a label is added toDEMO_OPTIONSwithout updating theActiveDemounion, the cast will silently accept an invalid value. Instead, define the interface as:export interface DemoOption { label: ActiveDemo; videoPath: string; colors: readonly [string, string, string, string]; }This eliminates the need for the cast and catches label mismatches at compile time.


Summary
Changes
HeroSection.tsx
flex-colwith centered text and full-width demo belowtext-4xltotext-7xl),font-medium,tracking-tightmax-w-xl mx-autouseScrollpassed down toProductDemoProductDemo.tsx
AppMockup.tsx
rounded-xl→rounded-2xl, darker bg (bg-black/60), thicker border (border-2 border-white/[0.12])text-[9px]→text-[11px],text-[10px]→text-xs)SelectorPill.tsx
rounded-fullfor pill shapeTest Plan
bun devin apps/marketing and visually verify hero sectionSummary by CodeRabbit
New Features
Style
Note
Low Risk
Primarily marketing UI/layout and animation tweaks; main risk is visual/regression across breakpoints and scroll performance, with no data/auth impact.
Overview
Redesigns the marketing
HeroSectionfrom a two-column layout into a centered, stacked hero with updated headline/copy and regrouped CTAs.Adds scroll-driven motion to the hero demo by tracking
scrollYProgressinHeroSectionand using it inProductDemoto scale the mockup and shift selector pills (mobile-aware), while removing the prior mesh-gradient background layer.Polishes the
AppMockupand controls with refined glass/shadow styling, larger typography/icon sizing, widened sidebars, and updatedTrustedBySectionspacing/visibility for small screens.Written by Cursor Bugbot for commit da04af9. This will update automatically on new commits. Configure here.