David Hill 2 месяцев назад
Родитель
Сommit
fba0aad2f8

BIN
packages/console/app/src/asset/lander/desktop-app-icon.png


+ 104 - 3
packages/console/app/src/routes/index.css

@@ -16,6 +16,8 @@
   --color-background-strong-hover: hsl(0, 5%, 18%);
   --color-background-strong-hover: hsl(0, 5%, 18%);
   --color-background-interactive: hsl(62, 84%, 88%);
   --color-background-interactive: hsl(62, 84%, 88%);
   --color-background-interactive-weaker: hsl(64, 74%, 95%);
   --color-background-interactive-weaker: hsl(64, 74%, 95%);
+  --color-surface-raised-base: hsla(0, 100%, 3%, 0.01);
+  --color-surface-raised-base-active: hsla(0, 100%, 17%, 0.06);
 
 
   --color-text: hsl(0, 1%, 39%);
   --color-text: hsl(0, 1%, 39%);
   --color-text-weak: hsl(0, 1%, 60%);
   --color-text-weak: hsl(0, 1%, 60%);
@@ -24,7 +26,7 @@
   --color-text-inverted: hsl(0, 20%, 99%);
   --color-text-inverted: hsl(0, 20%, 99%);
 
 
   --color-border: hsl(30, 2%, 81%);
   --color-border: hsl(30, 2%, 81%);
-  --color-border-weak: hsl(0, 1%, 85%);
+  --color-border-weak: hsla(0, 100%, 3%, 0.12);
 
 
   --color-icon: hsl(0, 1%, 55%);
   --color-icon: hsl(0, 1%, 55%);
 }
 }
@@ -62,6 +64,14 @@ body {
   }
   }
 }
 }
 
 
+[data-slot="br"] {
+  display: block;
+
+  @media (max-width: 60rem) {
+    display: none;
+  }
+}
+
 [data-page="opencode"] {
 [data-page="opencode"] {
   background: var(--color-background);
   background: var(--color-background);
   --padding: 5rem;
   --padding: 5rem;
@@ -465,6 +475,68 @@ body {
     }
     }
   }
   }
 
 
