Skip to content

feat(marketing): add interactive hero mockup with animated demo states#910

Merged
Kitenite merged 11 commits intomainfrom
hero-component
Jan 23, 2026
Merged

feat(marketing): add interactive hero mockup with animated demo states#910
Kitenite merged 11 commits intomainfrom
hero-component

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Jan 23, 2026

Summary

  • Replace video-based hero demos with a static app mockup component
  • Add hover-triggered animations for each demo option pill:
    • Use Any Agents: Animates in additional agent tabs (codex, gemini, cursor) with icons
    • Create Parallel Branches: Shows new workspace creation with terminal setup text
    • See Changes: Expands right sidebar with GitHub-style PR diff review
    • Open in Any IDE: Displays external IDE popup with code editor view

Test plan

  • Verify hover interactions work on all four demo pills
  • Check animations are smooth and sequential
  • Test responsive behavior on different screen sizes
  • Ensure mockup accurately represents the desktop app UI

Summary by CodeRabbit

  • New Features
    • Interactive application mockup with multi-agent tabs, workspace/sidebar, terminal output, change/diff review, and external IDE preview.
    • New animated backgrounds: shader-driven animation and interactive wave background.
    • Four demo modes: Use Any Agents, Create Parallel Branches, See Changes, Open in Any IDE.
  • Chore
    • Replaced static demo videos with the interactive mockup.
  • Style
    • Demo selector now switches scenarios on hover for faster previews.

✏️ Tip: You can customize this high-level summary in your review settings.

…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.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 23, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds 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

Cohort / File(s) Summary
New AppMockup Component
apps/marketing/src/app/components/HeroSection/components/AppMockup/AppMockup.tsx, apps/marketing/src/app/components/HeroSection/components/AppMockup/index.ts
Adds AppMockup component and exported ActiveDemo type. Implements a multi-pane static mock UI (workspace sidebar, tabbed main/terminal area, changes/review pane, optional IDE popup) with internal primitives and demo data; client-only, no data fetching.
ProductDemo Integration
apps/marketing/src/app/components/HeroSection/components/ProductDemo/ProductDemo.tsx
Replaces per-option DemoVideo rendering with <AppMockup activeDemo={activeOption} />; changes local state from string to ActiveDemo and imports AppMockup/ActiveDemo.
SelectorPill Interaction
apps/marketing/src/app/components/HeroSection/components/ProductDemo/components/SelectorPill/SelectorPill.tsx
Replaces onClick prop with onHover and uses onMouseEnter to update selection so demo changes on hover.
HeroSection visual updates
apps/marketing/src/app/components/HeroSection/HeroSection.tsx
Replaces GridBackground with new ShaderAnimation and updates hero copy text.
New UI primitives (visuals)
apps/marketing/src/components/ui/shader-animation.tsx, apps/marketing/src/components/ui/wave-background.tsx, apps/marketing/src/components/ui/index.ts
Adds ShaderAnimation (Three.js shader canvas) and Waves (SVG wave background) components and re-exports them from UI index.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant User
participant SelectorPill
participant ProductDemo
participant AppMockup
participant ExternalIDE

User->>SelectorPill: hover option
SelectorPill->>ProductDemo: onHover(label as ActiveDemo)
ProductDemo->>AppMockup: set activeDemo prop
AppMockup-->>AppMockup: render sidebar, main panel, right pane
alt activeDemo == "Open in Any IDE"
AppMockup->>ExternalIDE: open IDE popup
ExternalIDE-->>AppMockup: popup visible
end

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A mockup hops in with panels aglow,
Tabs and diffs and spinners all in a row,
Hover me gently and watch the panes play,
Popup an IDE and the demo will sway,
Cheers from a rabbit—code bright as day!

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description includes a comprehensive summary of changes and a test plan checklist, but does not follow the provided template structure with all required sections (Related Issues, Type of Change, Testing details, Screenshots, Additional Notes). Reorganize the description to match the template structure: add explicit 'Type of Change' section (mark 'New feature'), expand 'Testing' with detailed steps beyond the checklist, and clarify 'Related Issues' if any.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: adding an interactive hero mockup component with animated demo states, which matches the main objectives of replacing video-based demos with a static mockup.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 23, 2026

🚀 Preview Deployment

🔗 Preview Links

Service Status Link
Neon Database (Neon) View Branch
Fly.io Electric (Fly.io) View App
Vercel API (Vercel) Open Preview
Vercel Web (Vercel) Open Preview
Vercel Marketing (Vercel) Open Preview
Vercel Admin (Vercel) Open Preview
Vercel Docs (Vercel) Open Preview

Preview updates automatically with new commits

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a 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
`@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 plus type: string are brittle; a Record<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 the as ActiveDemo cast by typing DEMO_OPTIONS.
The assertion masks mismatches; if labels drift, state can become invalid. Type the options list so label is ActiveDemo, 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 }>;

Comment on lines +521 to +540
<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: ...]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

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.

Comment on lines 5 to 20
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={`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n apps/marketing/src/app/components/HeroSection/components/ProductDemo/components/SelectorPill/SelectorPill.tsx

Repository: superset-sh/superset

Length of output: 1142


🏁 Script executed:

cat -n apps/marketing/src/app/components/HeroSection/components/ProductDemo/components/ProductDemo.tsx

Repository: superset-sh/superset

Length of output: 191


🏁 Script executed:

rg "SelectorPill" apps/marketing/src/app/components/HeroSection/components/ProductDemo/ -A 5 -B 2

Repository: 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.

Suggested change
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.

@Kitenite Kitenite merged commit 6bd99ba into main Jan 23, 2026
3 of 6 checks passed
@Kitenite Kitenite deleted the hero-component branch January 23, 2026 05:38
saddlepaddle added a commit that referenced this pull request Jan 23, 2026
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
saddlepaddle added a commit that referenced this pull request Jan 23, 2026
Fix lint issues from PR #910:
- Add biome-ignore for useEffect in wave animation
- Format code to pass biome checks
saddlepaddle added a commit that referenced this pull request Jan 23, 2026
Fix lint issues from PR #910:
- Add biome-ignore for useEffect in wave animation
- Format code to pass biome checks
saddlepaddle added a commit that referenced this pull request Jan 23, 2026
* 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant