Refonte front (packages/web) : coquille applicative partagée (sidebar desktop + barre d'onglets mobile + PageHeader, langue/push/logout centralisés) pilotée par route.meta.layout ; design system (BaseButton/BaseBadge/SegmentedControl/EmptyState/ SkeletonRow, anneau de focus, icônes @lucide/vue) ; tri/filtre/recherche/pagination côté client via useListControls (+ synchro URL) sur sessions/worktrees/groupes ; section « À traiter », palette de commandes ⌘K, toasts. Aucune modif serveur/protocole/DB.
41 lines
1.2 KiB
Vue
41 lines
1.2 KiB
Vue
<template>
|
|
<nav
|
|
class="fixed inset-x-0 bottom-0 z-40 flex border-t border-zinc-800 bg-zinc-950/95 backdrop-blur md:hidden"
|
|
style="padding-bottom: env(safe-area-inset-bottom)"
|
|
>
|
|
<NavItem
|
|
v-for="item in items"
|
|
:key="item.key"
|
|
:to="item.to"
|
|
:icon="item.icon"
|
|
:label="item.label"
|
|
:badge="item.badge"
|
|
:active="isActive(item.match)"
|
|
orientation="col"
|
|
class="flex-1"
|
|
/>
|
|
<button
|
|
type="button"
|
|
class="flex flex-1 flex-col items-center gap-0.5 py-2 text-zinc-500 transition-colors hover:text-zinc-300 focus-visible:outline-none"
|
|
@click="showMore = true"
|
|
>
|
|
<Settings :size="20" :stroke-width="1.75" />
|
|
<span class="text-[10px]">{{ t('nav.settings') }}</span>
|
|
</button>
|
|
<MoreSheet v-if="showMore" @close="showMore = false" />
|
|
</nav>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { Settings } from '@lucide/vue';
|
|
import { useNav } from '../../composables/useNav';
|
|
import NavItem from './NavItem.vue';
|
|
import MoreSheet from './MoreSheet.vue';
|
|
|
|
const { t } = useI18n();
|
|
const { items, isActive } = useNav();
|
|
const showMore = ref(false);
|
|
</script>
|