手机端兼容与加载条
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-04-01 17:26:44 +08:00
parent b3e3f48bdb
commit aa33703b8b
3 changed files with 175 additions and 5 deletions

View File

@ -10,7 +10,19 @@ const { title = '小帕的小窝' } = Astro.props
---
<BaseLayout title={title}>
<div class="nav-container" transition:persist>
<div class="nav-mobile" aria-hidden="true" transition:persist>
<button
id="nav-mobile-button"
onclick="document.getElementById('nav-main').classList.remove('nav-container-hidden')"
><Icon name="mdi:menu-close" /></button
>
<a href="/">小帕的小窝</a>
</div>
<div
id="nav-main"
class="nav-container nav-container-hidden"
transition:persist
>
<nav>
<ul class="left">
<li class="website-logo">
@ -33,20 +45,66 @@ const { title = '小帕的小窝' } = Astro.props
<ul class="right">Hello!</ul>
</nav>
</div>
<main transition:animate="slide">
<div
class="loading-indicator hidden"
id="loading-indicator"
aria-hidden="true"
transition:persist
>
</div>
<main>
<slot />
</main>
</BaseLayout>
<script>
const navClose = () => {
const navMain = document.getElementById('nav-main')
navMain?.classList.add('nav-container-hidden')
}
document.getElementById('nav-main')?.addEventListener('click', (e) => {
const target = e.target as HTMLElement
if (target.id == 'nav-main') {
document.getElementById('nav-main')?.classList.add('nav-container-hidden')
}
})
document.addEventListener('astro:before-preparation', () => {
document.getElementById('loading-indicator')?.classList.remove('hidden')
})
document.addEventListener('astro:after-swap', () => {
requestAnimationFrame(navClose)
document.getElementById('loading-indicator')?.classList.add('hidden')
})
</script>
<style>
.nav-container {
width: 100dvw;
height: 3rem;
position: fixed;
z-index: 100;
z-index: 10000;
backdrop-filter: blur(4px);
background-color: rgb(from var(--color-bg-n) r g b / 0.5);
@media (max-width: 767px) {
height: 100dvh;
background-color: #00000033;
transition:
background-color ease 0.2s,
backdrop-filter ease 0.2s;
}
&.nav-container-hidden {
@media (max-width: 767px) {
backdrop-filter: blur(0px);
background-color: transparent;
pointer-events: none;
}
}
& > nav {
width: 100%;
height: 100%;
@ -61,14 +119,43 @@ const { title = '小帕的小窝' } = Astro.props
font-weight: 400;
@media (max-width: 767px) {
flex-direction: column;
padding-block: 5rem;
padding-inline: 2rem;
align-items: start;
width: 70%;
background-color: var(--color-bg-n);
margin-inline-start: 0;
font-size: larger;
transition: transform cubic-bezier(0.4, 1, 0.4, 1) 0.4s;
}
.nav-container-hidden & {
@media (max-width: 767px) {
transform: translateX(-80dvw);
}
}
& > ul {
display: flex;
flex-direction: row;
@media (max-width: 767px) {
flex-direction: column;
gap: 0.25rem;
width: 100%;
}
}
& li {
height: 2rem;
@media (max-width: 767px) {
height: 3rem;
width: 100%;
}
&:hover {
background-color: rgb(from var(--color-fg-0) r g b / 0.1);
}
@ -101,4 +188,89 @@ const { title = '小帕的小窝' } = Astro.props
}
}
}
.nav-mobile {
width: 100dvw;
height: 4rem;
position: fixed;
z-index: 100;
backdrop-filter: blur(4px);
background-color: rgb(from var(--color-bg-n) r g b / 0.5);
font-size: larger;
display: flex;
flex-direction: row;
align-items: center;
padding-inline: 1rem;
gap: 0.5rem;
& > button {
width: 3rem;
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
&:active,
&:hover {
background-color: rgb(from var(--color-fg-0) r g b / 0.1);
}
}
& > a {
font-weight: 600;
&:active,
&:hover {
background-color: rgb(from var(--color-fg-0) r g b / 0.1);
}
}
@media (min-width: 768px) {
display: none;
}
}
.loading-indicator {
--color1: oklch(from var(--color-blue) 0.7 0.17 h);
--color2: oklch(from var(--color-blue) 0.57 0.25 h);
--loading-x-size: 2rem;
--loading-height: 0.25rem;
position: fixed;
height: var(--loading-height);
background-color: var(--color1);
inset-inline-start: 0;
inset-inline-end: 0;
inset-block-start: 0;
z-index: 10001;
background-image: linear-gradient(
-45deg,
transparent 0%,
transparent 25%,
var(--color2) 25%,
var(--color2) 75%,
transparent 75%,
transparent 100%
);
background-repeat: repeat;
background-size: 2rem 100%;
animation: loading-animation infinite 0.5s linear;
transition: inset-block-start cubic-bezier(0.4, 1, 0.4, 1) 0.2s;
&.hidden {
inset-block-start: calc(-1 * var(--loading-height));
}
}
@keyframes loading-animation {
0% {
background-position: 0 0;
}
100% {
background-position: var(--loading-x-size) 0;
}
}
</style>

View File

@ -29,7 +29,6 @@ const blogs = await listBlogs({ page })
<style>
.__dev__caution {
width: 100dvw;
height: 100dvh;
display: flex;
align-items: center;

View File

@ -30,7 +30,6 @@ const tree = await toMarkdocTree(blogData.content)
<style>
.__dev__caution {
width: 100dvw;
height: 100dvh;
display: flex;
align-items: center;