feat(marketing): add interactive hero mockup with animated demo states#910
feat(marketing): add interactive hero mockup with animated demo states#910
Conversation
…teractions Replace video-based demos with static AppMockup component and change selector pills to trigger on hover instead of click, preparing for animated demo states.
Expand right sidebar and show GitHub-style PR diff review when See Changes demo option is hovered.
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughAdds a client-only AppMockup React component and integrates it into ProductDemo (replacing DemoVideo), switches SelectorPill to hover-driven interaction, and adds new shader and wave background UI components used by HeroSection. Changes
Sequence Diagram(s)mermaid User->>SelectorPill: hover option Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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 |
🚀 Preview Deployment🔗 Preview Links
Preview updates automatically with new commits |
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 521-540: In the AppMockup component update the hard-coded file
paths that include the real username (e.g., "/Users/kietho/.claude.json" and
"/Users/kietho/.superset/.../.mcp.json") to generic placeholders before shipping
the UI; replace those occurrences in AppMockup.tsx with non-identifying strings
such as "~/.claude.json", "/path/to/project/.mcp.json" or
"~/projects/<project>/.mcp.json" so the mock paths remain realistic but contain
no personal data.
In
`@apps/marketing/src/app/components/HeroSection/components/ProductDemo/components/SelectorPill/SelectorPill.tsx`:
- Around line 5-20: The SelectorPill component only calls onHover via
onMouseEnter; make it accessible by also invoking the onHover callback on focus
and on click. Update the motion.button JSX inside SelectorPill to add onFocus
and onClick handlers that call onHover (e.g., onFocus={() => onHover?.()} and
onClick={() => onHover?.()}) so keyboard focus/Enter and touch/click users can
activate the demo just like mouse hover.
🧹 Nitpick comments (3)
apps/marketing/src/app/components/HeroSection/components/AppMockup/AppMockup.tsx (2)
21-250: Split helper components into their own files.
This file defines multiple React components (AsciiSpinner, StatusIndicator, WorkspaceItem, FileChangeItem, AppMockup). Please move helpers into dedicated files under the AppMockup folder and import them here to keep one component per.tsx. As per coding guidelines.
199-226: Use a typed lookup map for FileChangeItem icon/color selection.
Nested ternaries plustype: stringare brittle; aRecord<FileChangeType, …>tightens typing and follows the lookup-map guideline. As per coding guidelines.♻️ Suggested refactor
+type FileChangeType = "folder" | "add" | "edit" | "file"; +const FILE_CHANGE_META: Record< + FileChangeType, + { icon: typeof LuFolder; color: string; isFolder?: boolean } +> = { + folder: { icon: LuFolder, color: "text-muted-foreground/50", isFolder: true }, + add: { icon: LuFilePlus, color: "text-emerald-400" }, + edit: { icon: LuPencil, color: "text-amber-400" }, + file: { icon: LuFile, color: "text-muted-foreground/50" }, +}; function FileChangeItem({ path, add = 0, del = 0, indent = 0, type, }: { path: string; add?: number; del?: number; indent?: number; - type: string; + type: FileChangeType; }) { - const Icon = - type === "folder" - ? LuFolder - : type === "add" - ? LuFilePlus - : type === "edit" - ? LuPencil - : LuFile; - const iconColor = - type === "add" - ? "text-emerald-400" - : type === "edit" - ? "text-amber-400" - : "text-muted-foreground/50"; - - const isFolder = type === "folder"; + const { icon: Icon, color: iconColor, isFolder = false } = + FILE_CHANGE_META[type];apps/marketing/src/app/components/HeroSection/components/ProductDemo/ProductDemo.tsx (1)
38-44: Avoid theas ActiveDemocast by typingDEMO_OPTIONS.
The assertion masks mismatches; if labels drift, state can become invalid. Type the options list solabelisActiveDemo, then drop the cast.♻️ Suggested refactor
- onHover={() => setActiveOption(option.label as ActiveDemo)} + onHover={() => setActiveOption(option.label)}And in
apps/marketing/src/app/components/HeroSection/components/ProductDemo/constants.ts:import type { ActiveDemo } from "../AppMockup"; export const DEMO_OPTIONS = [ // ... ] satisfies Array<{ label: ActiveDemo }>;
| <div className="mt-3 text-muted-foreground/70"> | ||
| <div>MCP Config locations (by scope):</div> | ||
| <div className="ml-2"> | ||
| • User config (available in all your projects): | ||
| </div> | ||
| <div className="ml-4 text-muted-foreground/50"> | ||
| · /Users/kietho/.claude.json | ||
| </div> | ||
| <div className="ml-2"> | ||
| • Project config (shared via .mcp.json): | ||
| </div> | ||
| <div className="ml-4 text-muted-foreground/50"> | ||
| · | ||
| /Users/kietho/.superset/worktrees/superset/cloud-ws/.mcp.json | ||
| </div> | ||
| <div className="ml-2"> | ||
| • Local config (private to you in this project): | ||
| </div> | ||
| <div className="ml-4 text-muted-foreground/50"> | ||
| · /Users/kietho/.claude.json [project: ...] |
There was a problem hiding this comment.
Remove the real-looking username from mock paths.
/Users/kietho/... reads like a personal identifier. Replace with generic placeholders (e.g., ~/.claude.json) before shipping marketing UI.
✅ Suggested fix
- · /Users/kietho/.claude.json
+ · ~/.claude.json
...
- /Users/kietho/.superset/worktrees/superset/cloud-ws/.mcp.json
+ ~/.superset/worktrees/superset/cloud-ws/.mcp.json
...
- · /Users/kietho/.claude.json [project: ...]
+ · ~/.claude.json [project: ...]🤖 Prompt for AI Agents
In
`@apps/marketing/src/app/components/HeroSection/components/AppMockup/AppMockup.tsx`
around lines 521 - 540, In the AppMockup component update the hard-coded file
paths that include the real username (e.g., "/Users/kietho/.claude.json" and
"/Users/kietho/.superset/.../.mcp.json") to generic placeholders before shipping
the UI; replace those occurrences in AppMockup.tsx with non-identifying strings
such as "~/.claude.json", "/path/to/project/.mcp.json" or
"~/projects/<project>/.mcp.json" so the mock paths remain realistic but contain
no personal data.
| interface SelectorPillProps { | ||
| label: string; | ||
| active?: boolean; | ||
| onClick?: () => void; | ||
| onHover?: () => void; | ||
| } | ||
|
|
||
| export function SelectorPill({ | ||
| label, | ||
| active = false, | ||
| onClick, | ||
| onHover, | ||
| }: SelectorPillProps) { | ||
| return ( | ||
| <motion.button | ||
| type="button" | ||
| onClick={onClick} | ||
| onMouseEnter={onHover} | ||
| className={` |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n apps/marketing/src/app/components/HeroSection/components/ProductDemo/components/SelectorPill/SelectorPill.tsxRepository: superset-sh/superset
Length of output: 1142
🏁 Script executed:
cat -n apps/marketing/src/app/components/HeroSection/components/ProductDemo/components/ProductDemo.tsxRepository: superset-sh/superset
Length of output: 191
🏁 Script executed:
rg "SelectorPill" apps/marketing/src/app/components/HeroSection/components/ProductDemo/ -A 5 -B 2Repository: superset-sh/superset
Length of output: 4474
Support keyboard and touch activation, not just hover.
The button only listens to onMouseEnter, making demo selection inaccessible for keyboard and touch users. Add onFocus and onClick to enable activation via keyboard focus/enter and touch/click events.
Suggested fix
<motion.button
type="button"
- onMouseEnter={onHover}
+ onMouseEnter={onHover}
+ onFocus={onHover}
+ onClick={onHover}
className={`📝 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.
| interface SelectorPillProps { | |
| label: string; | |
| active?: boolean; | |
| onClick?: () => void; | |
| onHover?: () => void; | |
| } | |
| export function SelectorPill({ | |
| label, | |
| active = false, | |
| onClick, | |
| onHover, | |
| }: SelectorPillProps) { | |
| return ( | |
| <motion.button | |
| type="button" | |
| onClick={onClick} | |
| onMouseEnter={onHover} | |
| className={` | |
| interface SelectorPillProps { | |
| label: string; | |
| active?: boolean; | |
| onHover?: () => void; | |
| } | |
| export function SelectorPill({ | |
| label, | |
| active = false, | |
| onHover, | |
| }: SelectorPillProps) { | |
| return ( | |
| <motion.button | |
| type="button" | |
| onMouseEnter={onHover} | |
| onFocus={onHover} | |
| onClick={onHover} | |
| className={` |
🤖 Prompt for AI Agents
In
`@apps/marketing/src/app/components/HeroSection/components/ProductDemo/components/SelectorPill/SelectorPill.tsx`
around lines 5 - 20, The SelectorPill component only calls onHover via
onMouseEnter; make it accessible by also invoking the onHover callback on focus
and on click. Update the motion.button JSX inside SelectorPill to add onFocus
and onClick handlers that call onHover (e.g., onFocus={() => onHover?.()} and
onClick={() => onHover?.()}) so keyboard focus/Enter and touch/click users can
activate the demo just like mouse hover.
Fix lint issues from PR #910 that were merged with failing CI: - Add biome-ignore for useEffect dependency array in wave animation - Fix import type for React - Format code to pass biome checks
Fix lint issues from PR #910: - Add biome-ignore for useEffect in wave animation - Format code to pass biome checks
Fix lint issues from PR #910: - Add biome-ignore for useEffect in wave animation - Format code to pass biome checks
* feat(billing): gate billing page behind feature flag Hide billing settings from users who don't have the billing-enabled feature flag. Uses centralized FEATURE_FLAGS constant from shared. * fix(marketing): fix lint errors in hero section components Fix lint issues from PR #910: - Add biome-ignore for useEffect in wave animation - Format code to pass biome checks
Summary
Test plan
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.