From 07cf8847fb1908ff5dc47a771f57d23926baa1ce Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 15 Aug 2025 19:29:24 -0400 Subject: wip: cloud stuff --- cloud/app/.gitignore | 28 +++ cloud/app/.opencode/agent/css.md | 61 +++++++ cloud/app/README.md | 32 ++++ cloud/app/app.config.ts | 9 + cloud/app/package.json | 21 +++ cloud/app/public/favicon.ico | Bin 0 -> 664 bytes cloud/app/src/app.css | 1 + cloud/app/src/app.tsx | 21 +++ cloud/app/src/asset/logo-ornate-dark.svg | 19 +++ cloud/app/src/asset/screenshot-github.webp | Bin 0 -> 924094 bytes cloud/app/src/asset/screenshot-splash.webp | Bin 0 -> 467281 bytes cloud/app/src/asset/screenshot-vscode.webp | Bin 0 -> 1022418 bytes cloud/app/src/component/icon.tsx | 24 +++ cloud/app/src/entry-client.tsx | 4 + cloud/app/src/entry-server.tsx | 21 +++ cloud/app/src/global.d.ts | 1 + cloud/app/src/routes/[...404].tsx | 19 +++ cloud/app/src/routes/index.css | 264 +++++++++++++++++++++++++++++ cloud/app/src/routes/index.tsx | 169 ++++++++++++++++++ cloud/app/src/style/base.css | 8 + cloud/app/src/style/component/button.css | 102 +++++++++++ cloud/app/src/style/index.css | 8 + cloud/app/src/style/reset.css | 76 +++++++++ cloud/app/src/style/token/color.css | 90 ++++++++++ cloud/app/src/style/token/font.css | 18 ++ cloud/app/src/style/token/space.css | 41 +++++ cloud/app/tsconfig.json | 19 +++ cloud/web/src/ui/style/token/space.css | 1 + 28 files changed, 1057 insertions(+) create mode 100644 cloud/app/.gitignore create mode 100644 cloud/app/.opencode/agent/css.md create mode 100644 cloud/app/README.md create mode 100644 cloud/app/app.config.ts create mode 100644 cloud/app/package.json create mode 100644 cloud/app/public/favicon.ico create mode 100644 cloud/app/src/app.css create mode 100644 cloud/app/src/app.tsx create mode 100644 cloud/app/src/asset/logo-ornate-dark.svg create mode 100644 cloud/app/src/asset/screenshot-github.webp create mode 100644 cloud/app/src/asset/screenshot-splash.webp create mode 100644 cloud/app/src/asset/screenshot-vscode.webp create mode 100644 cloud/app/src/component/icon.tsx create mode 100644 cloud/app/src/entry-client.tsx create mode 100644 cloud/app/src/entry-server.tsx create mode 100644 cloud/app/src/global.d.ts create mode 100644 cloud/app/src/routes/[...404].tsx create mode 100644 cloud/app/src/routes/index.css create mode 100644 cloud/app/src/routes/index.tsx create mode 100644 cloud/app/src/style/base.css create mode 100644 cloud/app/src/style/component/button.css create mode 100644 cloud/app/src/style/index.css create mode 100644 cloud/app/src/style/reset.css create mode 100644 cloud/app/src/style/token/color.css create mode 100644 cloud/app/src/style/token/font.css create mode 100644 cloud/app/src/style/token/space.css create mode 100644 cloud/app/tsconfig.json (limited to 'cloud') diff --git a/cloud/app/.gitignore b/cloud/app/.gitignore new file mode 100644 index 000000000..751513ce1 --- /dev/null +++ b/cloud/app/.gitignore @@ -0,0 +1,28 @@ +dist +.wrangler +.output +.vercel +.netlify +.vinxi +app.config.timestamp_*.js + +# Environment +.env +.env*.local + +# dependencies +/node_modules + +# IDEs and editors +/.idea +.project +.classpath +*.launch +.settings/ + +# Temp +gitignore + +# System Files +.DS_Store +Thumbs.db diff --git a/cloud/app/.opencode/agent/css.md b/cloud/app/.opencode/agent/css.md new file mode 100644 index 000000000..58c59da73 --- /dev/null +++ b/cloud/app/.opencode/agent/css.md @@ -0,0 +1,61 @@ +--- +description: use whenever you are styling a ui with css +--- + +you are very good at writing clean maintainable css using modern techniques + +css is structured like this + +```css +[data-page="home"] { + [data-component="header"] { + [data-slot="logo"] { + } + } +} +``` + +top level pages are scoped using `data-page` + +pages can break down into components using `data-component` + +components can break down into slots using `data-slot` + +structure things so that this hierarchy is followed - you should rarely need to +nest components inside other components. you should NEVER nest components inside +slots. you should NEVER nest slots inside other slots. + +thei hierarchy in css file does NOT have to match the hierarchy in the dom - you +can put components or slots at the same level even if one goes inside another. + +it is more important to follow the pages -> components -> slots structure + +use data attributes to represent different states of the component + +```css +[data-component="modal"] { + opacity: 0; + + &[data-state="open"] { + opacity: 1; + } +} +``` + +this will allow jsx to control the syling + +avoid selectors that just target an element type like `> span` you should assign +it a slot name. it's ok to do this sometimes where it makes sense semantically +like targeting `li` elements in a list + +in terms of file structure `./src/style/` contains all universal styling rules. +these should not contain anything specific to a page + +`./src/style/token` contains all the tokens used in the project + +`./src/style/component` is for reusable components like buttons or inputs + +page specific styles should go next to the page they are styling so +`./src/routes/about.tsx` should have its styles in `./src/routes/about.css` + +`about.css` should be scoped using `data-page="about"` diff --git a/cloud/app/README.md b/cloud/app/README.md new file mode 100644 index 000000000..9337430cf --- /dev/null +++ b/cloud/app/README.md @@ -0,0 +1,32 @@ +# SolidStart + +Everything you need to build a Solid project, powered by [`solid-start`](https://start.solidjs.com); + +## Creating a project + +```bash +# create a new project in the current directory +npm init solid@latest + +# create a new project in my-app +npm init solid@latest my-app +``` + +## Developing + +Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: + +```bash +npm run dev + +# or start the server and open the app in a new browser tab +npm run dev -- --open +``` + +## Building + +Solid apps are built with _presets_, which optimise your project for deployment to different environments. + +By default, `npm run build` will generate a Node app that you can run with `npm start`. To use a different preset, add it to the `devDependencies` in `package.json` and specify in your `app.config.js`. + +## This project was created with the [Solid CLI](https://github.com/solidjs-community/solid-cli) diff --git a/cloud/app/app.config.ts b/cloud/app/app.config.ts new file mode 100644 index 000000000..0ffa557f9 --- /dev/null +++ b/cloud/app/app.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "@solidjs/start/config" + +export default defineConfig({ + vite: { + server: { + allowedHosts: true, + }, + }, +}) diff --git a/cloud/app/package.json b/cloud/app/package.json new file mode 100644 index 000000000..59556e0ba --- /dev/null +++ b/cloud/app/package.json @@ -0,0 +1,21 @@ +{ + "name": "@opencode/cloud-app", + "type": "module", + "scripts": { + "dev": "vinxi dev --host 0.0.0.0", + "build": "vinxi build", + "start": "vinxi start", + "version": "vinxi version" + }, + "dependencies": { + "@ibm/plex": "6.4.1", + "@solidjs/meta": "^0.29.4", + "@solidjs/router": "^0.15.0", + "@solidjs/start": "^1.1.0", + "solid-js": "^1.9.5", + "vinxi": "^0.5.7" + }, + "engines": { + "node": ">=22" + } +} diff --git a/cloud/app/public/favicon.ico b/cloud/app/public/favicon.ico new file mode 100644 index 000000000..fb282da07 Binary files /dev/null and b/cloud/app/public/favicon.ico differ diff --git a/cloud/app/src/app.css b/cloud/app/src/app.css new file mode 100644 index 000000000..c0261c422 --- /dev/null +++ b/cloud/app/src/app.css @@ -0,0 +1 @@ +@import "./style/index.css"; diff --git a/cloud/app/src/app.tsx b/cloud/app/src/app.tsx new file mode 100644 index 000000000..04c569b91 --- /dev/null +++ b/cloud/app/src/app.tsx @@ -0,0 +1,21 @@ +import { MetaProvider, Title } from "@solidjs/meta"; +import { Router } from "@solidjs/router"; +import { FileRoutes } from "@solidjs/start/router"; +import { Suspense } from "solid-js"; +import "@ibm/plex/css/ibm-plex.css"; +import "./app.css"; + +export default function App() { + return ( + ( + + SolidStart - Basic + {props.children} + + )} + > + + + ); +} diff --git a/cloud/app/src/asset/logo-ornate-dark.svg b/cloud/app/src/asset/logo-ornate-dark.svg new file mode 100644 index 000000000..2efda934d --- /dev/null +++ b/cloud/app/src/asset/logo-ornate-dark.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/cloud/app/src/asset/screenshot-github.webp b/cloud/app/src/asset/screenshot-github.webp new file mode 100644 index 000000000..fda74e641 Binary files /dev/null and b/cloud/app/src/asset/screenshot-github.webp differ diff --git a/cloud/app/src/asset/screenshot-splash.webp b/cloud/app/src/asset/screenshot-splash.webp new file mode 100644 index 000000000..e900673ef Binary files /dev/null and b/cloud/app/src/asset/screenshot-splash.webp differ diff --git a/cloud/app/src/asset/screenshot-vscode.webp b/cloud/app/src/asset/screenshot-vscode.webp new file mode 100644 index 000000000..b8966a6b8 Binary files /dev/null and b/cloud/app/src/asset/screenshot-vscode.webp differ diff --git a/cloud/app/src/component/icon.tsx b/cloud/app/src/component/icon.tsx new file mode 100644 index 000000000..5a565ab9a --- /dev/null +++ b/cloud/app/src/component/icon.tsx @@ -0,0 +1,24 @@ + +import { JSX } from "solid-js" + + +export function IconCopy(props: JSX.SvgSVGAttributes) { + return ( + + + + + ) +} + +export function IconCheck(props: JSX.SvgSVGAttributes) { + return ( + + + + ) +} diff --git a/cloud/app/src/entry-client.tsx b/cloud/app/src/entry-client.tsx new file mode 100644 index 000000000..0ca4e3c30 --- /dev/null +++ b/cloud/app/src/entry-client.tsx @@ -0,0 +1,4 @@ +// @refresh reload +import { mount, StartClient } from "@solidjs/start/client"; + +mount(() => , document.getElementById("app")!); diff --git a/cloud/app/src/entry-server.tsx b/cloud/app/src/entry-server.tsx new file mode 100644 index 000000000..eb8aea1e8 --- /dev/null +++ b/cloud/app/src/entry-server.tsx @@ -0,0 +1,21 @@ +// @refresh reload +import { createHandler, StartServer } from "@solidjs/start/server"; + +export default createHandler(() => ( + ( + + + + + + {assets} + + +
{children}
+ {scripts} + + + )} + /> +)); diff --git a/cloud/app/src/global.d.ts b/cloud/app/src/global.d.ts new file mode 100644 index 000000000..dc6f10c22 --- /dev/null +++ b/cloud/app/src/global.d.ts @@ -0,0 +1 @@ +/// diff --git a/cloud/app/src/routes/[...404].tsx b/cloud/app/src/routes/[...404].tsx new file mode 100644 index 000000000..4ea71ec7f --- /dev/null +++ b/cloud/app/src/routes/[...404].tsx @@ -0,0 +1,19 @@ +import { Title } from "@solidjs/meta"; +import { HttpStatusCode } from "@solidjs/start"; + +export default function NotFound() { + return ( +
+ Not Found + +

