# 效果图
# 代码
<template>
<nav>
<div class="brand">
<img src="../public/profile.jpg">
<p>
Good day,
<span>Hossein</span>
</p>
</div>
<hr class="line">
<ul class="list">
<li @click="addClass($event)" ref="li" class="active">
<i>🏠</i>
<span>Dashboard</span>
</li>
<li @click="addClass($event)">
<i>💰</i>
<span>Accounts</span>
</li>
<li @click="addClass($event)">
<i>🛒</i>
<span>Orders</span>
</li>
<li @click="addClass($event)">
<i>📊</i>
<span>Charts</span>
</li>
<li @click="addClass($event)">
<i>🎉</i>
<span>Support</span>
</li>
<hr class="line">
<li @click="addClass($event)">
<i>🎈</i>
<span>Logout</span>
</li>
</ul>
</nav>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const li = ref(null)
onMounted(() => {
let delayTime = 3;
let spans = document.querySelectorAll(".container>nav>.list>li>span");
spans.forEach((e) => {
e.style.animationDelay = `.${delayTime++}s`
})
})
const addClass = (e) => {
li.value && li.value.classList.remove("active")
e.currentTarget.classList.add("active")
li.value = e.currentTarget
}
</script>
<style scoped>
nav {
width: 40px;
height: fit-content;
position: fixed;
top: 60px;
right: 0;
display: flex;
align-items: start;
justify-content: end;
flex-direction: column;
z-index: 2;
overflow-x: hidden;
padding: 5px 16px;
border-radius: 12px;
backdrop-filter: blur(18px);
background: rgba(230, 235, 240, .7);
border: 2px solid rgba(230, 235, 240, .7);
box-shadow: 0 0 30px rgba(0, 0, 0, .05);
transition: .6s cubic-bezier(.8, .5, .5, .8);
}
nav:hover {
width: 200px;
}
nav:hover ul li {
width: 90%;
}
.brand {
width: 100%;
display: flex;
align-items: center;
justify-content: start;
}
.brand img {
width: 65px;
border-radius: 50%;
border: 4px solid rgba(230, 235, 240, .8);
}
.brand p {
color: #505257;
font-size: 10px;
font-weight: 500;
font-style: italic;
text-align: left;
line-height: 22px;
margin-left: 4px;
box-sizing: inherit;
opacity: 0;
}
.brand p span {
color: #3c3e43;
display: block;
font-size: 20px;
font-style: normal;
}
nav .line {
width: 100%;
height: 2px;
margin: 5px 0;
border-radius: 30%;
background: #87a3af;
}
nav .list {
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: start;
margin-left: -20px;
}
nav .list li {
display: flex;
width: 60%;
margin: 5px 0;
padding: 5px 12px;
cursor: pointer;
border-radius: 8px;
transition: .4s ease-in-out;
}
nav .list li:hover {
background: rgba(230, 235, 240, .4);
}
nav .list li.active {
background: #3681f6;
}
nav .list li.active span {
color: #fff;
}
nav .list li.active i {
background: none;
-webkit-text-fill-color: unset;
color: #e6ebf0;
}
nav .list i {
font-size: 20px;
background: linear-gradient(-135deg,
#3c3e43,
#838487);
font-style: normal;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
nav .list span {
color: #505257;
font-size: 18px;
font-weight: 500;
margin: 0 0 0 12px;
}
nav .brand p,
nav .list span {
opacity: 0;
pointer-events: none;
transform: translateX(20px);
}
nav:hover .brand p {
animation: fadeIn .4s ease-out forwards;
animation-delay: .4s;
}
nav:hover .list span {
animation: fadeIn .3s ease-out forwards;
}
@keyframes fadeIn {
to {
opacity: 1;
pointer-events: unset;
transform: translateX(0);
}
}
</style>
# 未完待续
后期再做组件化相关工作
# 记 23-6-12 的 bug
本地代码无误,打包后在页面刷新时报节点无法增加子节点错误,排除后是 querySelectorAll 找错了节点,在 vuepress 打包后页面渲染时也有相同的节点。
错误在于 ssr 服务端渲染特性,client 端与 server 端渲染的 html 不一致,导致在hydrate
时出错。
目前的解决办法是增加ClientOnly标签。
# BUG
如果发现 bug 或者其他需求可以联系作者 也十分欢迎 pr 前往 github (opens new window)