+  [data-component="desktop-app-available"] {
+    background: var(--color-surface-raised-base);
+    border: 1px solid var(--color-border-weak);
+    display: flex;
+    margin-bottom: 48px;
+
+    [data-slot="desktop-icon"] {
+      border-right: 1px solid var(--color-border-weak);
+      width: 56px;
+      height: 72px;
+      background: var(--color-surface-raised-base-active);
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      position: relative;
+
+      img {
+        width: 40px;
+        height: 40px;
+        opacity: 100%;
+      }
+
+      [data-slot="dot"] {
+        border-radius: 100px;
+        width: 6px;
+        height: 6px;
+        background: var(--color-background-strong);
+        position: absolute;
+        bottom: 5px;
+        left: 24px;
+        opacity: 0;
+      }
+    }
+
+    &:has([data-slot="desktop-copy"]:hover) [data-slot="desktop-icon"] img {
+      animation: iconBounce 1s ease-in-out forwards;
+    }
+
+    &:has([data-slot="desktop-copy"]:hover) [data-slot="desktop-icon"] [data-slot="dot"] {
+      opacity: 0.4;
+      transition: opacity 0.3s ease-out 1s;
+    }
+
+
+
+    [data-slot="desktop-copy"] {
+      display: flex;
+      align-items: center;
+      padding: 20px;
+      gap: 16px;
+
+      span {
+        color: var(--color-text-strong);
+        line-height: 1;
+      }
+
+      a {
+        color: var(--color-text-weak);
+      }
+    }
+  }
+
   [data-slot="hero-copy"] {
   [data-slot="hero-copy"] {
     [data-slot="releases"] {
     [data-slot="releases"] {
       background: none;
       background: none;
@@ -502,7 +574,7 @@ body {
 
 
     p {
     p {
       color: var(--color-text);
       color: var(--color-text);
-      margin-bottom: 40px;
+      margin-bottom: 32px;
       max-width: 82%;
       max-width: 82%;
 
 
       @media (max-width: 50rem) {
       @media (max-width: 50rem) {
@@ -518,7 +590,6 @@ body {
       border-radius: 4px;
       border-radius: 4px;
       font-weight: 500;
       font-weight: 500;
       cursor: pointer;
       cursor: pointer;
-      margin-bottom: 80px;
       display: flex;
       display: flex;
       width: fit-content;
       width: fit-content;
       gap: 12px;
       gap: 12px;
@@ -1140,3 +1211,33 @@ body {
     }
     }
   }
   }
 }
 }
+
+@keyframes iconBounce {
+  0%, 100% {
+    transform: translateY(0);
+  }
+  50% {
+    transform: translateY(-10px);
+  }
+}
+  25% {
+    transform: translateY(-10px);
+  }
+  50% {
+    transform: translateY(0);
+  }
+  75% {
+    transform: translateY(-10px);
+  }
+}
+
+@keyframes dotAppear {
+  0% {
+    opacity: 0;
+    transform: scale(0);
+  }
+  100% {
+    opacity: 0.5;
+    transform: scale(1);
+  }
+}

+ 109 - 90
packages/console/app/src/routes/index.tsx

@@ -3,6 +3,7 @@ import { Title, Meta, Link } from "@solidjs/meta"
 // import { HttpHeader } from "@solidjs/start"
 // import { HttpHeader } from "@solidjs/start"
 import video from "../asset/lander/opencode-min.mp4"
 import video from "../asset/lander/opencode-min.mp4"
 import videoPoster from "../asset/lander/opencode-poster.png"
 import videoPoster from "../asset/lander/opencode-poster.png"
+import desktopAppIcon from "../asset/lander/desktop-app-icon.png"
 import { IconCopy, IconCheck } from "../component/icon"
 import { IconCopy, IconCheck } from "../component/icon"
 import { A, createAsync } from "@solidjs/router"
 import { A, createAsync } from "@solidjs/router"
 import { EmailSignup } from "~/component/email-signup"
 import { EmailSignup } from "~/component/email-signup"
@@ -14,6 +15,7 @@ import { Legal } from "~/component/legal"
 import { github } from "~/lib/github"
 import { github } from "~/lib/github"
 import { createMemo } from "solid-js"
 import { createMemo } from "solid-js"
 import { config } from "~/config"
 import { config } from "~/config"
+import avatarDavid from "~/asset/lander/avatar-david.png"
 
 
 function CopyStatus() {
 function CopyStatus() {
   return (
   return (
@@ -52,100 +54,117 @@ export default function Home() {
 
 
         <div data-component="content">
         <div data-component="content">
           <section data-component="hero">
           <section data-component="hero">
+            <div data-component="desktop-app-available">
+              <div data-slot="desktop-icon">
+                <img src={desktopAppIcon} alt="" />
+                <div data-slot="dot"></div>
+              </div>
+              <div data-slot="desktop-copy">
+                <span>Now available on desktop for macOS, Windows, and Linux.</span> <a href="/download">Learn more</a>
+              </div>
+            </div>
+
             <div data-slot="hero-copy">
             <div data-slot="hero-copy">
-              <a data-slot="releases" href={release()?.url ?? `${config.github.repoUrl}/releases`} target="_blank">
-                What’s new in {release()?.name ?? "the latest release"}
-              </a>
-              <h1>The open source coding agent</h1>
+              {/*<a data-slot="releases"*/}
+              {/*   href={release()?.url ?? `${config.github.repoUrl}/releases`}*/}
+              {/*   target="_blank">*/}
+              {/*  What’s new in {release()?.name ?? "the latest release"}*/}
+              {/*</a>*/}
+              <h1>The open source AI coding agent</h1>
               <p>
               <p>
-                OpenCode includes free models or connect from any provider to <br />
-                use other models, including Claude, GPT, Gemini and more.
+                Free models by default or connect any model from any provider, <span data-slot="br"></span>including
+                Claude, GPT, Gemini and more.
               </p>
               </p>
+              <a href="/download">
+                <span>Get started for free</span>
+                <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+                  <path
+                    d="M6.5 12L17 12M13 16.5L17.5 12L13 7.5"
+                    stroke="currentColor"
+                    stroke-width="1.5"
+                    stroke-linecap="square"
+                  />
+                </svg>
+              </a>
             </div>
             </div>
-            <p data-slot="installation-instructions">Install and use. No account, no email, and no credit card.</p>
-            <div data-slot="installation">
-              <Tabs
-                as="section"
-                aria-label="Install options"
-                class="tabs"
-                data-component="tabs"
-                data-active="curl"
-                defaultValue="curl"
-              >
-                <Tabs.List data-slot="tablist">
-                  <Tabs.Trigger value="curl" data-slot="tab">
-                    curl
-                  </Tabs.Trigger>
-                  <Tabs.Trigger value="npm" data-slot="tab">
-                    npm
-                  </Tabs.Trigger>
-                  <Tabs.Trigger value="bun" data-slot="tab">
-                    bun
-                  </Tabs.Trigger>
-                  <Tabs.Trigger value="brew" data-slot="tab">
-                    brew
-                  </Tabs.Trigger>
-                  <Tabs.Trigger value="paru" data-slot="tab">
-                    paru
-                  </Tabs.Trigger>
-                  <Tabs.Indicator />
-                </Tabs.List>
-                <div data-slot="panels">
-                  <Tabs.Content as="pre" data-slot="panel" value="curl">
-                    <button data-copy data-slot="command" onClick={handleCopyClick}>
-                      <span data-slot="command-script">
-                        <span>curl -fsSL </span>
-                        <span data-slot="protocol">https://</span>
-                        <span data-slot="highlight">opencode.ai/install</span>
-                        <span> | bash</span>
-                      </span>
-                      <CopyStatus />
-                    </button>
-                  </Tabs.Content>
-                  <Tabs.Content as="pre" data-slot="panel" value="npm">
-                    <button data-copy data-slot="command" onClick={handleCopyClick}>
-                      <span>
-                        <span data-slot="protocol">npm i -g </span>
-                        <span data-slot="highlight">opencode-ai</span>
-                      </span>
-                      <CopyStatus />
-                    </button>
-                  </Tabs.Content>
-                  <Tabs.Content as="pre" data-slot="panel" value="bun">
-                    <button data-copy data-slot="command" onClick={handleCopyClick}>
-                      <span>
-                        <span data-slot="protocol">bun add -g </span>
-                        <span data-slot="highlight">opencode-ai</span>
-                      </span>
-                      <CopyStatus />
-                    </button>
-                  </Tabs.Content>
-                  <Tabs.Content as="pre" data-slot="panel" value="brew">
-                    <button data-copy data-slot="command" onClick={handleCopyClick}>
-                      <span>
-                        <span data-slot="protocol">brew install </span>
-                        <span data-slot="highlight">opencode</span>
-                      </span>
-                      <CopyStatus />
-                    </button>
-                  </Tabs.Content>
-                  <Tabs.Content as="pre" data-slot="panel" value="paru">
-                    <button data-copy data-slot="command" onClick={handleCopyClick}>
-                      <span>
-                        <span data-slot="protocol">paru -S </span>
-                        <span data-slot="highlight">opencode</span>
-                      </span>
-                      <CopyStatus />
-                    </button>
-                  </Tabs.Content>
-                </div>
-              </Tabs>
-            </div>
-            <p data-slot="installation-options">
-              Available in terminal, web, and desktop (coming soon).
-              <br />
-              Extensions for VS Code, Cursor, Windsurf, and more.
-            </p>
+            {/*<div data-slot="installation">*/}
+            {/*  <Tabs*/}
+            {/*    as="section"*/}
+            {/*    aria-label="Install options"*/}
+            {/*    class="tabs"*/}
+            {/*    data-component="tabs"*/}
+            {/*    data-active="curl"*/}
+            {/*    defaultValue="curl"*/}
+            {/*  >*/}
+            {/*    <Tabs.List data-slot="tablist">*/}
+            {/*      <Tabs.Trigger value="curl" data-slot="tab">*/}
+            {/*        curl*/}
+            {/*      </Tabs.Trigger>*/}
+            {/*      <Tabs.Trigger value="npm" data-slot="tab">*/}
+            {/*        npm*/}
+            {/*      </Tabs.Trigger>*/}
+            {/*      <Tabs.Trigger value="bun" data-slot="tab">*/}
+            {/*        bun*/}
+            {/*      </Tabs.Trigger>*/}
+            {/*      <Tabs.Trigger value="brew" data-slot="tab">*/}
+            {/*        brew*/}
+            {/*      </Tabs.Trigger>*/}
+            {/*      <Tabs.Trigger value="paru" data-slot="tab">*/}
+            {/*        paru*/}
+            {/*      </Tabs.Trigger>*/}
+            {/*      <Tabs.Indicator />*/}
+            {/*    </Tabs.List>*/}
+            {/*    <div data-slot="panels">*/}
+            {/*      <Tabs.Content as="pre" data-slot="panel" value="curl">*/}
+            {/*        <button data-copy data-slot="command" onClick={handleCopyClick}>*/}
+            {/*          <span data-slot="command-script">*/}
+            {/*            <span>curl -fsSL </span>*/}
+            {/*            <span data-slot="protocol">https://</span>*/}
+            {/*            <span data-slot="highlight">opencode.ai/install</span>*/}
+            {/*            <span> | bash</span>*/}
+            {/*          </span>*/}
+            {/*          <CopyStatus />*/}
+            {/*        </button>*/}
+            {/*      </Tabs.Content>*/}
+            {/*      <Tabs.Content as="pre" data-slot="panel" value="npm">*/}
+            {/*        <button data-copy data-slot="command" onClick={handleCopyClick}>*/}
+            {/*          <span>*/}
+            {/*            <span data-slot="protocol">npm i -g </span>*/}
+            {/*            <span data-slot="highlight">opencode-ai</span>*/}
+            {/*          </span>*/}
+            {/*          <CopyStatus />*/}
+            {/*        </button>*/}
+            {/*      </Tabs.Content>*/}
+            {/*      <Tabs.Content as="pre" data-slot="panel" value="bun">*/}
+            {/*        <button data-copy data-slot="command" onClick={handleCopyClick}>*/}
+            {/*          <span>*/}
+            {/*            <span data-slot="protocol">bun add -g </span>*/}
+            {/*            <span data-slot="highlight">opencode-ai</span>*/}
+            {/*          </span>*/}
+            {/*          <CopyStatus />*/}
+            {/*        </button>*/}
+            {/*      </Tabs.Content>*/}
+            {/*      <Tabs.Content as="pre" data-slot="panel" value="brew">*/}
+            {/*        <button data-copy data-slot="command" onClick={handleCopyClick}>*/}
+            {/*          <span>*/}
+            {/*            <span data-slot="protocol">brew install </span>*/}
+            {/*            <span data-slot="highlight">opencode</span>*/}
+            {/*          </span>*/}
+            {/*          <CopyStatus />*/}
+            {/*        </button>*/}
+            {/*      </Tabs.Content>*/}
+            {/*      <Tabs.Content as="pre" data-slot="panel" value="paru">*/}
+            {/*        <button data-copy data-slot="command" onClick={handleCopyClick}>*/}
+            {/*          <span>*/}
+            {/*            <span data-slot="protocol">paru -S </span>*/}
+            {/*            <span data-slot="highlight">opencode</span>*/}
+            {/*          </span>*/}
+            {/*          <CopyStatus />*/}
+            {/*        </button>*/}
+            {/*      </Tabs.Content>*/}
+            {/*    </div>*/}
+            {/*  </Tabs>*/}
+            {/*</div>*/}
           </section>
           </section>
 
 
           <section data-component="video">
           <section data-component="video">