瀏覽代碼

feat(console): add desktop tabs promo

David Hill 1 月之前
父節點
當前提交
a4981cad43

+ 2 - 0
packages/console/app/src/app.tsx

@@ -9,6 +9,7 @@ import "./app.css"
 import { LanguageProvider } from "~/context/language"
 import { I18nProvider, useI18n } from "~/context/i18n"
 import { strip } from "~/lib/language"
+import { DesktopPromo } from "~/component/desktop-promo"
 
 function AppMeta() {
   const i18n = useI18n()
@@ -33,6 +34,7 @@ export default function App() {
             <MetaProvider>
               <AppMeta />
               <Suspense>{props.children}</Suspense>
+              <DesktopPromo />
             </MetaProvider>
           </I18nProvider>
         </LanguageProvider>

二進制
packages/console/app/src/asset/lander/desktop-tabs-landscape.mp4


+ 101 - 0
packages/console/app/src/component/desktop-promo.css

@@ -0,0 +1,101 @@
+[data-component="desktop-promo"] {
+  --promo-background: hsl(0, 20%, 99%);
+  --promo-background-weak: hsl(0, 8%, 97%);
+  --promo-text: hsl(0, 1%, 39%);
+  --promo-text-strong: hsl(0, 5%, 12%);
+  --promo-border: hsla(0, 100%, 3%, 0.12);
+
+  position: fixed;
+  z-index: 20;
+  right: 1.5rem;
+  bottom: 1.5rem;
+  width: min(28rem, calc(100vw - 2rem));
+  padding: 4px;
+  overflow: hidden;
+  color: var(--promo-text);
+  border: 1px solid var(--promo-border);
+  border-radius: 8px;
+  background: var(--promo-background);
+  box-shadow: 0 0.75rem 2rem rgb(0 0 0 / 15%);
+  font-family: var(--font-mono);
+
+  @media (prefers-color-scheme: dark) {
+    --promo-background: hsl(0, 9%, 7%);
+    --promo-background-weak: hsl(0, 6%, 10%);
+    --promo-text: hsl(0, 4%, 71%);
+    --promo-text-strong: hsl(0, 15%, 94%);
+    --promo-border: hsl(0, 4%, 23%);
+  }
+
+  @media (max-width: 40rem) {
+    right: 1rem;
+    bottom: 1rem;
+  }
+
+  [data-slot="desktop-promo-link"] {
+    display: block;
+    color: var(--promo-text);
+    text-decoration: none;
+  }
+
+  [data-slot="desktop-promo-link"]:focus-visible {
+    outline: 2px solid var(--promo-text-strong);
+    outline-offset: -3px;
+  }
+
+  video {
+    display: block;
+    width: 100%;
+    aspect-ratio: 16 / 9;
+    object-fit: cover;
+    border-radius: 4px;
+    background: var(--promo-background-weak);
+  }
+
+  [data-slot="desktop-promo-copy"] {
+    display: flex;
+    flex-direction: column;
+    gap: 0.35rem;
+    padding: 1rem;
+    font-size: 0.875rem;
+    line-height: 1.4;
+  }
+
+  [data-slot="desktop-promo-copy"] strong {
+    color: var(--promo-text-strong);
+    font-weight: 500;
+  }
+
+  [data-slot="desktop-promo-close"] {
+    position: absolute;
+    top: 0.5rem;
+    right: 0.5rem;
+    display: grid;
+    width: 2rem;
+    height: 2rem;
+    padding: 0;
+    place-items: center;
+    cursor: pointer;
+    color: white;
+    border: none;
+    border-radius: 0.25rem;
+    background: rgb(0 0 0 / 70%);
+    opacity: 0;
+    transition: opacity 150ms ease, background 150ms ease;
+  }
+
+  &:hover [data-slot="desktop-promo-close"],
+  [data-slot="desktop-promo-close"]:focus-visible {
+    opacity: 1;
+  }
+
+  [data-slot="desktop-promo-close"]:hover {
+    background: rgb(0 0 0 / 90%);
+  }
+
+  @media (hover: none) {
+    [data-slot="desktop-promo-close"] {
+      opacity: 1;
+    }
+  }
+}

+ 47 - 0
packages/console/app/src/component/desktop-promo.tsx

@@ -0,0 +1,47 @@
+import "./desktop-promo.css"
+import { A, useLocation } from "@solidjs/router"
+import { createSignal, Show } from "solid-js"
+import { getRequestEvent } from "solid-js/web"
+import desktopPromoVideo from "~/asset/lander/desktop-tabs-landscape.mp4"
+import { useI18n } from "~/context/i18n"
+import { useLanguage } from "~/context/language"
+import { strip } from "~/lib/language"
+
+export function DesktopPromo() {
+  const i18n = useI18n()
+  const language = useLanguage()
+  const location = useLocation()
+  const [visible, setVisible] = createSignal(true)
+  const request = getRequestEvent()?.request
+  const hostname = request ? new URL(request.url).hostname : typeof window === "object" ? window.location.hostname : ""
+  const primaryHost =
+    hostname === "opencode.ai" || hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1"
+
+  return (
+    <Show
+      when={
+        visible() &&
+        primaryHost &&
+        strip(location.pathname) !== "/download" &&
+        !strip(location.pathname).startsWith("/download/")
+      }
+    >
+      <aside data-component="desktop-promo">
+        <A href={language.route("/download")} data-slot="desktop-promo-link">
+          <video src={desktopPromoVideo} autoplay playsinline loop muted preload="metadata" aria-hidden="true" />
+          <span data-slot="desktop-promo-copy">
+            <strong>{i18n.t("home.promo.title")}</strong>
+            <span>{i18n.t("home.promo.body")}</span>
+            <span>{i18n.t("home.promo.cta")}</span>
+          </span>
+        </A>
+        <button type="button" data-slot="desktop-promo-close" onClick={() => setVisible(false)}>
+          <span class="sr-only">{i18n.t("home.promo.close")}</span>
+          <svg width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
+            <path d="M5 5L15 15M15 5L5 15" stroke="currentColor" stroke-width="1.5" />
+          </svg>
+        </button>
+      </aside>
+    </Show>
+  )
+}

+ 4 - 0
packages/console/app/src/i18n/ar.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "على macOS، Windows، وLinux",
   "home.banner.downloadNow": "حمّل الآن",
   "home.banner.downloadBetaNow": "حمّل النسخة التجريبية لتطبيق سطح المكتب الآن",
+  "home.promo.title": "نقدّم علامات التبويب لتطبيق سطح المكتب",
+  "home.promo.body": "تنقّل بين جلسات متعددة واعمل عليها بسهولة.",
+  "home.promo.cta": "حدّث تطبيق سطح المكتب إلى أحدث إصدار للبدء.",
+  "home.promo.close": "إغلاق إعلان تطبيق سطح المكتب",
 
   "home.hero.title": "وكيل برمجة بالذكاء الاصطناعي مفتوح المصدر",
   "home.hero.subtitle.a": "نماذج مجانية مضمّنة أو اربط أي نموذج من أي مزوّد،",

+ 4 - 0
packages/console/app/src/i18n/br.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "no macOS, Windows e Linux",
   "home.banner.downloadNow": "Baixar agora",
   "home.banner.downloadBetaNow": "Baixe agora o beta do desktop",
+  "home.promo.title": "Conheça as abas no app desktop",
+  "home.promo.body": "Trabalhe com facilidade em várias sessões.",
+  "home.promo.cta": "Atualize o app desktop para a versão mais recente para começar.",
+  "home.promo.close": "Fechar anúncio do app desktop",
 
   "home.hero.title": "O agente de codificação de código aberto com IA",
   "home.hero.subtitle.a": "Modelos grátis incluídos ou conecte qualquer modelo de qualquer provedor,",

+ 4 - 0
packages/console/app/src/i18n/da.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "på macOS, Windows og Linux",
   "home.banner.downloadNow": "Download nu",
   "home.banner.downloadBetaNow": "Download desktop-betaen nu",
+  "home.promo.title": "Introduktion af Tabs til Desktop",
+  "home.promo.body": "Arbejd nemt på tværs af flere sessioner.",
+  "home.promo.cta": "Opdater til den nyeste Desktop-app for at komme i gang.",
+  "home.promo.close": "Luk meddelelsen om Desktop-appen",
 
   "home.hero.title": "Den open source AI-kodningsagent",
   "home.hero.subtitle.a": "Gratis modeller inkluderet, eller forbind enhver model fra enhver udbyder,",

+ 4 - 0
packages/console/app/src/i18n/de.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "auf macOS, Windows und Linux",
   "home.banner.downloadNow": "Jetzt herunterladen",
   "home.banner.downloadBetaNow": "Desktop-Beta jetzt herunterladen",
+  "home.promo.title": "Neu: Tabs für Desktop",
+  "home.promo.body": "Arbeite mühelos in mehreren Sitzungen.",
+  "home.promo.cta": "Aktualisiere auf die neueste Desktop-App, um loszulegen.",
+  "home.promo.close": "Ankündigung zur Desktop-App schließen",
 
   "home.hero.title": "Der Open-Source AI-Coding-Agent",
   "home.hero.subtitle.a": "Kostenlose Modelle inklusive oder verbinde jedes Modell eines beliebigen Anbieters,",

+ 5 - 0
packages/console/app/src/i18n/en.ts

@@ -107,6 +107,11 @@ export const dict = {
   "home.banner.downloadNow": "Download now",
   "home.banner.downloadBetaNow": "Download the desktop beta now",
 
+  "home.promo.title": "Introducing Tabs for Desktop",
+  "home.promo.body": "Work across multiple sessions with ease.",
+  "home.promo.cta": "Update to the latest desktop app to get started.",
+  "home.promo.close": "Dismiss desktop app announcement",
+
   "home.hero.title": "The open source AI coding agent",
   "home.hero.subtitle.a": "Free models included or connect any model from any provider,",
   "home.hero.subtitle.b": "including Claude, GPT, Gemini and more.",

+ 4 - 0
packages/console/app/src/i18n/es.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "en macOS, Windows y Linux",
   "home.banner.downloadNow": "Descargar ahora",
   "home.banner.downloadBetaNow": "Descargar la beta de escritorio ahora",
+  "home.promo.title": "Presentamos Tabs para Desktop",
+  "home.promo.body": "Trabaja fácilmente en varias sesiones.",
+  "home.promo.cta": "Actualiza a la última versión de la aplicación Desktop para empezar.",
+  "home.promo.close": "Cerrar el anuncio de la aplicación Desktop",
 
   "home.hero.title": "El agente de codificación IA de código abierto",
   "home.hero.subtitle.a": "Modelos gratuitos incluidos o conecta cualquier modelo de cualquier proveedor,",

+ 4 - 0
packages/console/app/src/i18n/fr.ts

@@ -104,6 +104,10 @@ export const dict = {
   "home.banner.platforms": "sur macOS, Windows et Linux",
   "home.banner.downloadNow": "Télécharger maintenant",
   "home.banner.downloadBetaNow": "Télécharger la bêta desktop maintenant",
+  "home.promo.title": "Découvrez Tabs pour Desktop",
+  "home.promo.body": "Travaillez facilement dans plusieurs sessions.",
+  "home.promo.cta": "Mettez à jour l’application Desktop pour commencer.",
+  "home.promo.close": "Fermer l’annonce de l’application Desktop",
 
   "home.hero.title": "L'agent de code IA open source",
   "home.hero.subtitle.a":

+ 4 - 0
packages/console/app/src/i18n/it.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "su macOS, Windows e Linux",
   "home.banner.downloadNow": "Scarica ora",
   "home.banner.downloadBetaNow": "Scarica ora la beta desktop",
+  "home.promo.title": "Scopri Tabs per Desktop",
+  "home.promo.body": "Lavora facilmente su più sessioni.",
+  "home.promo.cta": "Aggiorna l’app Desktop all’ultima versione per iniziare.",
+  "home.promo.close": "Chiudi l’annuncio dell’app Desktop",
 
   "home.hero.title": "L'agente di coding IA open source",
   "home.hero.subtitle.a": "Modelli gratuiti inclusi o collega qualsiasi modello da qualsiasi provider,",

+ 4 - 0
packages/console/app/src/i18n/ja.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "macOS、Windows、Linux で",
   "home.banner.downloadNow": "今すぐダウンロード",
   "home.banner.downloadBetaNow": "デスクトップベータ版を今すぐダウンロード",
+  "home.promo.title": "デスクトップ版にタブが登場",
+  "home.promo.body": "複数のセッションを簡単に切り替えて作業できます。",
+  "home.promo.cta": "利用するには、デスクトップアプリを最新版にアップデートしてください。",
+  "home.promo.close": "デスクトップアプリのお知らせを閉じる",
 
   "home.hero.title": "オープンソースのAIコーディングエージェント",
   "home.hero.subtitle.a": "無料モデルが含まれています。また、任意のプロバイダーの任意のモデルに接続でき、",

+ 4 - 0
packages/console/app/src/i18n/ko.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "macOS, Windows, Linux 지원",
   "home.banner.downloadNow": "지금 다운로드",
   "home.banner.downloadBetaNow": "데스크톱 베타 다운로드",
+  "home.promo.title": "데스크톱 탭을 소개합니다",
+  "home.promo.body": "여러 세션을 간편하게 오가며 작업하세요.",
+  "home.promo.cta": "최신 데스크톱 앱으로 업데이트하고 시작하세요.",
+  "home.promo.close": "데스크톱 앱 안내 닫기",
 
   "home.hero.title": "오픈 소스 AI 코딩 에이전트",
   "home.hero.subtitle.a": "무료 모델이 포함되어 있으며, 어떤 제공자의 모델이든 연결 가능합니다.",

+ 4 - 0
packages/console/app/src/i18n/no.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "på macOS, Windows og Linux",
   "home.banner.downloadNow": "Last ned nå",
   "home.banner.downloadBetaNow": "Last ned desktop-betaen nå",
+  "home.promo.title": "Vi introduserer Tabs for Desktop",
+  "home.promo.body": "Jobb enkelt på tvers av flere økter.",
+  "home.promo.cta": "Oppdater til den nyeste Desktop-appen for å komme i gang.",
+  "home.promo.close": "Lukk kunngjøringen om Desktop-appen",
 
   "home.hero.title": "Den åpne kildekode AI-kodingsagenten",
   "home.hero.subtitle.a":

+ 4 - 0
packages/console/app/src/i18n/pl.ts

@@ -105,6 +105,10 @@ export const dict = {
   "home.banner.platforms": "na macOS, Windows i Linux",
   "home.banner.downloadNow": "Pobierz teraz",
   "home.banner.downloadBetaNow": "Pobierz betę wersji desktopowej",
+  "home.promo.title": "Przedstawiamy karty w aplikacji desktopowej",
+  "home.promo.body": "Pracuj wygodnie w wielu sesjach.",
+  "home.promo.cta": "Zaktualizuj aplikację desktopową do najnowszej wersji, aby zacząć.",
+  "home.promo.close": "Zamknij ogłoszenie o aplikacji desktopowej",
 
   "home.hero.title": "Open source'owy agent AI do kodowania",
   "home.hero.subtitle.a": "Darmowe modele w zestawie lub podłącz dowolny model od dowolnego dostawcy,",

+ 4 - 0
packages/console/app/src/i18n/ru.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "на macOS, Windows и Linux",
   "home.banner.downloadNow": "Скачать",
   "home.banner.downloadBetaNow": "Скачать бету для десктопа",
+  "home.promo.title": "Представляем вкладки в десктопном приложении",
+  "home.promo.body": "Легко работайте с несколькими сессиями.",
+  "home.promo.cta": "Обновите десктопное приложение до последней версии, чтобы начать.",
+  "home.promo.close": "Закрыть объявление о десктопном приложении",
 
   "home.hero.title": "AI-агент с открытым кодом для программирования",
   "home.hero.subtitle.a": "Бесплатные модели включены, или подключите любую модель от любого провайдера,",

+ 4 - 0
packages/console/app/src/i18n/th.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "บน macOS, Windows และ Linux",
   "home.banner.downloadNow": "ดาวน์โหลดตอนนี้",
   "home.banner.downloadBetaNow": "ดาวน์โหลดเบต้าเดสก์ท็อปตอนนี้",
+  "home.promo.title": "ขอแนะนำแท็บสำหรับเดสก์ท็อป",
+  "home.promo.body": "ทำงานข้ามหลายเซสชันได้อย่างง่ายดาย",
+  "home.promo.cta": "อัปเดตแอปเดสก์ท็อปเป็นเวอร์ชันล่าสุดเพื่อเริ่มใช้งาน",
+  "home.promo.close": "ปิดประกาศเกี่ยวกับแอปเดสก์ท็อป",
 
   "home.hero.title": "เอเจนต์เขียนโค้ดด้วย AI แบบโอเพนซอร์ส",
   "home.hero.subtitle.a": "มีโมเดลฟรีรวมอยู่ หรือเชื่อมต่อโมเดลใดก็ได้จากผู้ให้บริการรายใดก็ได้,",

+ 4 - 0
packages/console/app/src/i18n/tr.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "macOS, Windows ve Linux'ta",
   "home.banner.downloadNow": "Şimdi indir",
   "home.banner.downloadBetaNow": "Masaüstü betayı şimdi indir",
+  "home.promo.title": "Masaüstü uygulamasında sekmelerle tanışın",
+  "home.promo.body": "Birden fazla oturumda kolayca çalışın.",
+  "home.promo.cta": "Başlamak için masaüstü uygulamasını en son sürüme güncelleyin.",
+  "home.promo.close": "Masaüstü uygulaması duyurusunu kapat",
 
   "home.hero.title": "Açık kaynaklı yapay zeka kodlama ajanı",
   "home.hero.subtitle.a": "Ücretsiz modeller dahil veya herhangi bir sağlayıcıdan herhangi bir modeli bağlayın,",

+ 4 - 0
packages/console/app/src/i18n/uk.ts

@@ -106,6 +106,10 @@ export const dict = {
   "home.banner.platforms": "на macOS, Windows та Linux",
   "home.banner.downloadNow": "Завантажити зараз",
   "home.banner.downloadBetaNow": "Завантажити бета-версію десктопного застосунку",
+  "home.promo.title": "Представляємо вкладки в десктопному застосунку",
+  "home.promo.body": "Легко працюйте з кількома сесіями.",
+  "home.promo.cta": "Оновіть десктопний застосунок до останньої версії, щоб почати.",
+  "home.promo.close": "Закрити оголошення про десктопний застосунок",
 
   "home.hero.title": "Відкритий AI-агент для кодування",
   "home.hero.subtitle.a": "Безкоштовні моделі включено або підключіть будь-яку модель від будь-якого провайдера,",

+ 4 - 0
packages/console/app/src/i18n/zh.ts

@@ -107,6 +107,10 @@ export const dict = {
   "home.banner.platforms": "支持 macOS, Windows, 和 Linux",
   "home.banner.downloadNow": "立即下载",
   "home.banner.downloadBetaNow": "立即下载桌面 Beta 版",
+  "home.promo.title": "桌面版标签页现已推出",
+  "home.promo.body": "轻松处理多个会话。",
+  "home.promo.cta": "更新至最新版桌面应用即可开始使用。",
+  "home.promo.close": "关闭桌面应用公告",
 
   "home.hero.title": "开源 AI 编程代理",
   "home.hero.subtitle.a": "内置免费模型,或连接任意提供商的任意模型,",

+ 4 - 0
packages/console/app/src/i18n/zht.ts

@@ -107,6 +107,10 @@ export const dict = {
   "home.banner.platforms": "支援 macOS、Windows 與 Linux",
   "home.banner.downloadNow": "立即下載",
   "home.banner.downloadBetaNow": "立即下載桌面 Beta 版",
+  "home.promo.title": "桌面版分頁功能全新推出",
+  "home.promo.body": "輕鬆處理多個工作階段。",
+  "home.promo.cta": "更新至最新版桌面應用程式即可開始使用。",
+  "home.promo.close": "關閉桌面應用程式公告",
 
   "home.hero.title": "開源 AI 編碼代理",
   "home.hero.subtitle.a": "內建免費模型,或連接任意供應商的任意模型,",