Files
arboretum/packages/web/src/components/ide/ActivityBar.vue
Johan LEROY c96d929c7a
Some checks failed
CI / Build & test (Node 24) (push) Has been cancelled
CI / Pack & boot smoke (Node 22) (push) Has been cancelled
CI / No em/en dashes (push) Has been cancelled
CI / Build & test (Node 22) (push) Has been cancelled
feat(web): coquille IDE + arbre de projets unifié (route /ide)
components/ide/ : IdeShell (grille barre d'activité + panneau gauche + zone centrale + dock + barre de statut, splitters persistés, réconciliation des ressources ouvertes contre les données live), ActivityBar (Explorer/Git/Sessions/Groupes + Réglages/Aide), PrimarySidebar, ProjectTree + ProjectTreeNode (arbre unique repos -> worktrees -> sessions, fichiers embarqués via FileTree en mode sans chrome, dépliage paresseux), StatusBar.

Route /ide (layout 'ide'), entrée de nav « IDE », namespace i18n ide (EN/FR). Clics de l'arbre pilotent le store (contexte worktree, ouverture de fichier/terminal). Centre et dock en placeholders (remplis en B4/B5). FileTree gagne un mode embedded. 427 tests.
2026-07-17 17:08:35 +02:00

62 lines
2.4 KiB
Vue

<template>
<nav class="flex w-[var(--ide-activitybar-w)] shrink-0 flex-col items-center gap-1 border-r border-border bg-surface-1 py-2">
<button
v-for="item in items"
:key="item.view"
type="button"
class="relative flex h-10 w-10 items-center justify-center rounded-lg transition-colors"
:class="isActive(item.view) ? 'bg-surface-3 text-fg' : 'text-fg-subtle hover:bg-surface-2 hover:text-fg'"
:title="item.label"
:aria-label="item.label"
@click="ide.toggleActivity(item.view)"
>
<component :is="item.icon" :size="20" :stroke-width="1.75" />
<span
v-if="item.badge"
class="absolute top-1 right-1 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"
>
{{ item.badge }}
</span>
</button>
<div class="mt-auto flex flex-col items-center gap-1">
<RouterLink
v-for="l in links"
:key="l.name"
:to="{ name: l.name }"
:title="l.label"
:aria-label="l.label"
class="flex h-10 w-10 items-center justify-center rounded-lg text-fg-subtle transition-colors hover:bg-surface-2 hover:text-fg"
>
<component :is="l.icon" :size="20" :stroke-width="1.75" />
</RouterLink>
</div>
</nav>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { Boxes, FolderTree, GitCompare, LifeBuoy, Settings, SquareTerminal } from '@lucide/vue';
import { useIdeStore, type ActivityView } from '../../stores/ide';
import { useNav } from '../../composables/useNav';
const { t } = useI18n();
const ide = useIdeStore();
const { waitingCount } = useNav();
const isActive = (v: ActivityView): boolean => ide.activeActivity === v && ide.leftVisible;
const items = computed(() => [
{ view: 'explorer' as ActivityView, icon: FolderTree, label: t('ide.activity.explorer'), badge: 0 },
{ view: 'git' as ActivityView, icon: GitCompare, label: t('ide.activity.git'), badge: 0 },
{ view: 'sessions' as ActivityView, icon: SquareTerminal, label: t('ide.activity.sessions'), badge: waitingCount.value },
{ view: 'groups' as ActivityView, icon: Boxes, label: t('ide.activity.groups'), badge: 0 },
]);
const links = computed(() => [
{ name: 'settings', icon: Settings, label: t('nav.settings') },
{ name: 'help', icon: LifeBuoy, label: t('nav.help') },
]);
</script>