feat(ui): mobile bottom nav com 4 fixos + menu MAIS para rotas secundárias

- HOME, TX, IMPORT, PERS. fixos na barra inferior
- Botão '···' abre overlay com CONTAS, REC., CAT., CFG
- Overlay fecha ao navegar ou ao tocar fora
- Transição de fade no overlay
This commit is contained in:
2026-05-29 00:07:30 -03:00
parent e1f5eb2281
commit 3d4141f3cc
+71 -5
View File
@@ -1,10 +1,42 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const showMore = ref(false)
const router = useRouter()
router.afterEach(() => { showMore.value = false })
const moreItems = [
{ to: '/contas', label: 'CONTAS' },
{ to: '/recorrencias', label: 'REC.' },
{ to: '/categorias', label: 'CAT.' },
{ to: '/configuracoes', label: 'CFG' },
]
</script>
<template>
<Transition name="fc-more">
<div v-if="showMore" class="fc-more-overlay" @click.self="showMore = false">
<nav class="fc-more-menu">
<RouterLink
v-for="item in moreItems"
:key="item.to"
:to="item.to"
class="fc-more-menu__item fc-pixel"
>{{ item.label }}</RouterLink>
</nav>
</div>
</Transition>
<nav class="fc-bottom-nav">
<RouterLink to="/" class="fc-bottom-nav__item fc-pixel">HOME</RouterLink>
<RouterLink to="/transacoes" class="fc-bottom-nav__item fc-pixel">TX</RouterLink>
<RouterLink to="/importar" class="fc-bottom-nav__item fc-pixel add">+</RouterLink>
<RouterLink to="/importar" class="fc-bottom-nav__item fc-pixel">IMPORT</RouterLink>
<RouterLink to="/personagem" class="fc-bottom-nav__item fc-pixel">PERS.</RouterLink>
<RouterLink to="/contas" class="fc-bottom-nav__item fc-pixel">¤</RouterLink>
<button class="fc-bottom-nav__item fc-bottom-nav__more fc-pixel" @click="showMore = !showMore">
{{ showMore ? '' : '···' }}
</button>
</nav>
</template>
@@ -25,11 +57,45 @@
transition: color .12s;
}
.fc-bottom-nav__item.router-link-active { color: var(--fc-accent-2); }
.fc-bottom-nav__item.add {
font-size: 18px; color: var(--fc-accent);
text-shadow: 0 0 8px var(--fc-accent);
.fc-bottom-nav__more {
background: none; border: none; cursor: pointer;
font-size: 14px; letter-spacing: 1px;
}
.fc-bottom-nav__more.active { color: var(--fc-accent); }
/* overlay */
.fc-more-overlay {
display: none;
position: fixed; inset: 0; bottom: 56px;
z-index: 99;
background: rgba(0,0,0,.5);
align-items: flex-end;
}
.fc-more-menu {
width: 100%;
background: var(--fc-bg-panel);
border-top: 2px solid var(--fc-panel-edge);
display: grid;
grid-template-columns: repeat(4, 1fr);
}
.fc-more-menu__item {
display: flex; align-items: center; justify-content: center;
padding: 16px 4px;
font-size: 7px; color: var(--fc-text-dim);
text-decoration: none;
border-right: 1px solid var(--fc-panel-edge);
transition: color .12s, background .12s;
}
.fc-more-menu__item:last-child { border-right: none; }
.fc-more-menu__item.router-link-active,
.fc-more-menu__item:active { color: var(--fc-accent-2); background: rgba(0,240,255,.05); }
/* transitions */
.fc-more-enter-active, .fc-more-leave-active { transition: opacity .15s; }
.fc-more-enter-from, .fc-more-leave-to { opacity: 0; }
@media (max-width: 767px) {
.fc-bottom-nav { display: flex; }
.fc-more-overlay { display: flex; }
}
</style>