Skip to content

Commit e03f9f4

Browse files
megany128claude
andcommitted
wip: dashboard home layout + sample data
Remove broken feed Toggle, move SearchBar into feed header, swap hardcoded Landing hex for secondary-500 token, add Manrope to font link. Wire RoutedHome with client-side sample posts / side panels (Convex schema has no post table yet). New playwright helper for /home screenshots. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 26b883d commit e03f9f4

6 files changed

Lines changed: 189 additions & 48 deletions

File tree

apps/dashboard/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
<link rel="preconnect" href="https://fonts.googleapis.com" />
1010
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
11-
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;0,9..40,800;0,9..40,900&family=Inter:wght@400;500;700&display=swap" rel="stylesheet" />
11+
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;0,9..40,800;0,9..40,900&family=Inter:wght@400;500;700&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
1212
</head>
1313
<body>
1414
<div id="root"></div>

apps/dashboard/src/App.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Org } from "./pages/Org";
1010
import { Profile } from "./pages/profile";
1111
import type { SideBarItemId } from "@app/ui";
1212
import DesignSystem from "./pages/DesignSystem";
13+
import { SAMPLE_POSTS, SAMPLE_SIDE_PANELS } from "./data/sampleHome";
1314

1415
/**
1516
* Maps a SideBar nav id to its route path.
@@ -53,6 +54,8 @@ function RoutedHome() {
5354
<Home
5455
activeNavItem="home"
5556
onNavigate={(id) => navigate(pathForNavItem(id))}
57+
posts={SAMPLE_POSTS}
58+
sidePanels={SAMPLE_SIDE_PANELS}
5659
/>
5760
);
5861
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/**
2+
* Sample data for /home preview.
3+
*
4+
* Convex schema currently only carries auth tables
5+
* (apps/dashboard/convex/schema.ts), so posts/events are not persisted yet.
6+
* These constants let us preview the feed against the DashboardPost and
7+
* HomeSidePanel shapes exported from shared/ui and apps/dashboard/src/pages/Home.tsx.
8+
*
9+
* Content here is original placeholder copy (not taken from the Figma mockup).
10+
*/
11+
12+
import type { DashboardPostProps } from "@app/ui";
13+
import type { HomeSidePanelProps } from "../pages/Home";
14+
15+
export const SAMPLE_POSTS: DashboardPostProps[] = [
16+
{
17+
organizations: [{ name: "Cornell Outing Club" }],
18+
postedAt: "Apr 21",
19+
title: "Sunrise hike at Taughannock Falls",
20+
datetime: "April 27, 5:30am - 8:30am",
21+
location: "Taughannock Falls trailhead",
22+
description:
23+
"Start the weekend early with a guided sunrise hike along the gorge trail. We'll meet at the trailhead, watch the sun come up over the falls, and be back in time for brunch. All experience levels welcome — we'll keep the pace easygoing.",
24+
descriptionTruncated: true,
25+
tags: [
26+
{ label: "Outdoors" },
27+
{ label: "Just for Fun" },
28+
],
29+
},
30+
{
31+
organizations: [
32+
{ name: "WICC" },
33+
{ name: "CUAUV" },
34+
],
35+
postedAt: "Apr 20",
36+
title: "Spring industry mixer with alumni engineers",
37+
datetime: "April 29, 6:00pm - 8:00pm",
38+
location: "Duffield Hall Atrium",
39+
description:
40+
"Meet Cornell engineering alumni working at early-stage startups and mid-sized tech companies. Casual format — snacks, drinks, and roundtables grouped by discipline. Bring questions about the first two years of an engineering career.",
41+
descriptionTruncated: true,
42+
tags: [
43+
{ label: "You're free!", color: "blue" },
44+
{ label: "Early Career" },
45+
{ label: "Tech" },
46+
],
47+
},
48+
{
49+
organizations: [{ name: "Cornell Fintech Club" }],
50+
postedAt: "Apr 18",
51+
title: "Portfolio construction workshop",
52+
datetime: "April 24, 4:30pm - 6:00pm",
53+
location: "Statler Hall 265",
54+
description:
55+
"A hands-on session on building and rebalancing a long-only equity portfolio. No finance background required — we'll walk through the math and run through a paper-trading exercise together.",
56+
descriptionTruncated: true,
57+
tags: [
58+
{ label: "Mentorship" },
59+
{ label: "Finance" },
60+
],
61+
},
62+
{
63+
organizations: [{ name: "Big Red Robotics" }],
64+
postedAt: "Apr 15",
65+
title: "Open lab night: meet the team",
66+
datetime: "April 23, 7:00pm - 9:30pm",
67+
location: "Upson Hall B17",
68+
description:
69+
"Drop by the lab for a tour of our current build, chat with sub-team leads, and see live demos of the drivetrain and vision stack. Pizza while it lasts.",
70+
descriptionTruncated: true,
71+
tags: [
72+
{ label: "Recruitment" },
73+
{ label: "Tech" },
74+
],
75+
},
76+
];
77+
78+
export const SAMPLE_SIDE_PANELS: HomeSidePanelProps[] = [
79+
{
80+
title: "This week",
81+
items: [
82+
{
83+
title: "Sunrise hike at Taughannock",
84+
orgName: "Cornell Outing Club",
85+
isForYou: true,
86+
},
87+
{
88+
title: "Portfolio construction workshop",
89+
orgName: "Cornell Fintech Club",
90+
},
91+
{
92+
title: "Open lab night",
93+
orgName: "Big Red Robotics",
94+
hasIndicator: true,
95+
},
96+
],
97+
},
98+
{
99+
title: "Trending",
100+
items: [
101+
{
102+
title: "Spring industry mixer",
103+
orgName: "WICC",
104+
isForYou: true,
105+
hasIndicator: true,
106+
},
107+
{
108+
title: "Intro to quantum computing talk",
109+
orgName: "Cornell Physics Society",
110+
},
111+
{
112+
title: "Campus community cleanup",
113+
orgName: "Cornell Sustainability",
114+
isForYou: false,
115+
},
116+
],
117+
},
118+
];

