diff --git a/site/.vitepress/config/index.ts b/site/.vitepress/config/index.ts
index abe38149f..1ccbd485e 100644
--- a/site/.vitepress/config/index.ts
+++ b/site/.vitepress/config/index.ts
@@ -89,6 +89,12 @@ export default withDrawio(defineConfig({
{},
`(function(){try{var s=localStorage.getItem('vp-font-size')||'normal';if(s!=='xxsmall'&&s!=='small'&&s!=='normal'&&s!=='large'&&s!=='xxlarge'){s='normal';}document.documentElement.dataset.fontSize=s;}catch(e){}})()`,
],
+ // 首屏立即应用侧栏宽度(左导航 + 右大纲),防刷新闪烁。key 与 ResizableSidebar.vue 一致。
+ [
+ 'script',
+ {},
+ `(function(){try{var w=parseInt(localStorage.getItem('vp-sidebar-width'));if(!w||w<200||w>480){w=272;}document.documentElement.style.setProperty('--vp-sidebar-width',w+'px');var a=parseInt(localStorage.getItem('vp-aside-width'));if(!a||a<180||a>360){a=256;}document.documentElement.style.setProperty('--vp-aside-width',a+'px');}catch(e){}})()`,
+ ],
],
markdown: sharedMarkdown,
diff --git a/site/.vitepress/config/shared.ts b/site/.vitepress/config/shared.ts
index 53ba0495a..3652b9045 100644
--- a/site/.vitepress/config/shared.ts
+++ b/site/.vitepress/config/shared.ts
@@ -62,6 +62,12 @@ export const sharedBase = {
{},
`(function(){try{var s=localStorage.getItem('vp-font-size')||'normal';if(s!=='xxsmall'&&s!=='small'&&s!=='normal'&&s!=='large'&&s!=='xxlarge'){s='normal';}document.documentElement.dataset.fontSize=s;}catch(e){}})()`,
],
+ // 首屏立即应用侧栏宽度(左导航 + 右大纲),防刷新闪烁。key 与 ResizableSidebar.vue 一致。
+ [
+ 'script',
+ {},
+ `(function(){try{var w=parseInt(localStorage.getItem('vp-sidebar-width'));if(!w||w<200||w>480){w=272;}document.documentElement.style.setProperty('--vp-sidebar-width',w+'px');var a=parseInt(localStorage.getItem('vp-aside-width'));if(!a||a<180||a>360){a=256;}document.documentElement.style.setProperty('--vp-aside-width',a+'px');}catch(e){}})()`,
+ ],
],
markdown: sharedMarkdown,
diff --git a/site/.vitepress/theme/components/ResizableSidebar.vue b/site/.vitepress/theme/components/ResizableSidebar.vue
new file mode 100644
index 000000000..aeaf3606d
--- /dev/null
+++ b/site/.vitepress/theme/components/ResizableSidebar.vue
@@ -0,0 +1,177 @@
+
+
+
+
+
diff --git a/site/.vitepress/theme/custom.css b/site/.vitepress/theme/custom.css
index 1ebd59dfc..ac658e1a5 100644
--- a/site/.vitepress/theme/custom.css
+++ b/site/.vitepress/theme/custom.css
@@ -1252,6 +1252,89 @@ html.dark .online-compiler-demo__source-highlight .shiki span {
font-size: 0.85em;
}
+/* ================================================================
+ Resizable Sidebar(可拖拽侧栏宽度)
+ 组件: theme/components/ResizableSidebar.vue
+ 左 handle 在组件模板内(fixed),右 handle 运行时注入 .aside(absolute)。
+ 宽度由 --vp-sidebar-width(VitePress 原生,全链路消费)与 --vp-aside-width(本站自定义)驱动。
+ ================================================================ */
+
+:root {
+ --vp-aside-width: 256px; /* 右大纲栏宽度变量,默认与 VitePress 原值一致 */
+}
+
+/* 右栏宽度由变量驱动,覆盖 VitePress 的固定 max-width / width */
+.VPDoc.has-aside .aside {
+ max-width: var(--vp-aside-width);
+ position: relative; /* 给注入的 absolute handle 提供锚点 */
+}
+.VPDoc .aside-container {
+ width: calc(var(--vp-aside-width) - 32px); /* 保持原 32px 内边距逻辑(原 max-width 256 → container 224) */
+}
+
+/* 手柄公共态:常显一条 1px 淡灰细线(::before),悬浮 / 拖拽时变品牌色加粗。
+ 命中热区 8px(透明本体),避免过窄扫不到。z-index 压在 sidebar 之上,防止被侧栏盖住。 */
+.rs-handle {
+ z-index: calc(var(--vp-z-index-sidebar) + 1);
+ width: 8px;
+ background: transparent;
+ cursor: col-resize;
+}
+.rs-handle::before {
+ content: '';
+ position: absolute;
+ left: 50%;
+ top: 0;
+ bottom: 0;
+ width: 1px;
+ transform: translateX(-50%);
+ background: var(--vp-c-divider);
+ transition: width 0.15s ease, background-color 0.15s ease;
+}
+.rs-handle:hover::before,
+.rs-handle.is-active::before {
+ width: 2px;
+ background: var(--vp-c-brand-1);
+}
+
+/* 左手柄:fixed。left 仅作 SSR 首屏 fallback,onMounted 后由 JS 读取 .VPSidebar 右边缘精确
+ 覆盖 —— 宽屏(≥1440px)布局居中,右缘带 (vw-maxW)/2 偏移且受滚动条影响,CSS 公式推算
+ 总有小偏差,改读 getBoundingClientRect 根治(与右 handle 同策略)。 */
+.rs-handle--left {
+ position: fixed;
+ left: var(--vp-sidebar-width);
+ margin-left: -4px;
+ top: var(--vp-nav-height, 64px);
+ bottom: 0;
+}
+
+/* 右手柄:absolute 注入 .aside 内,居中压在其左边缘(默认隐藏,仅大屏显示见下方媒体查询) */
+.rs-handle--right {
+ position: absolute;
+ left: -4px;
+ top: 0;
+ bottom: 0;
+ display: none;
+}
+
+/* 拖拽进行中:禁选中文,全屏 col-resize 光标 */
+body.rs-resizing {
+ user-select: none;
+ cursor: col-resize;
+}
+
+/* 响应式:左栏 <960px 沉为抽屉;右栏 aside 仅 ≥1280px 显示 */
+@media (max-width: 959px) {
+ .rs-handle--left {
+ display: none;
+ }
+}
+@media (min-width: 1280px) {
+ .rs-handle--right {
+ display: block;
+ }
+}
+
/* ================================================================
Content Page Enhancements
================================================================ */
diff --git a/site/.vitepress/theme/index.ts b/site/.vitepress/theme/index.ts
index c3658a2ef..2931fe0f6 100644
--- a/site/.vitepress/theme/index.ts
+++ b/site/.vitepress/theme/index.ts
@@ -14,6 +14,7 @@ import HomeHeroVisual from './components/HomeHeroVisual.vue'
import ProofStrip from './components/ProofStrip.vue'
import HomeRoadmap from './components/HomeRoadmap.vue'
import FontSizeSwitcher from './components/FontSizeSwitcher.vue'
+import ResizableSidebar from './components/ResizableSidebar.vue'
import { setupMermaid } from './mermaid-client'
import './custom.css'
@@ -21,6 +22,7 @@ export default {
extends: DefaultTheme,
Layout() {
return h(DefaultTheme.Layout, null, {
+ 'layout-top': () => h(ResizableSidebar),
'home-hero-image': () => h(HomeHeroVisual),
'home-hero-actions-after': () => h('div', { class: 'proof-on-mobile' }, [h(ProofStrip)]),
'home-hero-after': () => h('div', { class: 'proof-on-desktop' }, [h(ProofStrip)]),