Skip to content

Commit 097c6e7

Browse files
committed
Rebuild landing page sections and typography
1 parent ea78827 commit 097c6e7

8 files changed

Lines changed: 564 additions & 237 deletions

File tree

src/app/_components/gallery-client.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ export function GalleryClient({
8787
const allPreviewValues = useMemo(() => facetValues(tasks, "preview"), [tasks]);
8888
const allParadigms = useMemo(() => facetValues(tasks, "paradigm"), [tasks]);
8989
const previewCount = useMemo(() => tasks.filter((task) => task.web_variant).length, [tasks]);
90-
const voiceCount = useMemo(() => tasks.filter((task) => task.has_voiceover).length, [tasks]);
9190
const filtered = useMemo(
9291
() => filterTasks(tasks, deferredQuery, selected),
9392
[deferredQuery, selected, tasks]
@@ -153,10 +152,6 @@ export function GalleryClient({
153152
<div className="font-heading text-3xl font-bold text-[#25314d]">{previewCount}</div>
154153
<div className="text-sm text-slate-600">With preview</div>
155154
</div>
156-
<div>
157-
<div className="font-heading text-3xl font-bold text-[#25314d]">{voiceCount}</div>
158-
<div className="text-sm text-slate-600">Voice-ready</div>
159-
</div>
160155
</div>
161156
</div>
162157

src/app/globals.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import url("https://fonts.googleapis.com/css2?family=Baloo+2:wght@600;700;800&family=DM+Sans:wght@400;500;700&display=swap");
1+
@import url("https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&family=Space+Grotesk:wght@400;500;600;700&display=swap");
22

33
@tailwind base;
44
@tailwind components;

src/app/page.tsx

Lines changed: 216 additions & 154 deletions
Large diffs are not rendered by default.
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
"use client";
2+
3+
import Link from "next/link";
4+
import { useEffect, useState } from "react";
5+
import { IconChevronLeft, IconChevronRight, IconPlay } from "@/components/icons";
6+
import { MaturityBadge } from "@/components/maturity-badge";
7+
import { TaskDrawer } from "@/components/task-drawer";
8+
import type { TaskIndexItem } from "@/lib/task-index";
9+
import { formatShortDate } from "@/lib/format";
10+
import { taskHandle, taskTitle } from "@/lib/task-display";
11+
12+
export function FeaturedTaskCarousel({
13+
tasks
14+
}: {
15+
tasks: TaskIndexItem[];
16+
}) {
17+
const [activeIndex, setActiveIndex] = useState(0);
18+
const [drawerRepo, setDrawerRepo] = useState<string | null>(null);
19+
20+
useEffect(() => {
21+
if (tasks.length < 2) return undefined;
22+
23+
const timer = window.setInterval(() => {
24+
setActiveIndex((current) => (current + 1) % tasks.length);
25+
}, 6500);
26+
27+
return () => window.clearInterval(timer);
28+
}, [tasks.length]);
29+
30+
if (tasks.length === 0) {
31+
return (
32+
<div className="tb-frame bg-[#fffdf9] p-6">
33+
<div className="font-heading text-2xl font-bold text-[#25314d]">
34+
Featured tasks are unavailable in this build.
35+
</div>
36+
</div>
37+
);
38+
}
39+
40+
const activeTask = tasks[activeIndex] ?? tasks[0];
41+
const preview = activeTask.web_variant;
42+
const drawerTask = tasks.find((task) => task.repo === drawerRepo) ?? null;
43+
44+
function goTo(nextIndex: number) {
45+
const total = tasks.length;
46+
setActiveIndex(((nextIndex % total) + total) % total);
47+
}
48+
49+
return (
50+
<>
51+
<div className="tb-frame bg-[#fffdf9] p-6">
52+
<div className="flex flex-wrap items-center justify-between gap-3">
53+
<div>
54+
<div className="text-sm font-bold text-slate-600">Featured Tasks</div>
55+
<div className="mt-1 font-heading text-3xl font-bold text-[#25314d]">
56+
Rotate through flagship paradigms
57+
</div>
58+
</div>
59+
60+
<div className="flex items-center gap-2">
61+
<button
62+
type="button"
63+
className="tb-focus-ring tb-button-ghost p-3"
64+
onClick={() => goTo(activeIndex - 1)}
65+
aria-label="Show previous featured task"
66+
>
67+
<IconChevronLeft className="size-4" />
68+
</button>
69+
<button
70+
type="button"
71+
className="tb-focus-ring tb-button-ghost p-3"
72+
onClick={() => goTo(activeIndex + 1)}
73+
aria-label="Show next featured task"
74+
>
75+
<IconChevronRight className="size-4" />
76+
</button>
77+
</div>
78+
</div>
79+
80+
<div className="mt-5 flex flex-wrap gap-2">
81+
{tasks.map((task, index) => (
82+
<button
83+
key={task.repo}
84+
type="button"
85+
className={
86+
index === activeIndex
87+
? "tb-focus-ring rounded-full border-2 border-[#25314d] bg-[#d7ebf6] px-3 py-1.5 text-sm font-bold text-[#25314d] shadow-[0_4px_0_#25314d]"
88+
: "tb-focus-ring rounded-full border-2 border-[#25314d] bg-white px-3 py-1.5 text-sm font-bold text-[#25314d]"
89+
}
90+
onClick={() => setActiveIndex(index)}
91+
>
92+
{task.tags?.paradigm?.[0] ?? taskHandle(task)}
93+
</button>
94+
))}
95+
</div>
96+
97+
<div className="mt-5 tb-frame-soft bg-[#f8fcff] p-5">
98+
<div className="flex flex-wrap items-center gap-2 text-xs text-slate-600">
99+
<code className="rounded-full border-2 border-[#25314d] bg-white px-2.5 py-1 font-mono text-[11px] font-semibold text-[#25314d]">
100+
{taskHandle(activeTask)}
101+
</code>
102+
{activeTask.maturity ? <MaturityBadge maturity={activeTask.maturity} /> : null}
103+
{preview ? (
104+
<span className="rounded-full bg-[#ecffe5] px-3 py-1 text-[11px] font-bold text-[#25314d]">
105+
Preview available
106+
</span>
107+
) : null}
108+
<span className="rounded-full bg-[#e2f3fb] px-3 py-1 text-[11px] font-bold text-[#25314d]">
109+
{formatShortDate(activeTask.last_updated)}
110+
</span>
111+
</div>
112+
113+
<div className="mt-4 font-heading text-3xl font-bold leading-tight text-[#25314d]">
114+
{taskTitle(activeTask)}
115+
</div>
116+
117+
<p className="mt-3 max-w-2xl text-sm leading-7 text-slate-700 sm:text-base">
118+
{activeTask.short_description}
119+
</p>
120+
121+
<div className="mt-6 flex flex-wrap gap-3">
122+
<button
123+
type="button"
124+
className="tb-focus-ring tb-button-primary"
125+
onClick={() => setDrawerRepo(activeTask.repo)}
126+
>
127+
Expand details
128+
</button>
129+
{preview ? (
130+
<a
131+
className="tb-focus-ring tb-button-secondary bg-[#d7ebf6]"
132+
href={preview.run_url}
133+
target="_blank"
134+
rel="noreferrer"
135+
>
136+
<IconPlay className="size-4" />
137+
Run Preview
138+
</a>
139+
) : null}
140+
</div>
141+
</div>
142+
143+
<div className="mt-6 flex flex-wrap items-center justify-between gap-4">
144+
<div className="text-sm leading-6 text-slate-700">
145+
Highlighted here: BART, SST, and MID as fast entry points into the broader task catalog.
146+
</div>
147+
<Link className="tb-focus-ring tb-button-primary" href="/tasks/">
148+
Continue to Tasks
149+
</Link>
150+
</div>
151+
</div>
152+
153+
<TaskDrawer task={drawerTask} onClose={() => setDrawerRepo(null)} />
154+
</>
155+
);
156+
}

src/components/icons.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,22 @@ export function IconViewGrid(props: { className?: string }) {
8282
);
8383
}
8484

85+
export function IconChevronLeft(props: { className?: string }) {
86+
return (
87+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className={props.className} aria-hidden="true">
88+
<path strokeLinecap="round" strokeLinejoin="round" d="M15 6l-6 6 6 6" />
89+
</svg>
90+
);
91+
}
92+
93+
export function IconChevronRight(props: { className?: string }) {
94+
return (
95+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className={props.className} aria-hidden="true">
96+
<path strokeLinecap="round" strokeLinejoin="round" d="M9 6l6 6-6 6" />
97+
</svg>
98+
);
99+
}
100+
85101
export function IconMenu(props: { className?: string }) {
86102
return (
87103
<svg

src/components/site-footer.tsx

Lines changed: 80 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,101 @@
11
import Link from "next/link";
2-
import { tasksPageHref } from "@/lib/routes";
2+
import { getIndex } from "@/lib/task-index";
33

44
export function SiteFooter() {
5+
const index = getIndex();
6+
const tasks = index.tasks ?? [];
7+
const previewCount = tasks.filter((task) => task.web_variant).length;
8+
59
return (
610
<footer className="mt-16 bg-[#efe7de]">
711
<div className="mx-auto w-full max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
812
<div className="tb-frame bg-[#fff8f0] px-6 py-8">
9-
<div className="flex flex-col gap-8 lg:flex-row lg:items-end lg:justify-between">
13+
<div className="grid gap-8 lg:grid-cols-[0.78fr_1.22fr]">
1014
<div className="max-w-2xl">
1115
<div className="font-heading text-3xl font-bold text-[#25314d]">TaskBeacon</div>
1216
<div className="mt-3 text-sm leading-7 text-slate-700">
13-
Canonical PsyFlow tasks, aligned web previews, contribution workflows, and
14-
framework references in one place.
17+
Canonical tasks, aligned previews, framework references, and automation-ready
18+
workflows for reusable cognitive task development.
19+
</div>
20+
<div className="mt-6 text-xs font-bold uppercase tracking-[0.18em] text-slate-500">
21+
Static index updated {new Date(index.generated_at).toLocaleDateString("en-US")}
1522
</div>
1623
</div>
1724

18-
<div className="flex flex-wrap gap-3 text-sm">
19-
<Link className="tb-focus-ring tb-button-ghost" href={tasksPageHref()}>
20-
Tasks
21-
</Link>
22-
<Link className="tb-focus-ring tb-button-secondary" href="/framework/">
23-
Framework
24-
</Link>
25-
<Link className="tb-focus-ring tb-button-secondary" href="/contribute/">
26-
Contribute
27-
</Link>
28-
<a
29-
className="tb-focus-ring tb-button-primary"
30-
href="https://taskbeacon.github.io/psyflow-web"
31-
target="_blank"
32-
rel="noreferrer"
33-
>
34-
Preview
35-
</a>
25+
<div className="grid gap-4 md:grid-cols-3">
26+
<article className="tb-frame-soft bg-white p-4">
27+
<div className="text-[11px] font-bold uppercase tracking-[0.18em] text-slate-500">
28+
Catalog
29+
</div>
30+
<div className="mt-3 font-heading text-2xl font-bold text-[#25314d]">
31+
{tasks.length} tasks, {previewCount} previews
32+
</div>
33+
<div className="mt-2 text-sm leading-6 text-slate-700">
34+
Open the explorer when you need the full catalog, filters, and README-backed details.
35+
</div>
36+
<div className="mt-4">
37+
<Link className="tb-focus-ring tb-button-secondary" href="/tasks/">
38+
Open Tasks
39+
</Link>
40+
</div>
41+
</article>
42+
43+
<article className="tb-frame-soft bg-white p-4">
44+
<div className="text-[11px] font-bold uppercase tracking-[0.18em] text-slate-500">
45+
Standards
46+
</div>
47+
<div className="mt-3 font-heading text-2xl font-bold text-[#25314d]">
48+
TAPS, PsyFlow, psyflow-web
49+
</div>
50+
<div className="mt-2 text-sm leading-6 text-slate-700">
51+
Read the structure standard, then move into the local and web runtime layers.
52+
</div>
53+
<div className="mt-4 flex flex-wrap gap-2">
54+
<a
55+
className="tb-focus-ring tb-button-ghost"
56+
href="https://github.com/TaskBeacon/taskbeacon.github.io/blob/main/source/taps.md"
57+
target="_blank"
58+
rel="noreferrer"
59+
>
60+
Read TAPS
61+
</a>
62+
<Link className="tb-focus-ring tb-button-secondary" href="/framework/">
63+
Framework
64+
</Link>
65+
</div>
66+
</article>
67+
68+
<article className="tb-frame-soft bg-white p-4">
69+
<div className="text-[11px] font-bold uppercase tracking-[0.18em] text-slate-500">
70+
Build
71+
</div>
72+
<div className="mt-3 font-heading text-2xl font-bold text-[#25314d]">
73+
Skills, tutorials, contribution
74+
</div>
75+
<div className="mt-2 text-sm leading-6 text-slate-700">
76+
Move from setup to localization, plotting, translation, and contribution without leaving the ecosystem.
77+
</div>
78+
<div className="mt-4 flex flex-wrap gap-2">
79+
<a
80+
className="tb-focus-ring tb-button-ghost"
81+
href="https://github.com/TaskBeacon/skills"
82+
target="_blank"
83+
rel="noreferrer"
84+
>
85+
Browse Skills
86+
</a>
87+
<Link className="tb-focus-ring tb-button-secondary" href="/contribute/">
88+
Contribute
89+
</Link>
90+
</div>
91+
</article>
3692
</div>
3793
</div>
3894

3995
<div className="mt-8 flex flex-wrap items-center justify-between gap-3 text-xs text-slate-600">
40-
<div>Built as a static site with automated index refresh.</div>
96+
<div>TaskBeacon GitHub organization remains the public source of truth for active repositories.</div>
4197
<a href="https://github.com/TaskBeacon" target="_blank" rel="noreferrer">
42-
GitHub Organization
98+
Open GitHub Organization
4399
</a>
44100
</div>
45101
</div>

0 commit comments

Comments
 (0)