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.
62 lines
2.4 KiB
Vue
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>
|