Page Not Found

+

+ Visit{" "} + + start.solidjs.com + {" "} + to learn how to build SolidStart apps. +

+
+ ); +} diff --git a/cloud/app/src/routes/index.css b/cloud/app/src/routes/index.css new file mode 100644 index 000000000..e3b11c605 --- /dev/null +++ b/cloud/app/src/routes/index.css @@ -0,0 +1,264 @@ +[data-page="home"] { + --color-bg: oklch(0.2097 0.008 274.53); + --color-border: oklch(0.46 0.02 269.88); + --color-text: #ffffff; + --color-text-secondary: oklch(0.72 0.01 270.15); + --color-text-dimmed: hsl(224, 7%, 46%); + padding: var(--space-6); + font-family: var(--font-mono); + color: var(--color-text); + + a { + color: var(--color-text); + text-decoration: underline; + text-underline-offset: 0.1875rem; + } + + background: var(--color-bg); + position: fixed; + overflow-y: scroll; + inset: 0; + + [data-component="content"] { + max-width: 67.5rem; + margin: 0 auto; + border: 2px solid var(--color-border); + } + + [data-component="top"] { + padding: var(--space-12); + display: flex; + flex-direction: column; + align-items: start; + gap: var(--space-4); + + [data-slot="logo"] { + height: 70px; + } + + [data-slot="title"] { + font-size: var(--font-size-2xl); + text-transform: uppercase; + } + } + + [data-component="cta"] { + height: var(--space-19); + border-top: 2px solid var(--color-border); + display: flex; + + [data-slot="left"] { + display: flex; + padding: 0 var(--space-12); + text-transform: uppercase; + text-decoration: underline; + align-items: center; + justify-content: center; + text-underline-offset: 0.1875rem; + border-right: 2px solid var(--color-border); + + a { + color: var(--color-text); + text-decoration: underline; + } + } + + [data-slot="right"] { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + gap: 0.625rem; + padding: 0 var(--space-6); + } + + [data-slot="command"] { + all: unset; + display: flex; + align-items: center; + cursor: pointer; + color: var(--color-text-secondary); + font-size: 1.125rem; + font-family: var(--font-mono); + gap: var(--space-2); + } + + [data-slot="highlight"] { + color: var(--color-text); + font-weight: 500; + } + } + + [data-component="features"] { + border-top: 2px solid var(--color-border); + padding: var(--space-12); + + [data-slot="list"] { + padding-left: var(--space-4); + margin: 0; + list-style: disc; + + li { + margin-bottom: var(--space-4); + + strong { + text-transform: uppercase; + font-weight: 600; + } + } + + li:last-child { + margin-bottom: 0; + } + } + } + + [data-component="install"] { + border-top: 2px solid var(--color-border); + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: 1fr 1fr; + + @media (max-width: 40rem) { + grid-template-columns: 1fr; + grid-template-rows: auto; + } + } + + [data-component="title"] { + letter-spacing: -0.03125rem; + text-transform: uppercase; + font-weight: 400; + font-size: var(--font-size-md); + flex-shrink: 0; + color: oklch(0.55 0.02 269.87); + } + + [data-component="method"] { + padding: var(--space-4) var(--space-6); + display: flex; + flex-direction: column; + align-items: start; + gap: var(--space-3); + + &:nth-child(1) {} + + &:nth-child(2) { + border-left: 2px solid var(--color-border); + } + + &:nth-child(3) { + border-top: 2px solid var(--color-border); + } + + &:nth-child(4) { + border-top: 2px solid var(--color-border); + border-left: 2px solid var(--color-border); + } + + [data-slot="button"] { + all: unset; + cursor: pointer; + display: flex; + align-items: center; + color: var(--color-text-secondary); + gap: var(--space-2); + + strong { + color: var(--color-text); + font-weight: 500; + } + } + } + + [data-component="screenshots"] { + border-top: 2px solid var(--color-border); + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0; + + [data-slot="left"] { + padding: var(--space-8) var(--space-6); + display: flex; + flex-direction: column; + + img { + width: 100%; + height: "auto"; + } + } + + [data-slot="right"] { + display: grid; + grid-template-rows: 1fr 1fr; + border-left: 2px solid var(--color-border); + } + + [data-slot="filler"] { + display: flex; + flex-grow: 1; + align-items: center; + justify-content: center; + } + + [data-slot="cell"] { + padding: var(--space-8) var(--space-6); + display: flex; + flex-direction: column; + gap: var(--space-4); + + &:nth-child(2) { + border-top: 2px solid var(--color-border); + } + + img { + width: 80%; + height: "auto"; + } + } + } + + [data-component="copy-status"] { + [data-slot="copy"] { + display: block; + width: 16px; + height: 16px; + color: var(--color-text-dimmed); + + [data-copied] & { + display: none; + } + } + + [data-slot="check"] { + display: none; + width: 16px; + height: 16px; + color: white; + + [data-copied] & { + display: block; + } + } + } + + [data-component="footer"] { + border-top: 2px solid var(--color-border); + display: grid; + grid-template-columns: 1fr 1fr 1fr; + font-size: var(--font-size-lg); + height: var(--space-20); + + [data-slot="cell"] { + display: flex; + align-items: center; + justify-content: center; + border-right: 2px solid var(--color-border); + text-transform: uppercase; + + &:last-child { + border-right: none; + } + } + } +} diff --git a/cloud/app/src/routes/index.tsx b/cloud/app/src/routes/index.tsx new file mode 100644 index 000000000..90062d0b5 --- /dev/null +++ b/cloud/app/src/routes/index.tsx @@ -0,0 +1,169 @@ +import { Title } from "@solidjs/meta" +import { onCleanup, onMount } from "solid-js" +import "./index.css" +import logo from "../asset/logo-ornate-dark.svg" +import IMG_SPLASH from "../asset/screenshot-splash.webp" +import IMG_VSCODE from "../asset/screenshot-vscode.webp" +import IMG_GITHUB from "../asset/screenshot-github.webp" +import { IconCopy, IconCheck } from "../component/icon" + +function CopyStatus() { + return ( +
+ + +
+ ) +} + +export default function Home() { + onMount(() => { + const commands = document.querySelectorAll("[data-copy]") + for (const button of commands) { + const callback = () => { + const text = button.textContent + alert(text) + if (text) { + navigator.clipboard.writeText(text) + button.setAttribute("data-copied", "") + setTimeout(() => { + button.removeAttribute("data-copied") + }, 1500) + } + } + button.addEventListener("click", callback) + onCleanup(() => { + button.removeEventListener("click", callback) + }) + } + }) + + return ( +
+ opencode | AI coding agent built for the terminal +
+
+ logo +

The AI coding agent built for the terminal.

+
+ +
+ +
+ +
+
+ +
+
    +
  • + Native TUI: A responsive, native, themeable terminal UI. +
  • +
  • + LSP enabled: Automatically loads the right LSPs for the LLM. +
  • +
  • + Multi-session: Start multiple agents in parallel on the same project. +
  • +
  • + Shareable links: Share a link to any sessions for reference or to debug. +
  • +
  • + Claude Pro: Log in with Anthropic to use your Claude Pro or Max account. +
  • +
  • + Use any model: Supports 75+ LLM providers through{" "} + Models.dev, including local models. +
  • +
+
+ +
+
+

npm

+ +
+
+

bun

+ +
+
+

homebrew

+ +
+
+

paru

+ +
+
+ +
+
+
opencode TUI with tokyonight theme
+
+ opencode TUI with tokyonight theme +
+
+
+
+
opencode in VS Code
+
+ opencode in VS Code +
+
+
+
opencode in GitHub
+
+ opencode in GitHub +
+
+
+
+ + +
+
+ ) +} diff --git a/cloud/app/src/style/base.css b/cloud/app/src/style/base.css new file mode 100644 index 000000000..2c95cdbb7 --- /dev/null +++ b/cloud/app/src/style/base.css @@ -0,0 +1,8 @@ +html { + color-scheme: dark; + line-height: 1; +} + +body { + font-family: var(--font-sans); +} diff --git a/cloud/app/src/style/component/button.css b/cloud/app/src/style/component/button.css new file mode 100644 index 000000000..d10f7af53 --- /dev/null +++ b/cloud/app/src/style/component/button.css @@ -0,0 +1,102 @@ +[data-component="button"] { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--space-2); + padding: var(--space-3) var(--space-4); + border: 1px solid transparent; + border-radius: var(--space-2); + font-family: var(--font-sans); + font-size: var(--font-size-md); + font-weight: 500; + line-height: 1.25; + cursor: pointer; + transition: all 0.2s ease-in-out; + text-decoration: none; + user-select: none; + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + } + + &:focus { + outline: none; + box-shadow: 0 0 0 2px var(--color-primary); + } + + &[data-color="primary"] { + background-color: var(--color-primary); + color: var(--color-primary-text); + border-color: var(--color-primary); + + &:hover:not(:disabled) { + background-color: var(--color-primary-hover); + border-color: var(--color-primary-hover); + } + + &:active:not(:disabled) { + background-color: var(--color-primary-active); + border-color: var(--color-primary-active); + } + } + + &[data-color="danger"] { + background-color: var(--color-danger); + color: var(--color-danger-text); + border-color: var(--color-danger); + + &:hover:not(:disabled) { + background-color: var(--color-danger-hover); + border-color: var(--color-danger-hover); + } + + &:active:not(:disabled) { + background-color: var(--color-danger-active); + border-color: var(--color-danger-active); + } + + &:focus { + box-shadow: 0 0 0 2px var(--color-danger); + } + } + + &[data-color="warning"] { + background-color: var(--color-warning); + color: var(--color-warning-text); + border-color: var(--color-warning); + + &:hover:not(:disabled) { + background-color: var(--color-warning-hover); + border-color: var(--color-warning-hover); + } + + &:active:not(:disabled) { + background-color: var(--color-warning-active); + border-color: var(--color-warning-active); + } + + &:focus { + box-shadow: 0 0 0 2px var(--color-warning); + } + } + + &[data-size="small"] { + padding: var(--space-2) var(--space-3); + font-size: var(--font-size-sm); + gap: var(--space-1-5); + } + + &[data-size="large"] { + padding: var(--space-4) var(--space-6); + font-size: var(--font-size-lg); + gap: var(--space-3); + } + + [data-slot="icon"] { + display: flex; + align-items: center; + width: 1em; + height: 1em; + } +} diff --git a/cloud/app/src/style/index.css b/cloud/app/src/style/index.css new file mode 100644 index 000000000..832a901e8 --- /dev/null +++ b/cloud/app/src/style/index.css @@ -0,0 +1,8 @@ +@import "./token/color.css"; +@import "./token/font.css"; +@import "./token/space.css"; + +@import "./component/button.css"; + +@import "./reset.css"; +@import "./base.css"; diff --git a/cloud/app/src/style/reset.css b/cloud/app/src/style/reset.css new file mode 100644 index 000000000..d331ed724 --- /dev/null +++ b/cloud/app/src/style/reset.css @@ -0,0 +1,76 @@ +/* 1. Use a more-intuitive box-sizing model */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +/* 2. Remove default margin */ +* { + margin: 0; +} + +/* 3. Enable keyword animations */ +@media (prefers-reduced-motion: no-preference) { + html { + interpolate-size: allow-keywords; + } +} + +body { + /* 4. Add accessible line-height */ + line-height: 1.5; + /* 5. Improve text rendering */ + -webkit-font-smoothing: antialiased; +} + +/* 6. Improve media defaults */ +img, +picture, +video, +canvas, +svg { + display: block; + max-width: 100%; +} + +/* 7. Inherit fonts for form controls */ +input, +button, +textarea, +select { + font: inherit; +} + +/* 8. Avoid text overflows */ +p, +h1, +h2, +h3, +h4, +h5, +h6 { + overflow-wrap: break-word; +} + +/* 9. Improve line wrapping */ +p { + text-wrap: pretty; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + text-wrap: balance; +} + +/* + 10. Create a root stacking context +*/ +#root, +#__next { + isolation: isolate; +} diff --git a/cloud/app/src/style/token/color.css b/cloud/app/src/style/token/color.css new file mode 100644 index 000000000..5382321e3 --- /dev/null +++ b/cloud/app/src/style/token/color.css @@ -0,0 +1,90 @@ +body { + --color-white: #ffffff; + --color-black: #000000; +} + +[data-color-mode="dark"] { + /* OpenCode theme colors */ + --color-bg: #0c0c0e; + --color-bg-surface: #161618; + --color-bg-elevated: #1c1c1f; + + --color-text: #ffffff; + --color-text-muted: #a1a1a6; + --color-text-disabled: #68686f; + + --color-accent: #007aff; + --color-accent-hover: #0056b3; + --color-accent-active: #004085; + + --color-success: #30d158; + --color-warning: #ff9f0a; + --color-danger: #ff453a; + + --color-border: #38383a; + --color-border-muted: #2c2c2e; + + /* Button colors */ + --color-primary: var(--color-accent); + --color-primary-hover: var(--color-accent-hover); + --color-primary-active: var(--color-accent-active); + --color-primary-text: #ffffff; + + --color-danger: #ff453a; + --color-danger-hover: #d70015; + --color-danger-active: #a50011; + --color-danger-text: #ffffff; + + --color-warning: #ff9f0a; + --color-warning-hover: #cc7f08; + --color-warning-active: #995f06; + --color-warning-text: #000000; + + /* Surface colors */ + --color-surface: var(--color-bg-surface); + --color-surface-hover: var(--color-bg-elevated); + --color-border: var(--color-border); +} + +[data-color-mode="light"] { + /* OpenCode light theme colors */ + --color-bg: #ffffff; + --color-bg-surface: #f5f5f7; + --color-bg-elevated: #ffffff; + + --color-text: #1d1d1f; + --color-text-muted: #6e6e73; + --color-text-disabled: #86868b; + + --color-accent: #007aff; + --color-accent-hover: #0056b3; + --color-accent-active: #004085; + + --color-success: #30d158; + --color-warning: #ff9f0a; + --color-danger: #ff3b30; + + --color-border: #d2d2d7; + --color-border-muted: #e5e5ea; + + /* Button colors */ + --color-primary: var(--color-accent); + --color-primary-hover: var(--color-accent-hover); + --color-primary-active: var(--color-accent-active); + --color-primary-text: #ffffff; + + --color-danger: #ff3b30; + --color-danger-hover: #d70015; + --color-danger-active: #a50011; + --color-danger-text: #ffffff; + + --color-warning: #ff9f0a; + --color-warning-hover: #cc7f08; + --color-warning-active: #995f06; + --color-warning-text: #000000; + + /* Surface colors */ + --color-surface: var(--color-bg-surface); + --color-surface-hover: var(--color-bg-elevated); + --color-border: var(--color-border); +} diff --git a/cloud/app/src/style/token/font.css b/cloud/app/src/style/token/font.css new file mode 100644 index 000000000..1852af5b0 --- /dev/null +++ b/cloud/app/src/style/token/font.css @@ -0,0 +1,18 @@ +body { + --font-size-2xs: 0.6875rem; + --font-size-xs: 0.75rem; + --font-size-sm: 0.8125rem; + --font-size-md: 0.9375rem; + --font-size-lg: 1.125rem; + --font-size-xl: 1.25rem; + --font-size-2xl: 1.5rem; + --font-size-3xl: 1.875rem; + --font-size-4xl: 2.25rem; + --font-size-5xl: 3rem; + --font-size-6xl: 3.75rem; + --font-size-7xl: 4.5rem; + --font-size-8xl: 6rem; + --font-size-9xl: 8rem; + --font-mono: IBM Plex Mono; + --font-sans: Inter; +} diff --git a/cloud/app/src/style/token/space.css b/cloud/app/src/style/token/space.css new file mode 100644 index 000000000..633c1238c --- /dev/null +++ b/cloud/app/src/style/token/space.css @@ -0,0 +1,41 @@ +body { + --space-0: 0; + --space-px: 1px; + --space-0-5: 0.125rem; + --space-1: 0.25rem; + --space-1-5: 0.375rem; + --space-2: 0.5rem; + --space-2-5: 0.625rem; + --space-3: 0.75rem; + --space-3-5: 0.875rem; + --space-4: 1rem; + --space-4-5: 1.125rem; + --space-5: 1.25rem; + --space-6: 1.5rem; + --space-7: 1.75rem; + --space-8: 2rem; + --space-9: 2.25rem; + --space-10: 2.5rem; + --space-11: 2.75rem; + --space-12: 3rem; + --space-14: 3.5rem; + --space-16: 4rem; + --space-17: 4.25rem; + --space-18: 4.5rem; + --space-19: 4.75rem; + --space-20: 5rem; + --space-24: 6rem; + --space-28: 7rem; + --space-32: 8rem; + --space-36: 9rem; + --space-40: 10rem; + --space-44: 11rem; + --space-48: 12rem; + --space-52: 13rem; + --space-56: 14rem; + --space-60: 15rem; + --space-64: 16rem; + --space-72: 18rem; + --space-80: 20rem; + --space-96: 24rem; +} diff --git a/cloud/app/tsconfig.json b/cloud/app/tsconfig.json new file mode 100644 index 000000000..7d5871a07 --- /dev/null +++ b/cloud/app/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "allowJs": true, + "strict": true, + "noEmit": true, + "types": ["vinxi/types/client"], + "isolatedModules": true, + "paths": { + "~/*": ["./src/*"] + } + } +} diff --git a/cloud/web/src/ui/style/token/space.css b/cloud/web/src/ui/style/token/space.css index b1e492f49..4a061d756 100644 --- a/cloud/web/src/ui/style/token/space.css +++ b/cloud/web/src/ui/style/token/space.css @@ -20,6 +20,7 @@ --space-12: 3rem; --space-14: 3.5rem; --space-16: 4rem; + --space-18: 4.5rem; --space-20: 5rem; --space-24: 6rem; --space-28: 7rem; -- cgit v1.2.3