Files
X-Financial/src/components/layout/SidebarRail.vue

71 lines
2.1 KiB
Vue
Raw Normal View History

<template>
<aside class="rail" aria-label="主导航">
<div class="mark">RO</div>
<nav class="rail-nav">
<button
v-for="item in navItems"
:key="item.id"
class="nav-btn"
:class="{ active: activeView === item.id }"
type="button"
:aria-label="item.label"
:title="item.label"
@click="emit('navigate', item.id)"
>
<span v-html="item.icon"></span>
</button>
</nav>
<button class="nav-btn muted" type="button" aria-label="打开合规对话" title="打开合规对话" @click="emit('openChat')">
<span v-html="messageIcon"></span>
</button>
</aside>
</template>
<script setup>
import { icons } from '../../data/icons.js'
defineProps({
navItems: { type: Array, required: true },
activeView: { type: String, required: true }
})
const emit = defineEmits(['navigate', 'openChat'])
const messageIcon = icons.message
</script>
<style scoped>
.rail {
position: sticky;
top: 0;
height: 100dvh;
display: grid;
grid-template-rows: auto 1fr auto;
gap: 18px;
padding: 18px 12px;
background: var(--nav);
color: #fff;
z-index: 20;
}
.mark { width: 48px; height: 48px; display: grid; place-items: center; border-radius: 14px; background: linear-gradient(135deg,#fff,#9db2ff); color: #10215c; font-weight: 850; }
.rail-nav { display: grid; gap: 10px; align-content: start; }
.nav-btn {
width: 48px;
min-height: 48px;
display: grid;
place-items: center;
border: 0;
border-radius: 14px;
background: transparent;
color: var(--nav-muted);
transition: background 160ms var(--ease), color 160ms var(--ease), transform 160ms var(--ease);
}
.nav-btn:hover, .nav-btn.active { background: rgba(255,255,255,.1); color: #fff; transform: translateY(-1px); }
.nav-btn svg { width: 18px; height: 18px; stroke: currentColor; stroke-width: 2; fill: none; stroke-linecap: round; stroke-linejoin: round; }
@media (max-width: 760px) {
.rail { position: sticky; height: auto; grid-template-columns: auto 1fr auto; grid-template-rows: none; padding: 10px 12px; }
.rail-nav { display: flex; overflow-x: auto; }
}
</style>