From f282b00424d15a5d9992af2beeb5cb8aa7e5caf9 Mon Sep 17 00:00:00 2001 From: Benjamin Shafii Date: Wed, 4 Feb 2026 00:39:01 -0800 Subject: [PATCH] feat(app): add proto-v1-ux web prototype for UX iteration --- packages/app/src/app/app.tsx | 20 +- packages/app/src/app/pages/proto-v1-ux.tsx | 712 +++++++++++++++++++++ 2 files changed, 731 insertions(+), 1 deletion(-) create mode 100644 packages/app/src/app/pages/proto-v1-ux.tsx diff --git a/packages/app/src/app/app.tsx b/packages/app/src/app/app.tsx index bed11142..8e1c94e4 100644 --- a/packages/app/src/app/app.tsx +++ b/packages/app/src/app/app.tsx @@ -39,6 +39,7 @@ import OnboardingView from "./pages/onboarding"; import DashboardView from "./pages/dashboard"; import SessionView from "./pages/session"; import ProtoWorkspacesView from "./pages/proto-workspaces"; +import ProtoV1UxView from "./pages/proto-v1-ux"; import { createClient, unwrap, waitForHealthy } from "./lib/opencode"; import { DEFAULT_MODEL, @@ -164,6 +165,9 @@ export default function App() { if (path.startsWith("/proto")) return "proto"; return "dashboard"; }); + const isProtoV1Ux = createMemo(() => + location.pathname.toLowerCase().startsWith("/proto-v1-ux") + ); const [tab, setTabState] = createSignal("home"); const [settingsTab, setSettingsTab] = createSignal("general"); @@ -4344,6 +4348,13 @@ export default function App() { return; } + if (path.startsWith("/proto-v1-ux")) { + if (isTauriRuntime()) { + navigate("/dashboard/home", { replace: true }); + } + return; + } + if (path.startsWith("/proto")) { if (isTauriRuntime()) { navigate("/dashboard/home", { replace: true }); @@ -4374,7 +4385,14 @@ export default function App() { <> - + + + + + + + + diff --git a/packages/app/src/app/pages/proto-v1-ux.tsx b/packages/app/src/app/pages/proto-v1-ux.tsx new file mode 100644 index 00000000..ef68f399 --- /dev/null +++ b/packages/app/src/app/pages/proto-v1-ux.tsx @@ -0,0 +1,712 @@ +import { For, Match, Show, Switch, createMemo, createSignal } from "solid-js"; +import { + ArrowUp, + BookOpen, + Box, + Brain, + Calendar, + ChevronDown, + ChevronRight, + Cloud, + Edit2, + ExternalLink, + FileCode, + FileText, + Gamepad2, + History, + Layout, + MessageSquare, + Mic, + MoreHorizontal, + Pencil, + Plus, + RefreshCw, + Search, + Settings, + Sparkles, + Terminal, + TrendingUp, + Trophy, + X, + Zap, + Clock, +} from "lucide-solid"; + +type TabKey = "new-thread" | "automations" | "skills"; + +const navTabs: Array<{ id: TabKey; label: string; icon: any }> = [ + { id: "new-thread", label: "New thread", icon: Plus }, + { id: "automations", label: "Automations", icon: History }, + { id: "skills", label: "Skills", icon: Zap }, +]; + +const threadItems = [ + { text: "my packages/web/src/app/(auth...", time: "3mo" }, + { text: "could you look at https://github...", time: "3mo" }, + { text: " User ini...", time: "3mo" }, + { text: "'/Users/benjaminshafii/Download...", time: "4mo" }, + { text: "could you review the current bra...", time: "4mo" }, + { text: "it seems there's an issue with th...", time: "4mo" }, +]; + +const automationTemplates = [ + { icon: Calendar, description: "Scan recent commits and flag riskier diffs.", color: "text-red-9" }, + { icon: BookOpen, description: "Draft weekly release notes from merged PRs.", color: "text-blue-9" }, + { icon: MessageSquare, description: "Summarize yesterday's git activity by repo.", color: "text-purple-9" }, + { icon: TrendingUp, description: "Watch CI failures and surface recurring flakes.", color: "text-indigo-9" }, + { icon: Trophy, description: "Build a tiny classic game for a team demo.", color: "text-amber-9" }, + { icon: Brain, description: "Suggest the next skills to install for this workspace.", color: "text-pink-9" }, +]; + +const skillInstalled = [ + { + icon: Sparkles, + title: "Remotion Best Practices", + description: "Best practices for Remotion - Video creation in React", + badge: "zerofinance", + }, + { + icon: Pencil, + title: "Skill Creator", + description: "Create or update a skill", + }, + { + icon: Layout, + title: "Skill Installer", + description: "Install curated skills from openai/skills or other repos", + }, +]; + +const skillRecommended = [ + { + icon: ExternalLink, + title: "Atlas", + description: "Manage tabs in ChatGPT Atlas and access your...", + }, + { + icon: Cloud, + title: "Cloudflare Deploy", + description: "Deploy Workers, Pages, and platform services", + }, + { + icon: Gamepad2, + title: "Develop Web Game", + description: "Web game dev + Playwright test loop", + }, + { + icon: FileCode, + title: "Doc", + description: "Edit and review docx files", + }, +]; + +const promptSuggestions = [ + { + icon: Gamepad2, + description: "Build a classic Snake game in this repo.", + color: "text-blue-9", + }, + { + icon: FileText, + description: "Create a one-page $pdf that summarizes this app.", + color: "text-purple-9", + }, + { + icon: Layout, + description: "Summarize last week's PRs by teammate and theme.", + color: "text-sky-9", + }, +]; + +const SidebarItem = (props: { + icon: any; + label: string; + active?: boolean; + onClick?: () => void; +}) => { + const Icon = props.icon; + return ( + + ); +}; + +const ThreadItem = (props: { text: string; time: string }) => ( +
+ + {props.text} + + + {props.time} + +
+ + +
+
+); + +const ProjectFolder = (props: { name: string; children: any }) => { + const [expanded, setExpanded] = createSignal(true); + const toggleExpanded = () => setExpanded((current) => !current); + + return ( +
+
{ + if (event.key !== "Enter" && event.key !== " ") return; + event.preventDefault(); + toggleExpanded(); + }} + class="group flex w-full cursor-pointer items-center justify-between rounded-xl px-3 py-2 text-left text-sm font-semibold text-gray-11 transition-colors hover:bg-gray-2 hover:text-gray-12" + > +
+ + {props.name} +
+
+ + +
+
+ +
{props.children}
+
+
+ ); +}; + +const AutomationCard = (props: { + icon: any; + description: string; + color?: string; + onClick?: () => void; +}) => { + const Icon = props.icon; + return ( + + ); +}; + +const SkillCard = (props: { + icon: any; + title: string; + description: string; + badge?: string; + type?: "installed" | "add"; +}) => { + const Icon = props.icon; + return ( +
+
+
+ +
+
+
+

{props.title}

+ + + + {props.badge} + + +
+

+ {props.description} +

+
+
+ +
+ ); +}; + +const CreateAutomationModal = (props: { open: boolean; onClose: () => void }) => ( + +
+