diff --git a/packages/website/src/components/landing-page.tsx b/packages/website/src/components/landing-page.tsx index 9443c4f6c7..2c1c5094a6 100644 --- a/packages/website/src/components/landing-page.tsx +++ b/packages/website/src/components/landing-page.tsx @@ -1238,7 +1238,7 @@ function PhoneShowcase() { role="img" aria-label="Paseo workspace drawer" > - + @@ -1264,7 +1264,7 @@ function PhoneShowcase() { role="img" aria-label="Paseo diff view" > - + diff --git a/packages/website/src/components/mockup/mobile/chat.tsx b/packages/website/src/components/mockup/mobile/chat.tsx index 618b61d2e2..4d3ac156fd 100644 --- a/packages/website/src/components/mockup/mobile/chat.tsx +++ b/packages/website/src/components/mockup/mobile/chat.tsx @@ -128,9 +128,11 @@ function Composer() { Message, @files, /commands
- - GPT-5.6-Sol - Medium + + + GPT-5.6-Sol + Medium + diff --git a/packages/website/src/components/mockup/mobile/diff.tsx b/packages/website/src/components/mockup/mobile/diff.tsx index 616e44c8de..4cffe0a813 100644 --- a/packages/website/src/components/mockup/mobile/diff.tsx +++ b/packages/website/src/components/mockup/mobile/diff.tsx @@ -4,57 +4,89 @@ // an addition, so the whole gutter runs green). Reuses the shared `Code` // highlighter and the `--color-mock-diff-*` tokens. -import { ChevronDown, GitBranch, MoreHorizontal, RefreshCw, SquarePlus, X } from "lucide-react"; +import { + ChevronDown, + FileDiff, + Files, + GitBranch, + GitPullRequest, + MoreHorizontal, + RefreshCw, + SquareDot, + X, +} from "lucide-react"; import { Code } from "../atoms"; import { ReactFileIcon } from "../icons"; -// Every visible line of the new atoms.tsx — all additions. Long lines are -// clipped by the phone width exactly as they are in the app. -const ADDED_LINES: { n: number; text: string }[] = [ - { n: 1, text: "// Shared bits of the Paseo UI, drawn small. Every" }, - { n: 2, text: "// no state, no interactivity. Colors come from th" }, - { n: 3, text: "// styles.css, which are copied from the app's def" }, - { n: 4, text: "" }, - { n: 5, text: 'import type * as React from "react";' }, - { n: 6, text: "" }, - { n: 7, text: "/**" }, - { n: 8, text: " * The `+12 −18` footnote. A diff stat is a *statu" }, - { n: 9, text: " * uses statusSuccess/statusDanger — see the comme" }, - { n: 10, text: " * packages/app/src/styles/theme.ts." }, - { n: 11, text: " */" }, - { n: 12, text: "export function DiffStat({ add, remove }: { add: st" }, - { n: 13, text: " return (" }, - { n: 14, text: ' +{add}-{remove}<' }, - { n: 17, text: " " }, - { n: 18, text: " );" }, - { n: 19, text: "}" }, - { n: 20, text: "" }, - { n: 21, text: 'export type DotTone = "success" | "danger" | "warni' }, - { n: 22, text: "" }, - { n: 23, text: "const DOT_TONE: Record = {" }, - { n: 24, text: ' success: "bg-mock-dot-success",' }, - { n: 25, text: ' danger: "bg-mock-dot-danger",' }, - { n: 26, text: ' warning: "bg-mock-dot-warning",' }, - { n: 27, text: ' running: "bg-mock-dot-running",' }, - { n: 28, text: ' idle: "bg-mock-surface3",' }, - { n: 29, text: "};" }, - { n: 30, text: "" }, - { n: 31, text: "/** The 6pt disc on a sidebar row that carries the" }, - { n: 32, text: "export function StatusDot({ tone }: { tone: DotTone" }, - { n: 33, text: " return = { + add: "bg-mock-diff-add", + remove: "bg-mock-diff-remove", + context: "", +}; + +const NUMBER_COLOR: Record = { + add: "text-mock-success", + remove: "text-mock-danger", + context: "text-mock-fg-muted", +}; + +const DIFF_LINES: MobileDiffLine[] = [ + { n: 7, text: 'type DotTone = "success" | "danger" | "idle";', mark: "remove" }, + { n: 7, text: "export type DotTone =", mark: "add" }, + { n: 8, text: ' | "success"', mark: "add" }, + { n: 9, text: ' | "danger"', mark: "add" }, + { n: 10, text: ' | "warning"', mark: "add" }, + { n: 11, text: ' | "running"', mark: "add" }, + { n: 12, text: ' | "idle";', mark: "add" }, + { n: 13, text: "", mark: "context" }, + { n: 14, text: "interface DiffStatProps {", mark: "context" }, + { n: 15, text: " add: string;", mark: "context" }, + { n: 16, text: " remove: string;", mark: "context" }, + { n: 17, text: "}", mark: "context" }, + { n: 18, text: "", mark: "context" }, + { n: 19, text: "/** Compact diff summary. */", mark: "add" }, + { n: 20, text: "export function DiffStat({", mark: "add" }, + { n: 21, text: " add,", mark: "add" }, + { n: 22, text: " remove,", mark: "add" }, + { n: 23, text: "}: DiffStatProps) {", mark: "add" }, + { n: 24, text: " return (", mark: "context" }, + { n: 25, text: ' ', mark: "remove" }, + { n: 25, text: ' ', mark: "add" }, + { n: 26, text: ' ', mark: "context" }, + { n: 27, text: " +{add}", mark: "context" }, + { n: 28, text: " ", mark: "context" }, + { n: 29, text: ' ', mark: "context" }, + { n: 30, text: " -{remove}", mark: "context" }, + { n: 31, text: " ", mark: "context" }, + { n: 32, text: " ", mark: "context" }, + { n: 33, text: " )", mark: "remove" }, + { n: 33, text: " );", mark: "add" }, + { n: 34, text: "}", mark: "context" }, ]; function Tabs() { return ( -
-
- - Changes - - Files -
+
+ + + Files + + + + Changes + + + + 3981 +
@@ -106,25 +138,26 @@ function FileHeader() { packages/website/src/componen… - +175 - -0 + +56 + -18 - +
); } -function DiffLine({ n, text }: { n: number; text: string }) { +function DiffLine({ n, text, mark }: MobileDiffLine) { + const comment = text.trimStart().startsWith("/") || text.trimStart().startsWith("*"); return ( -
+
{n} - + {comment ? {text} : }
); @@ -151,11 +184,11 @@ export function MobileDiff() {
- @@ -0,0 +1,175 @@ + @@ -7,20 +7,28 @@
- {ADDED_LINES.map((line) => ( - + {DIFF_LINES.map((line) => ( + ))}
diff --git a/packages/website/src/components/mockup/mobile/frame.tsx b/packages/website/src/components/mockup/mobile/frame.tsx index 9e6ffac08c..a4ccd4f07d 100644 --- a/packages/website/src/components/mockup/mobile/frame.tsx +++ b/packages/website/src/components/mockup/mobile/frame.tsx @@ -15,6 +15,21 @@ const SCREEN_SCALE = { height: PHONE_H, transform: `scale(tan(atan2(100cqw, ${PHONE_W}px)))`, }; +type PhoneDepth = "front" | "left" | "right"; + +const SLAB_STYLE: Record, React.CSSProperties> = { + left: { transform: "translate3d(-5px, 0, -8px)" }, + right: { transform: "translate3d(5px, 0, -8px)" }, +}; +const CONTACT_SHADOW_STYLE: Record = { + front: { transform: "translate3d(0, 4px, -12px)" }, + left: { transform: "translate3d(-2px, 3px, -12px)" }, + right: { transform: "translate3d(2px, 3px, -12px)" }, +}; +const GLASS_STYLE = { + background: + "linear-gradient(122deg, rgba(255,255,255,0.048) 0%, rgba(255,255,255,0.016) 25%, transparent 43%), radial-gradient(circle at 78% 10%, rgba(255,255,255,0.026), transparent 31%)", +}; /** iOS status bar: time, dynamic island, and the signal/wifi/battery cluster. */ function StatusBar({ time }: { time: string }) { @@ -71,20 +86,54 @@ function HomeIndicator() { ); } -export function PhoneFrame({ time, children }: { time: string; children: React.ReactNode }) { +function FrontButtons() { return ( -
-
-
-
- -
{children}
- + <> + + + + + ); +} + +export function PhoneFrame({ + time, + children, + depth = "front", +}: { + time: string; + children: React.ReactNode; + depth?: PhoneDepth; +}) { + return ( +
+
+ + {depth === "front" ? ( + + ) : ( +
+ )} + +
+
+
+
+ +
+ {children} +
+ +
+
); diff --git a/packages/website/src/components/mockup/sidebar.tsx b/packages/website/src/components/mockup/sidebar.tsx index 80de5d10df..2e15b2f110 100644 --- a/packages/website/src/components/mockup/sidebar.tsx +++ b/packages/website/src/components/mockup/sidebar.tsx @@ -267,13 +267,15 @@ export function Sidebar({ state }: { state: MockupStateId }) { return (
{/* The sidebar is one full-height column with no header border of its own. */} -
-
+
+
- + + +
@@ -334,5 +336,5 @@ export function Sidebar({ state }: { state: MockupStateId }) { } function PanelLeftGlyph() { - return ; + return ; } diff --git a/packages/website/src/components/mockup/window.tsx b/packages/website/src/components/mockup/window.tsx index 8d72ce169d..565d92e5ff 100644 --- a/packages/website/src/components/mockup/window.tsx +++ b/packages/website/src/components/mockup/window.tsx @@ -101,7 +101,7 @@ export function MockupWindow({ state }: { state: MockupStateId }) { return (
{/* Three full-height columns, each owning its own header. The middle