diff options
| author | Frank <[email protected]> | 2025-08-29 23:32:17 -0400 |
|---|---|---|
| committer | Frank <[email protected]> | 2025-08-29 23:32:17 -0400 |
| commit | 37f284f9a97d3354143d64fc76c2eb9f7d9ccf9e (patch) | |
| tree | 053db9abcb2178c71b22ebeadd07f920750ef5d2 /cloud/web/src/pages/components | |
| parent | 0178eab29bda2f1b37a29543cd313ede48ad3977 (diff) | |
| download | opencode-37f284f9a97d3354143d64fc76c2eb9f7d9ccf9e.tar.gz opencode-37f284f9a97d3354143d64fc76c2eb9f7d9ccf9e.zip | |
wip: cloud
Diffstat (limited to 'cloud/web/src/pages/components')
| -rw-r--r-- | cloud/web/src/pages/components/context-api.tsx | 24 | ||||
| -rw-r--r-- | cloud/web/src/pages/components/context-workspace.tsx | 38 | ||||
| -rw-r--r-- | cloud/web/src/pages/components/layout.module.css | 199 | ||||
| -rw-r--r-- | cloud/web/src/pages/components/layout.tsx | 96 |
4 files changed, 0 insertions, 357 deletions
diff --git a/cloud/web/src/pages/components/context-api.tsx b/cloud/web/src/pages/components/context-api.tsx deleted file mode 100644 index 0a348f48f..000000000 --- a/cloud/web/src/pages/components/context-api.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { hc } from "hono/client" -import { ApiType } from "@opencode/cloud-function/src/gateway" -import { useWorkspace } from "./context-workspace" -import { useOpenAuth } from "../../components/context-openauth" - -export function useApi() { - const workspace = useWorkspace() - const auth = useOpenAuth() - return hc<ApiType>(import.meta.env.VITE_API_URL, { - async fetch(...args: Parameters<typeof fetch>): Promise<Response> { - const [input, init] = args - const request = input instanceof Request ? input : new Request(input, init) - const headers = new Headers(request.headers) - headers.set("authorization", `Bearer ${await auth.access()}`) - headers.set("x-opencode-workspace", workspace.id) - return fetch( - new Request(request, { - ...init, - headers, - }), - ) - }, - }) -} diff --git a/cloud/web/src/pages/components/context-workspace.tsx b/cloud/web/src/pages/components/context-workspace.tsx deleted file mode 100644 index 6bad39840..000000000 --- a/cloud/web/src/pages/components/context-workspace.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useNavigate, useParams } from "@solidjs/router" -import { createInitializedContext } from "../../util/context" -import { useAccount } from "../../components/context-account" -import { createEffect, createMemo } from "solid-js" - -export const { use: useWorkspace, provider: WorkspaceProvider } = - createInitializedContext("WorkspaceProvider", () => { - const params = useParams() - const account = useAccount() - const workspace = createMemo(() => - account.current?.workspaces.find( - (x) => x.id === params.workspace || x.slug === params.workspace, - ), - ) - const nav = useNavigate() - - createEffect(() => { - if (!workspace()) nav("/") - }) - - const result = () => workspace()! - result.ready = true - - return { - get id() { - return workspace()!.id - }, - get slug() { - return workspace()!.slug - }, - get name() { - return workspace()!.name - }, - get ready() { - return workspace() !== undefined - }, - } - }) diff --git a/cloud/web/src/pages/components/layout.module.css b/cloud/web/src/pages/components/layout.module.css deleted file mode 100644 index c64faa18e..000000000 --- a/cloud/web/src/pages/components/layout.module.css +++ /dev/null @@ -1,199 +0,0 @@ -.root { - --padding: var(--space-10); - --vertical-padding: var(--space-8); - --heading-font-size: var(--font-size-4xl); - --sidebar-width: 200px; - --mobile-breakpoint: 40rem; - --topbar-height: 60px; - - margin: var(--space-4); - border: 2px solid var(--color-border); - height: calc(100vh - var(--space-8)); - display: flex; - flex-direction: row; - overflow: hidden; - /* Prevent overall scrolling */ - position: relative; -} - -[data-component="mobile-top-bar"] { - display: none; - position: fixed; - top: 0; - left: 0; - right: 0; - height: var(--topbar-height); - background: var(--color-background); - border-bottom: 2px solid var(--color-border); - z-index: 20; - align-items: center; - padding: 0 var(--space-4) 0 0; - - [data-slot="logo"] { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - - div { - text-transform: uppercase; - font-weight: 600; - letter-spacing: -0.03125rem; - } - - svg { - height: 28px; - width: auto; - color: var(--color-white); - } - } - - [data-slot="toggle"] { - background: transparent; - border: none; - padding: var(--space-4); - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - - & svg { - width: 24px; - height: 24px; - color: var(--color-foreground); - } - } -} - -[data-component="sidebar"] { - width: var(--sidebar-width); - border-right: 2px solid var(--color-border); - display: flex; - flex-direction: column; - padding: calc(var(--padding) / 2); - overflow-y: auto; - /* Allow scrolling if needed */ - position: sticky; - top: 0; - height: 100%; - background-color: var(--color-background); - z-index: 10; - - [data-slot="logo"] { - margin-top: 2px; - margin-bottom: var(--space-7); - color: var(--color-white); - - & svg { - height: 32px; - width: auto; - } - } - - [data-slot="nav"] { - flex: 1; - - ul { - list-style-type: none; - padding: 0; - } - - li { - margin-bottom: calc(var(--vertical-padding) / 2); - text-transform: uppercase; - font-weight: 500; - } - - a { - display: block; - padding: var(--space-2) 0; - } - } - - [data-slot="user"] { - [data-component="button"] { - padding-left: 0; - padding-bottom: 0; - height: auto; - } - } -} - -.navActiveLink { - cursor: default; - text-decoration: none; -} - -[data-slot="main-content"] { - flex: 1; - display: flex; - flex-direction: column; - height: 100%; - /* Full height */ - overflow: hidden; - /* Prevent overflow */ - position: relative; - /* For positioning footer */ - width: 100%; - /* Full width */ -} - -/* Backdrop for mobile */ -[data-component="backdrop"] { - display: none; - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - /* background-color: rgba(0, 0, 0, 0.5); */ - z-index: 25; - backdrop-filter: blur(2px); -} - -/* Mobile styles */ -@media (max-width: 40rem) { - .root { - margin: 0; - border: none; - height: 100vh; - } - - [data-component="mobile-top-bar"] { - display: flex; - } - - [data-component="backdrop"] { - display: block; - } - - [data-component="sidebar"] { - position: fixed; - left: -100%; - top: 0; - height: 100vh; - width: 80%; - max-width: 280px; - transition: left 0.3s ease-in-out; - box-shadow: none; - z-index: 30; - padding: var(--space-8); - background-color: var(--color-bg); - - &[data-opened="true"] { - left: 0; - box-shadow: 8px 0 0px 0px var(--color-gray-4); - } - } - - [data-slot="main-content"] { - padding-top: var(--topbar-height); - /* Add space for the top bar */ - overflow-y: auto; - } - - /* Hide the logo in the sidebar on mobile since it's in the top bar */ - [data-component="sidebar"] [data-slot="logo"] { - display: none; - } -} diff --git a/cloud/web/src/pages/components/layout.tsx b/cloud/web/src/pages/components/layout.tsx deleted file mode 100644 index 711ed8fc2..000000000 --- a/cloud/web/src/pages/components/layout.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import style from "./layout.module.css" -import { useAccount } from "../../components/context-account" -import { Button } from "../../ui/button" -import { IconLogomark } from "../../ui/svg" -import { IconBars3BottomLeft } from "../../ui/svg/icons" -import { ParentProps, createMemo, createSignal } from "solid-js" -import { A, useLocation } from "@solidjs/router" -import { useOpenAuth } from "../../components/context-openauth" - -export default function Layout(props: ParentProps) { - const auth = useOpenAuth() - const account = useAccount() - const [sidebarOpen, setSidebarOpen] = createSignal(false) - const location = useLocation() - - const workspaceId = createMemo(() => account.current?.workspaces[0].id) - const pageTitle = createMemo(() => { - const path = location.pathname - if (path.endsWith("/billing")) return "Billing" - if (path.endsWith("/keys")) return "API Keys" - return null - }) - - function handleLogout() { - auth.logout(auth.subject?.id!) - } - - return ( - <div class={style.root}> - {/* Mobile top bar */} - <div data-component="mobile-top-bar"> - <button data-slot="toggle" onClick={() => setSidebarOpen(!sidebarOpen())}> - <IconBars3BottomLeft /> - </button> - - <div data-slot="logo"> - {pageTitle() ? ( - <div>{pageTitle()}</div> - ) : ( - <A href="/"> - <IconLogomark /> - </A> - )} - </div> - </div> - - {/* Backdrop for mobile sidebar - closes sidebar when clicked */} - {sidebarOpen() && <div data-component="backdrop" onClick={() => setSidebarOpen(false)}></div>} - - <div data-component="sidebar" data-opened={sidebarOpen() ? "true" : "false"}> - <div data-slot="logo"> - <A href="/"> - <IconLogomark /> - </A> - </div> - - <nav data-slot="nav"> - <ul> - <li> - <A end activeClass={style.navActiveLink} href={`/${workspaceId()}`} onClick={() => setSidebarOpen(false)}> - Chat - </A> - </li> - <li> - <A - activeClass={style.navActiveLink} - href={`/${workspaceId()}/billing`} - onClick={() => setSidebarOpen(false)} - > - Billing - </A> - </li> - <li> - <A - activeClass={style.navActiveLink} - href={`/${workspaceId()}/keys`} - onClick={() => setSidebarOpen(false)} - > - API Keys - </A> - </li> - </ul> - </nav> - - <div data-slot="user"> - <Button color="ghost" onClick={handleLogout} title={account.current?.email || ""}> - Logout - </Button> - </div> - </div> - - {/* Main Content */} - <div data-slot="main-content">{props.children}</div> - </div> - ) -} |
