agent-ecosystem/landing/product-docs/.vitepress/theme/DocsCardGrid.vue
2026-06-02 11:49:25 +03:00

267 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { useData, withBase } from "vitepress";
import { computed } from "vue";
const props = withDefaults(defineProps<{ type?: "start" | "reference" }>(), {
type: "start"
});
type CardText = { title: string; desc: string; icon?: string; link?: string };
// Locales that have their own translated card copy. Anything else falls back to English (root).
const KNOWN_LOCALES = ["ru", "zh", "es", "ja", "fr", "de"] as const;
// Links and icons are shared across locales; only the path prefix changes per locale.
const START_LINKS = ["/guide/quickstart", "/guide/installation", "/guide/create-team", "/guide/code-review"];
const START_ICONS = ["01", "02", "03", "04"];
const REFERENCE_LINKS = [
"/reference/concepts",
"/reference/providers-runtimes",
"/reference/contributor-architecture",
"/reference/privacy-local-data",
"/reference/faq"
];
const REFERENCE_ICONS = ["◈", "⌁", "▦", "⌘", "?"];
const CARD_TEXT: Record<string, { start: CardText[]; reference: CardText[] }> = {
"": {
start: [
{ icon: "01", title: "Beginner workflow", desc: "Understand the first run from project to approval.", link: "/guide/beginner-workflow" },
{ icon: "02", title: "Quickstart", desc: "Install the app and validate the base launch.", link: "/guide/quickstart" },
{ icon: "03", title: "First team", desc: "Lead, builder, reviewer, roles, models, and Worktree.", link: "/guide/create-first-team" },
{ icon: "04", title: "Run work", desc: "Lead brief, task board, comments, and monitoring.", link: "/guide/run-and-monitor-work" },
{ icon: "05", title: "Review and approve", desc: "Task detail, logs, diff, and hunk-level decisions.", link: "/guide/review-and-approve" },
{ icon: "06", title: "Runtime setup", desc: "Claude, Codex, OpenCode, and multimodel setup.", link: "/guide/runtime-setup" }
],
reference: [
{ title: "Concepts", desc: "Teams, tasks, roles, and autonomy levels." },
{ title: "Runtimes", desc: "Claude, Codex, OpenCode, and multimodel mode." },
{ title: "Architecture", desc: "Feature layout, guardrails, and runtime/provider boundaries." },
{ title: "Local data", desc: "What stays on disk and what providers receive." },
{ title: "FAQ", desc: "Short answers to common questions." }
]
},
ru: {
start: [
{ icon: "01", title: "Путь новичка", desc: "Понять весь первый запуск от проекта до approval.", link: "/ru/guide/beginner-workflow" },
{ icon: "02", title: "Быстрый старт", desc: "Поставить приложение и проверить базовый запуск.", link: "/ru/guide/quickstart" },
{ icon: "03", title: "Первая команда", desc: "Lead, builder, reviewer, роли, модели и Worktree.", link: "/ru/guide/create-first-team" },
{ icon: "04", title: "Запуск работы", desc: "Brief для lead, task board, comments и monitoring.", link: "/ru/guide/run-and-monitor-work" },
{ icon: "05", title: "Review и approval", desc: "Task detail, logs, diff и hunk-level decisions.", link: "/ru/guide/review-and-approve" },
{ icon: "06", title: "Рантаймы", desc: "Claude, Codex, OpenCode и multimodel setup.", link: "/ru/guide/runtime-setup" }
],
reference: [
{ title: "Концепции", desc: "Команды, задачи, роли и уровни автономности." },
{ title: "Рантаймы", desc: "Claude, Codex, OpenCode и multimodel-режим." },
{ title: "Архитектура", desc: "Feature layout, guardrails и границы runtime/provider." },
{ title: "Локальные данные", desc: "Что хранится на машине и что уходит провайдерам." },
{ title: "FAQ", desc: "Короткие ответы на частые вопросы." }
]
},
zh: {
start: [
{ title: "快速开始", desc: "安装应用并创建你的第一个团队。" },
{ title: "安装", desc: "平台、发布版本以及从源码运行。" },
{ title: "创建团队", desc: "角色、lead prompt 与任务边界。" },
{ title: "代码审查", desc: "以代码块hunk级别的决策审查任务变更。" }
],
reference: [
{ title: "概念", desc: "团队、任务、角色与自主级别。" },
{ title: "运行时", desc: "Claude、Codex、OpenCode 与多模型模式。" },
{ title: "架构", desc: "功能布局、护栏以及运行时/提供方边界。" },
{ title: "本地数据", desc: "哪些数据留在磁盘上,哪些会发送给提供方。" },
{ title: "常见问题", desc: "对常见问题的简短解答。" }
]
},
es: {
start: [
{ title: "Inicio rápido", desc: "Instala la aplicación y crea tu primer equipo." },
{ title: "Instalación", desc: "Plataformas, versiones y ejecución desde el código fuente." },
{ title: "Crear un equipo", desc: "Roles, prompt del lead y límites de las tareas." },
{ title: "Revisión de código", desc: "Revisa los cambios de las tareas con decisiones a nivel de hunk." }
],
reference: [
{ title: "Conceptos", desc: "Equipos, tareas, roles y niveles de autonomía." },
{ title: "Runtimes", desc: "Claude, Codex, OpenCode y modo multimodelo." },
{ title: "Arquitectura", desc: "Estructura de las funciones, guardrails y límites entre runtime y proveedor." },
{ title: "Datos locales", desc: "Qué permanece en el disco y qué reciben los proveedores." },
{ title: "Preguntas frecuentes", desc: "Respuestas breves a preguntas habituales." }
]
},
ja: {
start: [
{ title: "クイックスタート", desc: "アプリをインストールして、最初のチームを作成します。" },
{ title: "インストール", desc: "対応プラットフォーム、リリース、ソースからの実行について。" },
{ title: "チームの作成", desc: "ロール、リードプロンプト、タスクの範囲について。" },
{ title: "コードレビュー", desc: "ハンク単位の判断でタスクの変更をレビューします。" }
],
reference: [
{ title: "コンセプト", desc: "チーム、タスク、ロール、自律性のレベルについて。" },
{ title: "ランタイム", desc: "Claude、Codex、OpenCode、およびマルチモデルモードについて。" },
{ title: "アーキテクチャ", desc: "機能の構成、ガードレール、ランタイム/プロバイダーの境界について。" },
{ title: "ローカルデータ", desc: "ディスクに保持されるものと、プロバイダーに送信されるものについて。" },
{ title: "FAQ", desc: "よくある質問への簡潔な回答。" }
]
},
fr: {
start: [
{ title: "Démarrage rapide", desc: "Installez l'application et créez votre première équipe." },
{ title: "Installation", desc: "Plateformes, versions et exécution depuis les sources." },
{ title: "Créer une équipe", desc: "Rôles, prompt du lead et périmètre des tâches." },
{ title: "Revue de code", desc: "Examinez les modifications de tâches avec des décisions au niveau du hunk." }
],
reference: [
{ title: "Concepts", desc: "Équipes, tâches, rôles et niveaux d'autonomie." },
{ title: "Runtimes", desc: "Claude, Codex, OpenCode et mode multimodèle." },
{ title: "Architecture", desc: "Organisation des fonctionnalités, garde-fous et frontières runtime/fournisseur." },
{ title: "Données locales", desc: "Ce qui reste sur le disque et ce que reçoivent les fournisseurs." },
{ title: "FAQ", desc: "Réponses brèves aux questions fréquentes." }
]
},
de: {
start: [
{ title: "Schnellstart", desc: "Installieren Sie die App und erstellen Sie Ihr erstes Team." },
{ title: "Installation", desc: "Plattformen, Releases und Ausführen aus dem Quellcode." },
{ title: "Team erstellen", desc: "Rollen, Lead-Prompt und Aufgabengrenzen." },
{ title: "Code-Review", desc: "Aufgabenänderungen mit Entscheidungen auf Hunk-Ebene überprüfen." }
],
reference: [
{ title: "Konzepte", desc: "Teams, Aufgaben, Rollen und Autonomiestufen." },
{ title: "Runtimes", desc: "Claude, Codex, OpenCode und Multimodell-Modus." },
{ title: "Architektur", desc: "Feature-Aufbau, Guardrails und Grenzen zwischen Runtime und Anbieter." },
{ title: "Lokale Daten", desc: "Was auf dem Datenträger bleibt und was die Anbieter erhalten." },
{ title: "FAQ", desc: "Kurze Antworten auf häufige Fragen." }
]
}
};
const { page } = useData();
const locale = computed(() => {
const segment = page.value.relativePath.split("/")[0];
return (KNOWN_LOCALES as readonly string[]).includes(segment) ? segment : "";
});
const cards = computed(() => {
const text = CARD_TEXT[locale.value] ?? CARD_TEXT[""];
const isReference = props.type === "reference";
const entries = isReference ? text.reference : text.start;
const links = isReference ? REFERENCE_LINKS : START_LINKS;
const icons = isReference ? REFERENCE_ICONS : START_ICONS;
const prefix = locale.value ? `/${locale.value}` : "";
return entries.map((entry, index) => ({
icon: entry.icon ?? icons[index] ?? String(index + 1).padStart(2, "0"),
title: entry.title,
desc: entry.desc,
link: entry.link ?? `${prefix}${links[index]}`
}));
});
</script>
<template>
<div class="docs-card-grid">
<a v-for="card in cards" :key="card.link" class="docs-card" :href="withBase(card.link)">
<span class="docs-card__icon">{{ card.icon }}</span>
<strong>{{ card.title }}</strong>
<span>{{ card.desc }}</span>
<span class="docs-card__arrow" aria-hidden="true"></span>
</a>
</div>
</template>
<style scoped>
.docs-card-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14px;
margin: 24px 0;
}
.docs-card {
position: relative;
overflow: hidden;
display: grid;
grid-template-columns: auto 1fr auto;
grid-template-rows: auto auto;
column-gap: 12px;
row-gap: 4px;
padding: 18px;
border: var(--at-glass-border);
border-radius: var(--at-radius-xl);
background: var(--at-c-surface-soft);
color: var(--at-c-text);
text-decoration: none !important;
box-shadow: var(--at-shadow-card);
transition:
border-color var(--at-transition-base),
background-color var(--at-transition-base),
transform var(--at-transition-base),
box-shadow var(--at-transition-base);
}
.docs-card:hover {
border-color: var(--at-c-border-strong);
background: var(--at-glass-bg-hover);
transform: translateY(-3px);
box-shadow: var(--at-shadow-cyan-md);
}
.docs-card__icon {
grid-row: 1 / -1;
display: grid;
place-items: center;
width: 40px;
height: 40px;
border-radius: var(--at-radius-md);
background: var(--at-gradient-panel);
color: var(--at-c-cyan);
font-family: var(--at-font-mono);
font-size: 13px;
border: 1px solid rgba(0, 240, 255, 0.14);
}
.docs-card strong {
color: var(--at-c-text);
font-size: 15px;
line-height: 1.3;
}
.docs-card > span:nth-of-type(2) {
color: var(--at-c-text-muted);
font-size: 13px;
line-height: 1.45;
}
.docs-card__arrow {
grid-column: 3;
align-self: end;
color: var(--at-c-cyan);
font-family: var(--at-font-mono);
font-size: 16px;
opacity: 0.55;
transform: translateX(-4px);
transition:
opacity var(--at-transition-base),
transform var(--at-transition-base);
}
.docs-card:hover .docs-card__arrow {
opacity: 1;
transform: translateX(0);
}
@media (max-width: 640px) {
.docs-card-grid {
grid-template-columns: 1fr;
}
.docs-card {
grid-template-columns: auto 1fr;
}
.docs-card__arrow {
display: none;
}
}
</style>