feat1 + showcase worktree-first mentionnent commit/push/promotion sans terminal ; carte worktree du mockup montre les actions Commit/Push (fidèle au WorktreeCard).
258 lines
18 KiB
Vue
258 lines
18 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { DLG_OPTS } from '../i18n/content';
|
|
import type { AppLocale } from '../i18n';
|
|
|
|
const { t, locale } = useI18n();
|
|
|
|
// Options du dialogue (réutilisées pour le rail « À traiter » et la vue mobile).
|
|
const dlgOpts = computed(() => DLG_OPTS[locale.value as AppLocale]);
|
|
</script>
|
|
|
|
<template>
|
|
<section id="showcase" class="mx-auto flex max-w-[1200px] scroll-mt-[84px] flex-col gap-[92px] px-6">
|
|
<!-- a) dashboard worktree-first : rail « À traiter » + section de repo (fidèle à AttentionSection + RepoSection) -->
|
|
<div v-reveal class="flex flex-wrap items-center gap-12">
|
|
<div class="min-w-[280px] flex-[1_1_360px]">
|
|
<div class="mb-3 font-mono text-xs uppercase tracking-[0.12em] text-emerald-400">{{ t('scAKicker') }}</div>
|
|
<h2 class="m-0 mb-4 text-[clamp(26px,3vw,34px)] font-semibold leading-[1.15] tracking-[-0.025em] text-zinc-50">
|
|
{{ t('scATitle') }}
|
|
</h2>
|
|
<p class="m-0 text-[16.5px] leading-[1.6] text-zinc-400">{{ t('scABody') }}</p>
|
|
</div>
|
|
<div class="flex min-w-[280px] flex-[1_1_440px] flex-col gap-3">
|
|
<!-- rail « À traiter » -->
|
|
<div class="flex flex-col gap-2 rounded-xl border border-amber-900/50 bg-amber-950/20 p-3 shadow-card">
|
|
<div class="flex items-center gap-2">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#fbbf24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z" /><path d="M12 9v4" /><path d="M12 17h.01" /></svg>
|
|
<h3 class="text-sm font-semibold text-amber-200">{{ t('mAttn') }}</h3>
|
|
<span class="rounded-full bg-amber-500/20 px-1.5 text-[11px] font-semibold text-amber-300">1</span>
|
|
</div>
|
|
<span class="truncate font-mono text-xs text-amber-300/80">~/code/arboretum/api</span>
|
|
<!-- DialogPrompt -->
|
|
<div class="rounded-lg border border-amber-900/60 bg-amber-950/30 p-2.5">
|
|
<div class="flex items-center gap-2">
|
|
<span class="inline-flex items-center rounded bg-amber-900 px-1.5 py-0.5 text-[11px] font-medium text-amber-200">{{ t('mPermission') }}</span>
|
|
<span class="text-[12.5px] text-amber-100">{{ t('dlgQ') }}</span>
|
|
</div>
|
|
<div class="mt-2 flex flex-wrap gap-1.5">
|
|
<span
|
|
v-for="(op, i) in dlgOpts"
|
|
:key="i"
|
|
class="inline-flex items-center gap-1.5 rounded-lg border border-zinc-700 bg-zinc-800 px-2.5 py-1.5 text-xs font-medium text-zinc-200"
|
|
>
|
|
<span class="font-mono text-amber-400">{{ i + 1 }}</span> {{ op }}
|
|
</span>
|
|
<span class="inline-flex items-center rounded-lg border border-red-900 bg-red-950 px-2.5 py-1.5 text-xs font-medium text-red-300">{{ t('mDeny') }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- section de repo : worktrees + état de session -->
|
|
<div class="flex flex-col gap-2 rounded-xl border border-zinc-800 bg-zinc-900/50 p-3 shadow-card">
|
|
<header class="flex flex-wrap items-center gap-2">
|
|
<h3 class="font-semibold text-zinc-100">arboretum</h3>
|
|
<span class="truncate font-mono text-xs text-zinc-500">~/code/arboretum</span>
|
|
<span class="ml-auto inline-flex items-center gap-1.5 rounded-lg border border-zinc-700 bg-zinc-800 px-2 py-1 text-xs font-medium text-zinc-200">
|
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
|
|
{{ t('mStart') }}
|
|
</span>
|
|
</header>
|
|
|
|
<!-- worktree : branche principale, session au repos -->
|
|
<div class="rounded border border-zinc-800 bg-zinc-900/40 p-2">
|
|
<div class="flex items-center gap-2">
|
|
<span class="font-mono text-sm text-zinc-200">main</span>
|
|
<span class="inline-flex items-center rounded bg-zinc-800 px-1.5 py-0.5 text-[11px] font-medium text-zinc-400">{{ t('mMain') }}</span>
|
|
<span class="ml-auto text-xs text-zinc-600">{{ t('mClean') }}</span>
|
|
</div>
|
|
<p class="truncate font-mono text-xs text-zinc-500">~/code/arboretum</p>
|
|
<div class="mt-1 flex items-center gap-2">
|
|
<span class="inline-flex items-center gap-1 rounded bg-zinc-800/60 px-1.5 py-0.5">
|
|
<span class="inline-flex items-center gap-1 rounded bg-emerald-950 px-1.5 py-0.5 text-[11px] font-medium text-emerald-400">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-emerald-400"></span>{{ t('idle') }}
|
|
</span>
|
|
<span class="font-mono text-[11px] text-zinc-400">claude</span>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- worktree : branche de feature, session occupée -->
|
|
<div class="rounded border border-zinc-800 bg-zinc-900/40 p-2">
|
|
<div class="flex items-center gap-2">
|
|
<span class="font-mono text-sm text-zinc-200">feat/auth</span>
|
|
<span class="ml-auto flex items-center gap-2 text-xs text-zinc-500">
|
|
<span>↑2</span>
|
|
<span class="text-amber-400">● {{ t('mDirty') }}</span>
|
|
</span>
|
|
</div>
|
|
<p class="truncate font-mono text-xs text-zinc-500">~/code/arboretum/.wt/feat-auth</p>
|
|
<div class="mt-1 flex items-center gap-2">
|
|
<span class="inline-flex items-center gap-1 rounded bg-zinc-800/60 px-1.5 py-0.5">
|
|
<span class="inline-flex items-center gap-1 rounded bg-sky-950 px-1.5 py-0.5 text-[11px] font-medium text-sky-300">
|
|
<span class="h-1.5 w-1.5 animate-pulse-sky rounded-full bg-sky-300"></span>{{ t('busy') }}
|
|
</span>
|
|
<span class="font-mono text-[11px] text-zinc-400">claude</span>
|
|
</span>
|
|
</div>
|
|
<!-- actions git de la carte : commit / push (fidèle au WorktreeCard) -->
|
|
<div class="mt-1 flex items-center gap-1.5">
|
|
<span class="inline-flex items-center rounded border border-zinc-700 bg-zinc-800 px-1.5 py-0.5 text-[11px] font-medium text-zinc-300">{{ t('mCommit') }}</span>
|
|
<span class="inline-flex items-center rounded border border-zinc-700 bg-zinc-800 px-1.5 py-0.5 text-[11px] font-medium text-zinc-300">{{ t('mPush') }} ↑2</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- b) grille multi-terminaux (fidèle à TerminalCell : badge d'état + titre repo · branche + commande) -->
|
|
<div v-reveal class="flex flex-wrap-reverse items-center gap-12">
|
|
<div class="min-w-[280px] flex-[1_1_440px]">
|
|
<div class="grid grid-cols-2 gap-2.5 overflow-hidden rounded-xl border border-zinc-800 bg-[#0c0c0e] p-3 shadow-card">
|
|
<div class="overflow-hidden rounded-lg border border-zinc-800 bg-[#09090b]">
|
|
<div class="flex items-center gap-2 border-b border-zinc-800 px-2 py-1.5">
|
|
<span class="inline-flex items-center gap-1 rounded bg-sky-950 px-1.5 py-0.5 text-[10px] font-medium text-sky-300"><span class="h-1.5 w-1.5 animate-pulse-sky rounded-full bg-sky-300"></span>{{ t('busy') }}</span>
|
|
<span class="truncate font-mono text-[11px] text-zinc-300">api · feat/auth</span>
|
|
<span class="ml-auto shrink-0 font-mono text-[11px] text-zinc-500">claude</span>
|
|
</div>
|
|
<div class="p-[11px] font-mono text-[11px] leading-[1.75] text-zinc-300">
|
|
<div class="text-emerald-400">● Edit session.ts</div>
|
|
<div class="text-emerald-400">+ const token = sign(...)</div>
|
|
<div class="text-red-400">- legacy cookie auth</div>
|
|
<div class="text-zinc-500">refactoring guards…</div>
|
|
</div>
|
|
</div>
|
|
<div class="overflow-hidden rounded-lg border border-zinc-800 bg-[#09090b]">
|
|
<div class="flex items-center gap-2 border-b border-zinc-800 px-2 py-1.5">
|
|
<span class="inline-flex items-center gap-1 rounded bg-emerald-950 px-1.5 py-0.5 text-[10px] font-medium text-emerald-400"><span class="h-1.5 w-1.5 rounded-full bg-emerald-400"></span>{{ t('idle') }}</span>
|
|
<span class="truncate font-mono text-[11px] text-zinc-300">web · fix/cart</span>
|
|
<span class="ml-auto shrink-0 font-mono text-[11px] text-zinc-500">claude</span>
|
|
</div>
|
|
<div class="p-[11px] font-mono text-[11px] leading-[1.75] text-zinc-300">
|
|
<div class="text-emerald-400">✓ all tests passing</div>
|
|
<div class="text-zinc-500">24 passed, 0 failed</div>
|
|
<div>
|
|
<span class="text-emerald-400">$</span>
|
|
<span class="ml-1 inline-block h-[11px] w-1.5 animate-blink align-middle bg-zinc-200"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="overflow-hidden rounded-lg border border-zinc-800 bg-[#09090b]">
|
|
<div class="flex items-center gap-2 border-b border-zinc-800 px-2 py-1.5">
|
|
<span class="inline-flex items-center gap-1 rounded bg-sky-950 px-1.5 py-0.5 text-[10px] font-medium text-sky-300"><span class="h-1.5 w-1.5 animate-pulse-sky rounded-full bg-sky-300"></span>{{ t('busy') }}</span>
|
|
<span class="truncate font-mono text-[11px] text-zinc-300">db · refactor</span>
|
|
<span class="ml-auto shrink-0 font-mono text-[11px] text-zinc-500">claude</span>
|
|
</div>
|
|
<div class="p-[11px] font-mono text-[11px] leading-[1.75] text-zinc-300">
|
|
<div class="text-emerald-400">● Write migration</div>
|
|
<div class="text-zinc-500">0003_add_index.sql</div>
|
|
<div class="text-zinc-500">applying to schema…</div>
|
|
</div>
|
|
</div>
|
|
<div class="overflow-hidden rounded-lg border border-zinc-800 bg-[#09090b]">
|
|
<div class="flex items-center gap-2 border-b border-zinc-800 px-2 py-1.5">
|
|
<span class="inline-flex items-center gap-1 rounded bg-amber-950 px-1.5 py-0.5 text-[10px] font-medium text-amber-300"><span class="h-1.5 w-1.5 animate-pulse-amber rounded-full bg-amber-300"></span>{{ t('waiting') }}</span>
|
|
<span class="truncate font-mono text-[11px] text-zinc-300">docs · api</span>
|
|
<span class="ml-auto shrink-0 font-mono text-[11px] text-zinc-500">claude</span>
|
|
</div>
|
|
<div class="p-[11px] font-mono text-[11px] leading-[1.75] text-zinc-300">
|
|
<div class="text-emerald-400">● Read README.md</div>
|
|
<div class="text-amber-300">Permission required</div>
|
|
<div class="text-zinc-500">waiting for input…</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="min-w-[280px] flex-[1_1_360px]">
|
|
<div class="mb-3 font-mono text-xs uppercase tracking-[0.12em] text-emerald-400">{{ t('scBKicker') }}</div>
|
|
<h2 class="m-0 mb-4 text-[clamp(26px,3vw,34px)] font-semibold leading-[1.15] tracking-[-0.025em] text-zinc-50">
|
|
{{ t('scBTitle') }}
|
|
</h2>
|
|
<p class="m-0 text-[16.5px] leading-[1.6] text-zinc-400">{{ t('scBBody') }}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- c) mobile : push + réponse au dialogue (fidèle à DialogPrompt) + barre d'onglets -->
|
|
<div v-reveal class="flex flex-wrap items-center gap-12">
|
|
<div class="min-w-[280px] flex-[1_1_380px]">
|
|
<div class="mb-3 font-mono text-xs uppercase tracking-[0.12em] text-emerald-400">{{ t('scCKicker') }}</div>
|
|
<h2 class="m-0 mb-4 text-[clamp(26px,3vw,34px)] font-semibold leading-[1.15] tracking-[-0.025em] text-zinc-50">
|
|
{{ t('scCTitle') }}
|
|
</h2>
|
|
<p class="m-0 text-[16.5px] leading-[1.6] text-zinc-400">{{ t('scCBody') }}</p>
|
|
</div>
|
|
<div class="flex min-w-[280px] flex-[1_1_320px] justify-center">
|
|
<div class="relative w-[300px] overflow-hidden rounded-[40px] border-[9px] border-zinc-900 bg-zinc-950 shadow-phone">
|
|
<div class="flex h-[30px] items-center justify-center">
|
|
<div class="h-1.5 w-[90px] rounded-full bg-zinc-800"></div>
|
|
</div>
|
|
<div class="px-3 pb-[64px]">
|
|
<!-- toast push -->
|
|
<div class="flex items-start gap-[11px] rounded-[15px] border border-[rgba(120,53,15,0.5)] bg-[#0c0c0e] p-[13px] shadow-toast-sm">
|
|
<span class="inline-flex h-[30px] w-[30px] flex-none items-center justify-center rounded-lg bg-emerald-500/[0.14]">
|
|
<img src="/assets/arboretum-mark.png" alt="" width="18" height="18" class="h-[18px] w-[18px] object-contain" />
|
|
</span>
|
|
<div class="min-w-0 flex-1">
|
|
<div class="flex items-center justify-between">
|
|
<span class="font-mono text-[11px] text-emerald-400">Arboretum</span>
|
|
<span class="text-[10px] text-zinc-600">now</span>
|
|
</div>
|
|
<div class="mt-[3px] text-[13.5px] font-semibold text-zinc-50">{{ t('toastTitle') }}</div>
|
|
<div class="text-xs leading-[1.45] text-zinc-400">{{ t('toastBody') }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- carte « À traiter » + DialogPrompt -->
|
|
<div class="mt-[14px] flex flex-col gap-2 rounded-[15px] border border-amber-900/50 bg-amber-950/20 p-2.5">
|
|
<div class="flex items-center gap-2">
|
|
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#fbbf24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z" /><path d="M12 9v4" /><path d="M12 17h.01" /></svg>
|
|
<span class="text-[13px] font-semibold text-amber-200">{{ t('mAttn') }}</span>
|
|
<span class="rounded-full bg-amber-500/20 px-1.5 text-[11px] font-semibold text-amber-300">1</span>
|
|
</div>
|
|
<span class="font-mono text-[11px] text-amber-300/80">api · feat/auth</span>
|
|
<div class="rounded-lg border border-amber-900/60 bg-amber-950/30 p-2.5">
|
|
<span class="inline-flex items-center rounded bg-amber-900 px-1.5 py-0.5 text-[11px] font-medium text-amber-200">{{ t('mPermission') }}</span>
|
|
<div class="mt-1.5 text-[13px] leading-[1.4] text-amber-100">{{ t('dlgQ') }}</div>
|
|
<div class="mt-2 flex flex-col gap-1.5">
|
|
<span
|
|
v-for="(op, i) in dlgOpts"
|
|
:key="i"
|
|
class="flex items-center gap-2 rounded-lg border border-zinc-700 bg-zinc-800 px-2.5 py-2 text-[13px] font-medium text-zinc-200"
|
|
>
|
|
<span class="font-mono text-amber-400">{{ i + 1 }}</span> {{ op }}
|
|
</span>
|
|
<span class="rounded-lg border border-red-900 bg-red-950 px-2.5 py-2 text-center text-[13px] font-medium text-red-300">{{ t('mDeny') }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- barre d'onglets mobile (fidèle à MobileTabBar) -->
|
|
<div class="absolute inset-x-0 bottom-0 flex border-t border-zinc-800 bg-zinc-950/95 backdrop-blur">
|
|
<div class="flex flex-1 flex-col items-center gap-0.5 py-2 text-zinc-500">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="6" x2="6" y1="3" y2="15" /><circle cx="18" cy="6" r="3" /><circle cx="6" cy="18" r="3" /><path d="M18 9a9 9 0 0 1-9 9" /></svg>
|
|
<span class="text-[10px]">{{ t('mWorktrees') }}</span>
|
|
</div>
|
|
<div class="relative flex flex-1 flex-col items-center gap-0.5 py-2 text-emerald-400">
|
|
<span class="relative">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m7 11 2-2-2-2" /><path d="M11 13h4" /><rect width="18" height="18" x="3" y="3" rx="2" ry="2" /></svg>
|
|
<span class="absolute -right-1.5 -top-1.5 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-amber-500 px-1 text-[9px] font-semibold text-amber-950">1</span>
|
|
</span>
|
|
<span class="text-[10px]">{{ t('mSessions') }}</span>
|
|
</div>
|
|
<div class="flex flex-1 flex-col items-center gap-0.5 py-2 text-zinc-500">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z" /><path d="M7 16.5 12 13.5" /><path d="M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z" /><path d="m17 16.5 4.74-2.85" /><path d="M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0z" /></svg>
|
|
<span class="text-[10px]">{{ t('mGroups') }}</span>
|
|
</div>
|
|
<div class="flex flex-1 flex-col items-center gap-0.5 py-2 text-zinc-500">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="4" x2="20" y1="12" y2="12" /><line x1="4" x2="20" y1="6" y2="6" /><line x1="4" x2="20" y1="18" y2="18" /></svg>
|
|
<span class="text-[10px]">{{ t('mMore') }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</template>
|