style(marketing): redesign hero AppMockup to match v2 / Linear#4394
Conversation
Restructures the marketing-page product demo to align with the v2 desktop UI shipped in app.superset.sh. Sidebars run full-height, the middle column owns its own tabs row, and surfaces use v2 tokens (bg-card, bg-background, border-border) with brand-orange used only for active accents (workspace marker, active tab underline, working spinner). Edges are sharper (rounded-sm/md, flat rows in the sidebar), type sizes tightened, and the diff overlay uses Linear-style 2px left-borders matching `file-diff-tool`.
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughRestructure AppMockup to add a TabBar, remove the WindowChrome wrapper, and reorganize into LeftSidebar | (TabBar + MainPanel) | RightSidebar; parameterize WindowChrome, refactor sidebars/panels, restyle ExternalIdePopup, and update file/workspace/diff UI and status styles. ChangesAppMockup Component System Redesign
🎯 4 (Complex) | ⏱️ ~45 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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 |
Greptile SummaryThis PR redesigns the marketing hero
Confidence Score: 3/5Two of the four demo states display the wrong branch name in the right sidebar, a visible defect on the marketing homepage. The branch name bug in RightSidebar is directly observable by any visitor who clicks "Create Parallel Branches" or "Open in Any IDE": the branch pill shows use-any-agents for both. The correct TITLE_BY_DEMO mapping was written in this PR but landed inside the now-unused WindowChrome component instead of being shared. The rest of the redesign is solid. RightSidebar.tsx (branch pill ternary) and WindowChrome.tsx (dead code containing the mapping that would fix it).
|
| Filename | Overview |
|---|---|
| apps/marketing/src/app/components/HeroSection/components/AppMockup/components/WindowChrome/WindowChrome.tsx | Substantially refactored with new activeDemo prop and TITLE_BY_DEMO mapping, but AppMockup.tsx no longer imports or renders it — all new code is dead. |
| apps/marketing/src/app/components/HeroSection/components/AppMockup/components/TabBar/TabBar.tsx | New component extracted from MainPanel; correctly handles animated agent tabs, Open/Run buttons, and active tab underline. |
| apps/marketing/src/app/components/HeroSection/components/AppMockup/components/RightSidebar/RightSidebar.tsx | Branch pill uses a binary isDiff ternary that shows "use-any-agents" for Create Parallel Branches and Open in Any IDE demos. Two absolute panels share a hardcoded top-[108px] offset. |
| apps/marketing/src/app/components/HeroSection/components/AppMockup/components/LeftSidebar/LeftSidebar.tsx | Redesigned with new NavRow and GroupHeader helpers; all logic preserved correctly. |
| apps/marketing/src/app/components/HeroSection/components/AppMockup/components/MainPanel/MainPanel.tsx | Tab bar rows removed (now in TabBar); tightened with v2 tokens. No functional regressions. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
AM[AppMockup] --> LS[LeftSidebar]
AM --> MC[middle column div]
AM --> RS[RightSidebar]
AM --> EI[ExternalIdePopup]
MC --> TB[TabBar NEW]
MC --> MP[MainPanel]
RS -->|branch pill| BP{isDiff?}
BP -->|yes - See Changes| SC[see-changes]
BP -->|no| UA[use-any-agents WRONG for 2 demos]
WC[WindowChrome DEAD CODE] -.->|never rendered| X
style WC fill:#f88,stroke:#c00
style UA fill:#fda,stroke:#c80
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 3
apps/marketing/src/app/components/HeroSection/components/AppMockup/components/RightSidebar/RightSidebar.tsx:62-64
**Branch name wrong for two demos**
The ternary only distinguishes `isDiff` ("See Changes") from everything else, falling back to `"use-any-agents"`. Visitors who click "Create Parallel Branches" or "Open in Any IDE" will see `use-any-agents` in the branch pill instead of the correct branch for that demo. The full per-demo mapping already exists in the (now-unused) `WindowChrome.tsx` and could be reused here to fix all four cases.
### Issue 2 of 3
apps/marketing/src/app/components/HeroSection/components/AppMockup/components/WindowChrome/WindowChrome.tsx:1-58
**`WindowChrome` is now dead code**
`AppMockup.tsx` no longer imports or renders `WindowChrome` — it was replaced wholesale by `TabBar`. Yet this PR adds ~40 lines of new logic to `WindowChrome` (an `activeDemo` prop, a full `TITLE_BY_DEMO` mapping, an "Open" button). None of that code is ever executed. The `TITLE_BY_DEMO` map would actually be the right fix for the branch-name issue in `RightSidebar`, but it currently lives inside an unreachable component.
### Issue 3 of 3
apps/marketing/src/app/components/HeroSection/components/AppMockup/components/RightSidebar/RightSidebar.tsx:79-101
**Magic pixel offset couples two independent layout sections**
`top-[108px]` is repeated on both absolute panels and silently encodes the combined height of the three header rows above them (h-9 + h-8 + the branch-summary block). If any of those rows ever changes height — even by adding a single line of text to the branch summary — the file list and diff panels will overlap or leave a gap. Using a sticky/flex approach or a CSS variable would make the relationship explicit.
Reviews (1): Last reviewed commit: "style(marketing): redesign hero AppMocku..." | Re-trigger Greptile
| <span className="truncate font-medium text-foreground/95"> | ||
| {isDiff ? "see-changes" : "use-any-agents"} | ||
| </span> |
There was a problem hiding this comment.
Branch name wrong for two demos
The ternary only distinguishes isDiff ("See Changes") from everything else, falling back to "use-any-agents". Visitors who click "Create Parallel Branches" or "Open in Any IDE" will see use-any-agents in the branch pill instead of the correct branch for that demo. The full per-demo mapping already exists in the (now-unused) WindowChrome.tsx and could be reused here to fix all four cases.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/marketing/src/app/components/HeroSection/components/AppMockup/components/RightSidebar/RightSidebar.tsx
Line: 62-64
Comment:
**Branch name wrong for two demos**
The ternary only distinguishes `isDiff` ("See Changes") from everything else, falling back to `"use-any-agents"`. Visitors who click "Create Parallel Branches" or "Open in Any IDE" will see `use-any-agents` in the branch pill instead of the correct branch for that demo. The full per-demo mapping already exists in the (now-unused) `WindowChrome.tsx` and could be reused here to fix all four cases.
How can I resolve this? If you propose a fix, please make it concise.| "use client"; | ||
|
|
||
| export function WindowChrome() { | ||
| import { LuChevronDown, LuExternalLink, LuX } from "react-icons/lu"; | ||
| import type { ActiveDemo } from "../../types"; | ||
|
|
||
| interface WindowChromeProps { | ||
| activeDemo?: ActiveDemo; | ||
| } | ||
|
|
||
| const TITLE_BY_DEMO: Record<ActiveDemo, { title: string; branch: string }> = { | ||
| "Use Any Agents": { | ||
| title: "use any agents in parallel", | ||
| branch: "use-any-agents", | ||
| }, | ||
| "Create Parallel Branches": { | ||
| title: "set up parallel branches", | ||
| branch: "create-parallel-branches", | ||
| }, | ||
| "See Changes": { | ||
| title: "review cloud-workspace diff", | ||
| branch: "see-changes", | ||
| }, | ||
| "Open in Any IDE": { | ||
| title: "edit in any IDE", | ||
| branch: "open-in-any-ide", | ||
| }, | ||
| }; | ||
|
|
||
| export function WindowChrome({ | ||
| activeDemo = "Use Any Agents", | ||
| }: WindowChromeProps) { | ||
| const { title, branch } = TITLE_BY_DEMO[activeDemo]; | ||
| return ( | ||
| <div className="flex items-center justify-between border-b border-white/[0.06] bg-white/[0.03] px-5 py-3.5 backdrop-blur-md"> | ||
| <div className="flex items-center gap-1.5"> | ||
| <div className="h-3 w-3 rounded-full bg-[#ff5f57]" /> | ||
| <div className="h-3 w-3 rounded-full bg-[#febc2e]" /> | ||
| <div className="h-3 w-3 rounded-full bg-[#28c840]" /> | ||
| <div className="flex h-9 items-center gap-2 border-b border-border bg-background px-3"> | ||
| <div className="flex min-w-0 flex-1 items-center gap-1"> | ||
| <span className="flex h-6 items-center gap-1.5 truncate border border-border bg-background px-2 text-[11px] font-medium text-foreground/90"> | ||
| <span className="truncate">{title}</span> | ||
| </span> | ||
| <span className="flex h-6 items-center gap-1.5 border border-border bg-background px-2 font-mono text-[10px] text-muted-foreground/80"> | ||
| <span className="size-1.5 rounded-full bg-brand" /> | ||
| <span className="truncate">{branch}</span> | ||
| <LuX className="size-2.5 text-muted-foreground/40" /> | ||
| </span> | ||
| </div> | ||
|
|
||
| <div className="ml-2 flex items-center gap-2"> | ||
| <button | ||
| type="button" | ||
| className="flex h-6 items-center gap-1 border border-border bg-background px-2 text-[10px] font-medium uppercase tracking-[0.06em] text-foreground/85 hover:bg-foreground/[0.04]" | ||
| > | ||
| <LuExternalLink className="size-2.5 text-muted-foreground/65" /> | ||
| <span>Open</span> | ||
| <LuChevronDown className="size-2.5 text-muted-foreground/55" /> | ||
| </button> | ||
| </div> | ||
| <span className="text-[12px] font-medium text-muted-foreground/55"> | ||
| superset | ||
| </span> | ||
| <div className="w-12" /> | ||
| </div> | ||
| ); | ||
| } |
There was a problem hiding this comment.
AppMockup.tsx no longer imports or renders WindowChrome — it was replaced wholesale by TabBar. Yet this PR adds ~40 lines of new logic to WindowChrome (an activeDemo prop, a full TITLE_BY_DEMO mapping, an "Open" button). None of that code is ever executed. The TITLE_BY_DEMO map would actually be the right fix for the branch-name issue in RightSidebar, but it currently lives inside an unreachable component.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/marketing/src/app/components/HeroSection/components/AppMockup/components/WindowChrome/WindowChrome.tsx
Line: 1-58
Comment:
**`WindowChrome` is now dead code**
`AppMockup.tsx` no longer imports or renders `WindowChrome` — it was replaced wholesale by `TabBar`. Yet this PR adds ~40 lines of new logic to `WindowChrome` (an `activeDemo` prop, a full `TITLE_BY_DEMO` mapping, an "Open" button). None of that code is ever executed. The `TITLE_BY_DEMO` map would actually be the right fix for the branch-name issue in `RightSidebar`, but it currently lives inside an unreachable component.
How can I resolve this? If you propose a fix, please make it concise.| @@ -73,100 +94,64 @@ export function RightSidebar({ activeDemo }: RightSidebarProps) { | |||
| type={file.type} | |||
| /> | |||
| ))} | |||
| </motion.div> | |||
| </div> | |||
| </motion.div> | |||
|
|
|||
| <motion.div | |||
| className="absolute inset-0 flex flex-col bg-black/30 backdrop-blur-md" | |||
| className="absolute inset-x-0 bottom-0 top-[108px] flex flex-col bg-card" | |||
There was a problem hiding this comment.
Magic pixel offset couples two independent layout sections
top-[108px] is repeated on both absolute panels and silently encodes the combined height of the three header rows above them (h-9 + h-8 + the branch-summary block). If any of those rows ever changes height — even by adding a single line of text to the branch summary — the file list and diff panels will overlap or leave a gap. Using a sticky/flex approach or a CSS variable would make the relationship explicit.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/marketing/src/app/components/HeroSection/components/AppMockup/components/RightSidebar/RightSidebar.tsx
Line: 79-101
Comment:
**Magic pixel offset couples two independent layout sections**
`top-[108px]` is repeated on both absolute panels and silently encodes the combined height of the three header rows above them (h-9 + h-8 + the branch-summary block). If any of those rows ever changes height — even by adding a single line of text to the branch summary — the file list and diff panels will overlap or leave a gap. Using a sticky/flex approach or a CSS variable would make the relationship explicit.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/marketing/src/app/components/HeroSection/components/AppMockup/components/RightSidebar/RightSidebar.tsx (1)
164-200: ⚡ Quick winConsider using a className utility for DiffLine.
The string concatenation for
classNameworks but could be more maintainable using a utility likeclsxorcn(commonly used in Next.js projects).♻️ Alternative implementation with cn utility
function DiffLine({ n, added, removed, children, }: { n?: number; added?: boolean; removed?: boolean; children?: React.ReactNode; }) { - let bg = ""; - let bar = "border-transparent"; - let prefix = ""; - let textColor = "text-muted-foreground/75"; - - if (added) { - bg = "bg-emerald-500/[0.08]"; - bar = "border-emerald-500/85"; - prefix = "+"; - textColor = "text-emerald-300/95"; - } else if (removed) { - bg = "bg-rose-500/[0.08]"; - bar = "border-rose-500/85"; - prefix = "−"; - textColor = "text-rose-300/95"; - } + const prefix = added ? "+" : removed ? "−" : ""; return ( - <div className={`flex border-l-2 ${bar} ${bg}`}> + <div className={cn( + "flex border-l-2", + added && "border-emerald-500/85 bg-emerald-500/[0.08]", + removed && "border-rose-500/85 bg-rose-500/[0.08]", + !added && !removed && "border-transparent" + )}> <span className="w-6 shrink-0 pr-2 text-right tabular-nums text-muted-foreground/40"> {prefix || n} </span> - <span className={textColor}>{children}</span> + <span className={cn( + added && "text-emerald-300/95", + removed && "text-rose-300/95", + !added && !removed && "text-muted-foreground/75" + )}>{children}</span> </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 `@apps/marketing/src/app/components/HeroSection/components/AppMockup/components/RightSidebar/RightSidebar.tsx` around lines 164 - 200, The DiffLine component builds className strings via template concatenation which is hard to maintain; update DiffLine to use the project's className utility (e.g., cn or clsx) to compose classes for the container div and the text span instead of manual string interpolation. Locate the DiffLine function and replace the backtick template for the container (<div className={`flex border-l-2 ${bar} ${bg}`}> ) and the text span ( <span className={textColor}> ) with cn(...) calls that combine static classes and the computed variables (bar, bg, textColor) to improve readability and avoid accidental spacing bugs. Ensure you import the utility at the top of the file and keep the existing logic for setting bar/bg/prefix/textColor unchanged.
🤖 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
`@apps/marketing/src/app/components/HeroSection/components/AppMockup/components/ExternalIdePopup/ExternalIdePopup.tsx`:
- Around line 15-23: The popup's motion.div (the ExternalIdePopup container)
only animates visuals so it still blocks/receives pointer events when inactive;
update the element to conditionally gate pointer events and accessibility: add a
style or class that sets pointerEvents: activeDemo === "Open in Any IDE" ?
"auto" : "none" (or tailwind classes like pointer-events-none /
pointer-events-auto based on activeDemo) and set aria-hidden={activeDemo !==
"Open in Any IDE"} on the same motion.div so non-active demos neither intercept
clicks nor expose the hidden popup to assistive tech; keep the existing
animate/initial props unchanged.
---
Nitpick comments:
In
`@apps/marketing/src/app/components/HeroSection/components/AppMockup/components/RightSidebar/RightSidebar.tsx`:
- Around line 164-200: The DiffLine component builds className strings via
template concatenation which is hard to maintain; update DiffLine to use the
project's className utility (e.g., cn or clsx) to compose classes for the
container div and the text span instead of manual string interpolation. Locate
the DiffLine function and replace the backtick template for the container (<div
className={`flex border-l-2 ${bar} ${bg}`}> ) and the text span ( <span
className={textColor}> ) with cn(...) calls that combine static classes and the
computed variables (bar, bg, textColor) to improve readability and avoid
accidental spacing bugs. Ensure you import the utility at the top of the file
and keep the existing logic for setting bar/bg/prefix/textColor unchanged.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 352ceb43-5401-4e90-a31f-2b2083672636
📒 Files selected for processing (12)
apps/marketing/src/app/components/HeroSection/components/AppMockup/AppMockup.tsxapps/marketing/src/app/components/HeroSection/components/AppMockup/components/ExternalIdePopup/ExternalIdePopup.tsxapps/marketing/src/app/components/HeroSection/components/AppMockup/components/FileChangeItem/FileChangeItem.tsxapps/marketing/src/app/components/HeroSection/components/AppMockup/components/LeftSidebar/LeftSidebar.tsxapps/marketing/src/app/components/HeroSection/components/AppMockup/components/MainPanel/MainPanel.tsxapps/marketing/src/app/components/HeroSection/components/AppMockup/components/RightSidebar/RightSidebar.tsxapps/marketing/src/app/components/HeroSection/components/AppMockup/components/StatusIndicator/StatusIndicator.tsxapps/marketing/src/app/components/HeroSection/components/AppMockup/components/TabBar/TabBar.tsxapps/marketing/src/app/components/HeroSection/components/AppMockup/components/TabBar/index.tsapps/marketing/src/app/components/HeroSection/components/AppMockup/components/WindowChrome/WindowChrome.tsxapps/marketing/src/app/components/HeroSection/components/AppMockup/components/WorkspaceItem/WorkspaceItem.tsxapps/marketing/src/app/components/HeroSection/components/AppMockup/constants.ts
💤 Files with no reviewable changes (1)
- apps/marketing/src/app/components/HeroSection/components/AppMockup/constants.ts
🚀 Preview Deployment🔗 Preview Links
Preview updates automatically with new commits |
There was a problem hiding this comment.
2 issues found across 12 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/marketing/src/app/components/HeroSection/components/AppMockup/components/RightSidebar/RightSidebar.tsx">
<violation number="1" location="apps/marketing/src/app/components/HeroSection/components/AppMockup/components/RightSidebar/RightSidebar.tsx:63">
P2: Map the branch label from `activeDemo` instead of a two-case ternary so each demo shows the correct branch name.</violation>
</file>
<file name="apps/marketing/src/app/components/HeroSection/components/AppMockup/components/WindowChrome/WindowChrome.tsx">
<violation number="1" location="apps/marketing/src/app/components/HeroSection/components/AppMockup/components/WindowChrome/WindowChrome.tsx:10">
P3: `WindowChrome` is not rendered by `AppMockup`, so the new `TITLE_BY_DEMO` branch/title logic here is unreachable and can drift from the live UI.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| activeDemo?: ActiveDemo; | ||
| } | ||
|
|
||
| const TITLE_BY_DEMO: Record<ActiveDemo, { title: string; branch: string }> = { |
There was a problem hiding this comment.
P3: WindowChrome is not rendered by AppMockup, so the new TITLE_BY_DEMO branch/title logic here is unreachable and can drift from the live UI.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/marketing/src/app/components/HeroSection/components/AppMockup/components/WindowChrome/WindowChrome.tsx, line 10:
<comment>`WindowChrome` is not rendered by `AppMockup`, so the new `TITLE_BY_DEMO` branch/title logic here is unreachable and can drift from the live UI.</comment>
<file context>
@@ -1,17 +1,58 @@
+ activeDemo?: ActiveDemo;
+}
+
+const TITLE_BY_DEMO: Record<ActiveDemo, { title: string; branch: string }> = {
+ "Use Any Agents": {
+ title: "use any agents in parallel",
</file context>
…eview - AGENT_TABS: codex, cursor, opencode, copilot (white), amp, gemini - WorkspaceItem: TbCloud icon for "see changes", LuGitBranch for "forward ports" - RightSidebar: rename third tab from "Notes" to "Review"
…e IDE popup Addresses PR review feedback: - RightSidebar: introduce BRANCH_BY_DEMO so each of the 4 demos shows its real branch (was hardcoded to "use-any-agents" for everything except "See Changes") - RightSidebar: replace `top-[108px]` absolute offset with a flex-1 relative container so the two motion panels no longer break if a header row changes height - ExternalIdePopup: gate pointerEvents on activeDemo so the hidden popup doesn't intercept clicks on the right sidebar underneath WindowChrome is left in place even though AppMockup no longer renders it; keeping it around as reference dead code is intentional.
Summary
apps/marketing/.../AppMockup) to mirror the v2 desktop UI: full-height sidebars with the middle column owning its own tabs + Open/Run rowbg-card,bg-background,border-border) and uses brand-orange surgically (active workspace bar, active tab underline, working spinner)Notable changes
Workspaces / Automations / New Workspacenav rows → workspace groups (desktop,cloud,mobile,cli) with nested tasks → Ports section at bottom+button; right side hasOpen ⌄and a green▶ RunbuttonFiles / Changes / Notestabs → branch summary with stats → file list (or diff overlay for the "See Changes" demo)Test plan
/on marketing app at http://localhost:4402bun run lintandbun run typecheckare clean (they were when I pushed)min-w-[700px]and scrolls horizontally)Summary by cubic
Redesigned the marketing hero AppMockup to match the v2 desktop UI. Adds a new
TabBar, v2 tokens (bg-card,bg-background,border-border), and sharper diff/IDE demos with Linear-style accents and correct per‑demo branch labels.Refactors
WindowChrome.Files / Changes / Reviewtabs, branch summary + stats, and a diff overlay with 2px left borders; uses flex layout (no magic offsets).New Features
TabBarwith animated agent tabs and a 2px active underline; expanded agents to include codex, cursor, opencode, copilot, amp, and gemini.Written for commit bba2ffd. Summary will update on new commits.
Summary by CodeRabbit
New Features
Style
Chores