feat(layout): 基础布局/导航/页脚/明暗不闪烁

- BaseLayout:字体三轨统持、viewport-fit=cover、theme-color 双套、skip-link
- Header:≤4 项导航纪律 + sticky 毛玻璃 + aria-current;搜索 icon 占位待 T8
- Footer:ICP 备案链接(法定保留)+ built-from 具名槽位待 T7
- ThemeScript:head 内联先于首帧,手选 > 系统偏好,防白闪

验证: pnpm astro build exit 0;dist/index.html 含 ICP 文案与跳到正文链

Spec: 2026-10-24_add-blog-skeleton
Co-authored-by: GLM-5.3
This commit is contained in:
wait4xandGLM-5.3 committed 2026-10-24 23:09:45 +08:00
1 parent ee53279822
commit b50eddf2bb
5 files changed
+185 -13

No files matched your search

+39
View File
@@ -0,0 +1,39 @@
---
// 页脚:版权 + ICP 备案(法定保留)+ 构建透明槽位(T7 built-from 填充)
---
<footer class="site-footer safe-area">
<div class="container">
<p class="fine">
© {new Date().getFullYear()} wait4x ·
<a href="https://beian.miit.gov.cn/" rel="noopener noreferrer" target="_blank" class="link">
陕ICP备2026014860号-1
</a>
</p>
<!-- T7 注入:built from {commit} · {time} · Astro(链到 gitea commit) -->
<slot name="build-info" />
</div>
</footer>
<style>
.site-footer {
border-top: 1px solid var(--line);
margin-top: var(--space-6);
padding-block: var(--space-4);
}
.fine {
font-size: 13px;
color: var(--ink-3);
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
justify-content: center;
}
:global(.build-info) {
margin-top: var(--space-1);
text-align: center;
font-family: var(--font-mono);
font-size: 12px;
color: var(--ink-4);
}
</style>
+84
View File
@@ -0,0 +1,84 @@
---
// 顶部导航:≤4 项纪律(防 higan 十项复发);当前页 aria-current
const nav = [
{ href: '/archives/', label: '文章' },
{ href: '/gallery/', label: '图库' },
{ href: '/about/', label: '关于' },
];
const path = Astro.url.pathname;
const isCurrent = (href: string) =>
path === href || path === href.replace(/\/$/, '') || path.startsWith(href);
---
<header class="site-header safe-area">
<div class="container-wide header-inner">
<a href="/" class="brand" aria-label="wait4x 首页">wait4x</a>
<nav aria-label="主导航">
<ul>
{nav.map((item) => (
<li>
<a
href={item.href}
class="tap nav-link"
aria-current={isCurrent(item.href) ? 'page' : undefined}
>
{item.label}
</a>
</li>
))}
<!-- 搜索入口:T8 Pagefind 面板接管,先留可聚焦占位 -->
<li>
<button class="tap nav-link" type="button" data-search-trigger aria-label="搜索">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<circle cx="11" cy="11" r="7"></circle>
<path d="m20 20-3.5-3.5"></path>
</svg>
</button>
</li>
</ul>
</nav>
</div>
</header>
<style>
.site-header {
border-bottom: 1px solid var(--line);
position: sticky;
top: 0;
background: color-mix(in oklab, var(--bg) 88%, transparent);
backdrop-filter: blur(8px);
z-index: 10;
}
.header-inner {
display: flex;
align-items: center;
justify-content: space-between;
height: 56px;
}
.brand {
font-family: var(--font-mono);
font-weight: 700;
font-size: 18px;
color: var(--ink-1);
letter-spacing: 0.02em;
}
nav ul {
display: flex;
gap: var(--space-2);
list-style: none;
padding: 0;
margin: 0;
}
.nav-link {
font-size: 15px;
color: var(--ink-3);
padding-inline: var(--space-2);
border-radius: 6px;
transition: color var(--dur) var(--ease);
}
.nav-link:hover { color: var(--ink-1); }
.nav-link[aria-current='page'] { color: var(--accent); }
@media (max-width: 560px) {
.nav-link { font-size: 14px; padding-inline: var(--space-1); }
}
</style>
+14
View File
@@ -0,0 +1,14 @@
---
// 明暗不闪烁脚本:<head> 内联、先于首帧。
// 优先级:用户手选(localStorage) > 系统偏好;切换按钮(T7 键盘/组件)写同一 key。
---
<script is:inline>
(function () {
var saved = localStorage.getItem('theme');
var theme = saved === 'light' || saved === 'dark'
? saved
: (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.dataset.theme = theme;
})();
</script>