From 8c3cc0d44777b10edc4a03366f2c3de58d1a8f72 Mon Sep 17 00:00:00 2001
From: Adam <2363879+adamdotdevin@users.noreply.github.com>
Date: Fri, 9 Jan 2026 21:09:26 -0600
Subject: [PATCH] chore: prep
---
bun.lock | 1 +
packages/console/app/package.json | 1 +
.../app/src/routes/black/workspace.css | 214 ++++++++++++++++
.../app/src/routes/black/workspace.tsx | 229 ++++++++++++++++++
4 files changed, 445 insertions(+)
create mode 100644 packages/console/app/src/routes/black/workspace.css
create mode 100644 packages/console/app/src/routes/black/workspace.tsx
diff --git a/bun.lock b/bun.lock
index d7ca5d83e..9aba2f10f 100644
--- a/bun.lock
+++ b/bun.lock
@@ -87,6 +87,7 @@
"chart.js": "4.5.1",
"nitro": "3.0.1-alpha.1",
"solid-js": "catalog:",
+ "solid-list": "0.3.0",
"vite": "catalog:",
"zod": "catalog:",
},
diff --git a/packages/console/app/package.json b/packages/console/app/package.json
index 701802fc9..0af730e9f 100644
--- a/packages/console/app/package.json
+++ b/packages/console/app/package.json
@@ -26,6 +26,7 @@
"chart.js": "4.5.1",
"nitro": "3.0.1-alpha.1",
"solid-js": "catalog:",
+ "solid-list": "0.3.0",
"vite": "catalog:",
"zod": "catalog:"
},
diff --git a/packages/console/app/src/routes/black/workspace.css b/packages/console/app/src/routes/black/workspace.css
new file mode 100644
index 000000000..bf9d94878
--- /dev/null
+++ b/packages/console/app/src/routes/black/workspace.css
@@ -0,0 +1,214 @@
+[data-page="black"] {
+ background: #000;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: stretch;
+ font-family: var(--font-mono);
+ color: #fff;
+
+ [data-component="header-gradient"] {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 288px;
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.16) 0%, rgba(0, 0, 0, 0) 100%);
+ }
+
+ [data-component="header"] {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding-top: 40px;
+ flex-shrink: 0;
+
+ /* [data-component="header-logo"] { */
+ /* } */
+ }
+
+ [data-component="content"] {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 100%;
+ flex-grow: 1;
+
+ [data-slot="hero-black"] {
+ margin-top: 110px;
+
+ @media (min-width: 768px) {
+ margin-top: 150px;
+ }
+ }
+
+ [data-slot="select-workspace"] {
+ display: flex;
+ margin-top: -24px;
+ width: 100%;
+ max-width: 480px;
+ height: 305px;
+ padding: 32px 20px 0 20px;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 24px;
+
+ border: 1px solid #303030;
+ background: #0a0a0a;
+ box-shadow:
+ 0 100px 80px 0 rgba(0, 0, 0, 0.04),
+ 0 41.778px 33.422px 0 rgba(0, 0, 0, 0.05),
+ 0 22.336px 17.869px 0 rgba(0, 0, 0, 0.06),
+ 0 12.522px 10.017px 0 rgba(0, 0, 0, 0.08),
+ 0 6.65px 5.32px 0 rgba(0, 0, 0, 0.09),
+ 0 2.767px 2.214px 0 rgba(0, 0, 0, 0.13);
+
+ [data-slot="select-workspace-title"] {
+ flex-shrink: 0;
+ align-self: stretch;
+ color: rgba(255, 255, 255, 0.59);
+ text-align: center;
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 160%; /* 25.6px */
+ }
+
+ [data-slot="workspaces"] {
+ width: 100%;
+ padding: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 8px;
+ align-self: stretch;
+ outline: none;
+ overflow-y: auto;
+ flex: 1;
+ min-height: 0;
+
+ scrollbar-width: none;
+ &::-webkit-scrollbar {
+ display: none;
+ }
+
+ [data-slot="workspace"] {
+ width: 100%;
+ display: flex;
+ padding: 8px 12px;
+ align-items: center;
+ gap: 8px;
+ align-self: stretch;
+ cursor: pointer;
+
+ [data-slot="selected-icon"] {
+ visibility: hidden;
+ color: rgba(255, 255, 255, 0.39);
+ font-family: "IBM Plex Mono";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 160%; /* 25.6px */
+ }
+
+ a {
+ color: rgba(255, 255, 255, 0.92);
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 160%; /* 25.6px */
+ text-decoration: none;
+ }
+ }
+
+ [data-slot="workspace"]:hover,
+ [data-slot="workspace"][data-active="true"] {
+ background: #161616;
+
+ [data-slot="selected-icon"] {
+ visibility: visible;
+ }
+ }
+ }
+ }
+ }
+
+ [data-component="footer"] {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ justify-content: center;
+ align-items: center;
+ gap: 24px;
+ flex-shrink: 0;
+
+ @media (min-width: 768px) {
+ height: 120px;
+ }
+
+ [data-slot="footer-content"] {
+ display: flex;
+ gap: 24px;
+ align-items: center;
+ justify-content: center;
+
+ @media (min-width: 768px) {
+ gap: 40px;
+ }
+
+ span,
+ a {
+ color: rgba(255, 255, 255, 0.39);
+ font-family: "JetBrains Mono Nerd Font";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: normal;
+ text-decoration: none;
+ }
+
+ [data-slot="github-stars"] {
+ color: rgba(255, 255, 255, 0.25);
+ font-family: "JetBrains Mono Nerd Font";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: normal;
+ }
+
+ [data-slot="anomaly"] {
+ display: none;
+
+ @media (min-width: 768px) {
+ display: block;
+ }
+ }
+ }
+ [data-slot="anomaly-alt"] {
+ color: rgba(255, 255, 255, 0.39);
+ font-family: "JetBrains Mono Nerd Font";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: normal;
+ text-decoration: none;
+ margin-bottom: 24px;
+
+ a {
+ color: rgba(255, 255, 255, 0.39);
+ font-family: "JetBrains Mono Nerd Font";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: normal;
+ text-decoration: none;
+ }
+
+ @media (min-width: 768px) {
+ display: none;
+ }
+ }
+ }
+}
diff --git a/packages/console/app/src/routes/black/workspace.tsx b/packages/console/app/src/routes/black/workspace.tsx
new file mode 100644
index 000000000..0eca8cd11
--- /dev/null
+++ b/packages/console/app/src/routes/black/workspace.tsx
@@ -0,0 +1,229 @@
+import { A, createAsync, useNavigate } from "@solidjs/router"
+import "./workspace.css"
+import { Title } from "@solidjs/meta"
+import { github } from "~/lib/github"
+import { createEffect, createMemo, For, onMount } from "solid-js"
+import { config } from "~/config"
+import { createList } from "solid-list"
+
+export default function BlackWorkspace() {
+ const navigate = useNavigate()
+ const githubData = createAsync(() => github())
+ const starCount = createMemo(() =>
+ githubData()?.stars
+ ? new Intl.NumberFormat("en-US", {
+ notation: "compact",
+ compactDisplay: "short",
+ }).format(githubData()!.stars!)
+ : config.github.starsFormatted.compact,
+ )
+
+ // TODO: Frank, replace with real workspaces
+ const workspaces = [
+ { name: "Workspace 1", id: "wrk_123" },
+ { name: "Workspace 2", id: "wrk_456" },
+ { name: "Workspace 3", id: "wrk_789" },
+ { name: "Workspace 4", id: "wrk_111" },
+ { name: "Workspace 5", id: "wrk_222" },
+ { name: "Workspace 6", id: "wrk_333" },
+ { name: "Workspace 7", id: "wrk_444" },
+ { name: "Workspace 8", id: "wrk_555" },
+ ]
+
+ let listRef: HTMLUListElement | undefined
+
+ const { active, setActive, onKeyDown } = createList({
+ items: () => workspaces.map((w) => w.id),
+ initialActive: workspaces[0]?.id ?? null,
+ handleTab: true,
+ })
+
+ onMount(() => {
+ listRef?.focus()
+ })
+
+ createEffect(() => {
+ const id = active()
+ if (!id || !listRef) return
+ const el = listRef.querySelector(`[data-id="${id}"]`)
+ el?.scrollIntoView({ block: "nearest" })
+ })
+
+ return (
+
+
opencode
+
+
+
+
+
+
+
+
+
+
+
+ Select a workspace for this plan
+ {
+ if (e.key === "Enter" && active()) {
+ navigate(`/black/workspace/${active()}`)
+ } else if (e.key === "Tab") {
+ e.preventDefault()
+ onKeyDown(e)
+ } else {
+ onKeyDown(e)
+ }
+ }}
+ >
+
+ {(workspace) => (
+ - setActive(workspace.id)}
+ onClick={() => navigate(`/black/workspace/${workspace.id}`)}
+ >
+ [*]
+ {workspace.name}
+
+ )}
+
+
+
+
+
+
+ )
+}