refactor(layout): promote AI capture above timeline on desktop
Give the composer full-width desktop space before the event timeline so capture stays prominent and the toolbar can keep its intended two-column composition. Add source-level regression tests to lock the new page hierarchy in place.
This commit is contained in:
@@ -436,10 +436,8 @@ export default function HomePage() {
|
|||||||
);
|
);
|
||||||
const appSectionSurfaceClasses = getAppSectionSurfaceClasses(isMobile);
|
const appSectionSurfaceClasses = getAppSectionSurfaceClasses(isMobile);
|
||||||
const appNavSurfaceClasses = getAppNavSurfaceClasses(isMobile);
|
const appNavSurfaceClasses = getAppNavSurfaceClasses(isMobile);
|
||||||
const mainContentClasses = cn(
|
const mainContentClasses = "space-y-4";
|
||||||
"grid items-start gap-4",
|
const timelineContentClasses = "space-y-4";
|
||||||
isMobile ? "grid-cols-1" : "grid-cols-[minmax(0,0.75fr)_minmax(0,1.25fr)]",
|
|
||||||
);
|
|
||||||
const headerActionsClasses = isMobile
|
const headerActionsClasses = isMobile
|
||||||
? "flex w-full items-center justify-between gap-2"
|
? "flex w-full items-center justify-between gap-2"
|
||||||
: "flex flex-wrap items-center justify-end gap-2";
|
: "flex flex-wrap items-center justify-end gap-2";
|
||||||
@@ -552,7 +550,6 @@ export default function HomePage() {
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<section className={mainContentClasses}>
|
<section className={mainContentClasses}>
|
||||||
<div className="space-y-4">
|
|
||||||
<section className={appSectionSurfaceClasses}>
|
<section className={appSectionSurfaceClasses}>
|
||||||
<div className="mb-4 space-y-1">
|
<div className="mb-4 space-y-1">
|
||||||
<p className="text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
|
<p className="text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
|
||||||
@@ -562,8 +559,8 @@ export default function HomePage() {
|
|||||||
Capture from text or files.
|
Capture from text or files.
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-sm leading-6 text-muted-foreground">
|
<p className="text-sm leading-6 text-muted-foreground">
|
||||||
Start with a prompt, screenshots, or both. Review happens
|
Start with a prompt, screenshots, or both. Review happens in
|
||||||
in the timeline rather than a separate flow.
|
the timeline rather than a separate flow.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -587,9 +584,8 @@ export default function HomePage() {
|
|||||||
events={events}
|
events={events}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-4">
|
<section className={timelineContentClasses}>
|
||||||
<section className={appSectionSurfaceClasses}>
|
<section className={appSectionSurfaceClasses}>
|
||||||
<div className="mb-4 flex items-center justify-between gap-3">
|
<div className="mb-4 flex items-center justify-between gap-3">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
@@ -634,7 +630,7 @@ export default function HomePage() {
|
|||||||
onDelete={handleDelete}
|
onDelete={handleDelete}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -166,6 +166,14 @@ describe("AI capture redesign", () => {
|
|||||||
expect(source).not.toContain("lg:grid-cols-");
|
expect(source).not.toContain("lg:grid-cols-");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("desktop composer uses a two-column row when the page gives it full-width space", () => {
|
||||||
|
const source = readToolbarSource();
|
||||||
|
|
||||||
|
expect(source).toContain("isMobile");
|
||||||
|
expect(source).toContain('? "grid gap-3"');
|
||||||
|
expect(source).toContain(': "grid gap-3 grid-cols-[minmax(0,1fr)_minmax(0,1fr)]"');
|
||||||
|
});
|
||||||
|
|
||||||
test("attachments panel is a first-class surfaced region, not an inline footer affordance", () => {
|
test("attachments panel is a first-class surfaced region, not an inline footer affordance", () => {
|
||||||
const source = readToolbarSource();
|
const source = readToolbarSource();
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,22 @@ describe("home page hierarchy", () => {
|
|||||||
const source = readFileSync("src/app/page.tsx", "utf8");
|
const source = readFileSync("src/app/page.tsx", "utf8");
|
||||||
|
|
||||||
expect(source).toContain("useIsMobile");
|
expect(source).toContain("useIsMobile");
|
||||||
expect(source).toContain("grid-cols-[minmax(0,0.75fr)_minmax(0,1.25fr)]");
|
expect(source).toContain('const mainContentClasses = "space-y-4"');
|
||||||
|
expect(source).toContain('const timelineContentClasses = "space-y-4"');
|
||||||
expect(source).toContain('"items-center justify-between"');
|
expect(source).toContain('"items-center justify-between"');
|
||||||
expect(source).toContain("desktopUtilityActionsClasses");
|
expect(source).toContain("desktopUtilityActionsClasses");
|
||||||
expect(source).toContain("AI capture");
|
expect(source).toContain("AI capture");
|
||||||
expect(source).toContain("Event timeline");
|
expect(source).toContain("Event timeline");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("desktop layout promotes AI capture to a full-width top row before the timeline grid", () => {
|
||||||
|
const source = readFileSync("src/app/page.tsx", "utf8");
|
||||||
|
|
||||||
|
expect(source).toContain("<section className={appSectionSurfaceClasses}>");
|
||||||
|
expect(source).toContain("<section className={timelineContentClasses}>");
|
||||||
|
expect(source).not.toContain("grid-cols-[minmax(0,0.75fr)_minmax(0,1.25fr)]");
|
||||||
|
});
|
||||||
|
|
||||||
test("manual create is routed through a More menu instead of a primary mobile action", () => {
|
test("manual create is routed through a More menu instead of a primary mobile action", () => {
|
||||||
const source = readFileSync("src/app/page.tsx", "utf8");
|
const source = readFileSync("src/app/page.tsx", "utf8");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user