apps/dashboard/src/pages/Home.tsx

Lines changed: 17 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import type { ComponentPropsWithoutRef } from "react";
2323
import { SideBar } from "@app/ui";
2424
import type { SideBarItemId } from "@app/ui";
25-
import { Toggle } from "@app/ui";
2625
import { Tag } from "@app/ui";
2726
import { SearchBar } from "@app/ui";
2827
import { DashboardPost } from "@app/ui";
@@ -49,8 +48,6 @@ const SECTION_TITLE =
4948

5049
// ─── Public types ─────────────────────────────────────────────────────────────
5150

52-
export type FeedTab = "for-you" | "following";
53-
5451
export interface FeedTagItem {
5552
/** Display label for the filter tag, e.g. "Recruitment". */
5653
label: string;
@@ -93,12 +90,6 @@ export interface HomeProps extends ComponentPropsWithoutRef<"div"> {
9390
/** Called with the nav item id when a sidebar tab is clicked. */
9491
onNavigate?: (id: SideBarItemId) => void;
9592

96-
// ── Feed toggle ──
97-
/** Active feed tab. Defaults to 'for-you'. */
98-
activeTab?: FeedTab;
99-
/** Called with the new tab value when the toggle changes. */
100-
onTabChange?: (tab: FeedTab) => void;
101-
10293
// ── Tag filter bar ──
10394
/**
10495
* List of tags shown in the horizontal filter bar.
@@ -339,8 +330,6 @@ function HomeSidePanel({ title, items, onShowMore }: HomeSidePanelProps) {
339330
export function Home({
340331
activeNavItem = "home",
341332
onNavigate,
342-
activeTab = "for-you",
343-
onTabChange,
344333
feedTags = DEFAULT_FEED_TAGS,
345334
onTagClick,
346335
onAddTag,
@@ -364,34 +353,25 @@ export function Home({
364353

365354
{/* ── Main feed ── */}
366355
<main
367-
className="flex-1 min-w-0 flex flex-col gap-[var(--space-6)] py-[var(--space-6)] overflow-y-auto"
356+
className="flex-1 min-w-0 flex flex-col gap-[var(--space-6)] py-[var(--space-6)] overflow-y-auto bg-[var(--color-surface-subtle)]"
368357
aria-label="Feed"
369358
>
370-
{/* ── Feed header: tab toggle + tag filter bar ── */}
371-
<div className="flex flex-col gap-[var(--space-6)] w-full shrink-0">
372-
{/*
373-
* Feed tab toggle — "For you" / "Following".
374-
* w-full stretches the toggle to fill the padded container.
375-
* Figma (node 263:3535): full-width pill container, px 24px.
376-
*/}
377-
<div className="px-[var(--space-6)]">
378-
<Toggle
379-
options={[
380-
{ value: "for-you", label: "For you" },
381-
{ value: "following", label: "Following" },
382-
]}
383-
value={activeTab}
384-
onChange={(v) => onTabChange?.(v as FeedTab)}
385-
className="w-full"
386-
/>
387-
</div>
388-
389-
{/*
390-
* Tag filter bar — horizontal scrollable row of neutral Tag chips.
391-
* Figma (node 263:3540): px 32px, gap 12px.
392-
* The final "+" tag triggers onAddTag to open a tag picker.
393-
*/}
394-
<div className="flex items-center gap-[var(--space-3)] px-[var(--space-8)] overflow-x-auto">
359+
{/* ── Feed header: search bar + tag filter bar ── */}
360+
{/*
361+
* Figma node 506:8718: SearchBar sits above the tag filter bar within
362+
* the main feed, gap 16px. Tags row is the category filter shown
363+
* beneath it; the "+" tag opens a picker.
364+
*/}
365+
<div className="flex flex-col gap-[var(--space-4)] w-full shrink-0 px-[var(--space-8)]">
366+
<SearchBar
367+
value={searchValue}
368+
onChange={onSearchChange}
369+
onClear={onSearchClear}
370+
placeholder="Search"
371+
className="w-full shrink-0"
372+
/>
373+
374+
<div className="flex items-center gap-[var(--space-3)] overflow-x-auto">
395375
{feedTags.map((tag) => (
396376
<Tag
397377
key={tag.label}
@@ -453,15 +433,6 @@ export function Home({
453433
].join(" ")}
454434
aria-label="Contextual panel"
455435
>
456-
{/* Search bar — Figma node 263:3692 */}
457-
<SearchBar
458-
value={searchValue}
459-
onChange={onSearchChange}
460-
onClear={onSearchClear}
461-
placeholder="Search"
462-
className="w-full shrink-0"
463-
/>
464-
465436
{/* Contextual event sections — "This week", "Trending", etc. */}
466437
{sidePanels.map((panel, i) => (
467438
<HomeSidePanel key={i} {...panel} />

apps/dashboard/src/pages/Landing.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ export default function Landing() {
243243
}, []);
244244

245245
return (
246-
<div className="relative min-h-screen overflow-x-hidden bg-[#5BA0DC]">
246+
<div className="relative min-h-screen overflow-x-hidden bg-[var(--color-secondary-500)]">
247247
{/* ── Background ─────────────────────────────────────────────── */}
248248
{/* Texture image tiled full-page height */}
249249
<img

scripts/home-shot.mjs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* /home screenshot for Figma alignment loop.
3+
* Usage: bun scripts/home-shot.mjs <iter>
4+
* Writes /tmp/home-iter-<iter>/full.png + header.png
5+
*/
6+
import { chromium } from 'playwright';
7+
import { mkdirSync } from 'node:fs';
8+
9+
const iter = process.argv[2] ?? '0';
10+
const outDir = `/tmp/home-iter-${iter}`;
11+
mkdirSync(outDir, { recursive: true });
12+
13+
const PORTS = [5173, 5174, 5175, 5176, 5177];
14+
const browser = await chromium.launch();
15+
const page = await browser.newPage({ viewport: { width: 1280, height: 832 } });
16+
17+
page.on('console', (msg) => {
18+
if (msg.type() === 'error' || msg.type() === 'warning') {
19+
console.log(`[${msg.type()}] ${msg.text()}`);
20+
}
21+
});
22+
page.on('pageerror', (err) => console.log(`[pageerror] ${err.message}`));
23+
24+
let url = null;
25+
for (const p of PORTS) {
26+
const candidate = `http://localhost:${p}/home`;
27+
try {
28+
await page.goto(candidate, { timeout: 3000, waitUntil: 'networkidle' });
29+
url = candidate;
30+
break;
31+
} catch {
32+
/* next */
33+
}
34+
}
35+
if (!url) throw new Error('No dev server on 5173–5177');
36+
37+
await page.waitForTimeout(1000);
38+
await page.evaluate(() => document.fonts?.ready);
39+
await page.waitForTimeout(400);
40+
41+
await page.screenshot({ path: `${outDir}/full.png`, fullPage: false });
42+
await page.screenshot({
43+
path: `${outDir}/header.png`,
44+
fullPage: false,
45+
clip: { x: 0, y: 0, width: 1280, height: 260 },
46+
});
47+
48+
console.log(`iter ${iter}${outDir} (source ${url})`);
49+
await browser.close();

0 commit comments

Comments
 (0)