fix(bug-2): sidebar width via CSS attribute — bypasses @persist Alpine reactivity issue
@persist disconnects Alpine :class bindings from store reactivity on re-render. Solution: drive sidebar width via html[data-sidebar-collapsed] CSS attribute (same mechanism as skeleton) instead of Alpine :class. - _syncDataset() now uses isCollapsed (respects mobile: never narrow on <768px) - Blocking script checks window.innerWidth >= 768 before setting attribute - Resize handler calls _syncDataset() to update attribute on viewport change - aside gets sidebar-aside class; CSS sets 15rem/4rem at md+ via attribute Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>main
parent
fe257ef75b
commit
0a08d0f268
|
|
@ -70,10 +70,11 @@ document.addEventListener('alpine:init', () => {
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener('resize', () => {
|
||||||
this.isMobile = window.innerWidth < 768;
|
this.isMobile = window.innerWidth < 768;
|
||||||
this.isCollapsed = this.collapsed && ! this.isMobile;
|
this.isCollapsed = this.collapsed && ! this.isMobile;
|
||||||
|
this._syncDataset();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
_syncDataset() {
|
_syncDataset() {
|
||||||
if (this.collapsed) {
|
if (this.isCollapsed) {
|
||||||
document.documentElement.dataset.sidebarCollapsed = '1';
|
document.documentElement.dataset.sidebarCollapsed = '1';
|
||||||
} else {
|
} else {
|
||||||
delete document.documentElement.dataset.sidebarCollapsed;
|
delete document.documentElement.dataset.sidebarCollapsed;
|
||||||
|
|
|
||||||
|
|
@ -98,8 +98,7 @@
|
||||||
|
|
||||||
<aside
|
<aside
|
||||||
x-data="{ wsOpen: false }"
|
x-data="{ wsOpen: false }"
|
||||||
:class="$store.sidebar.isCollapsed ? 'w-16' : 'w-60'"
|
class="sidebar-aside fixed inset-y-0 left-0 h-screen flex flex-col bg-s1 border-r border-white/[.06] z-40 -translate-x-full md:translate-x-0 transition-[width,transform] duration-200 ease-in-out"
|
||||||
class="fixed inset-y-0 left-0 h-screen flex flex-col bg-s1 border-r border-white/[.06] z-40 -translate-x-full md:translate-x-0 transition-[width,transform] duration-200 ease-in-out"
|
|
||||||
:style="$store.sidebar?.mobileOpen ? 'translate: 0' : null"
|
:style="$store.sidebar?.mobileOpen ? 'translate: 0' : null"
|
||||||
>
|
>
|
||||||
<!-- Header: Logo + Workspace Switcher -->
|
<!-- Header: Logo + Workspace Switcher -->
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
try {
|
try {
|
||||||
if (localStorage.getItem('sidebarCollapsed') === 'true') {
|
if (localStorage.getItem('sidebarCollapsed') === 'true' && window.innerWidth >= 768) {
|
||||||
document.documentElement.dataset.sidebarCollapsed = '1';
|
document.documentElement.dataset.sidebarCollapsed = '1';
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
@ -92,6 +92,8 @@
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.nim-content { margin-left: 210px; }
|
.nim-content { margin-left: 210px; }
|
||||||
html[data-sidebar-collapsed] .nim-content { margin-left: 55px; }
|
html[data-sidebar-collapsed] .nim-content { margin-left: 55px; }
|
||||||
|
.sidebar-aside { width: 15rem; }
|
||||||
|
html[data-sidebar-collapsed] .sidebar-aside { width: 4rem; }
|
||||||
}
|
}
|
||||||
body.app-ready .app-spinner,
|
body.app-ready .app-spinner,
|
||||||
body.app-ready .skel-sidebar,
|
body.app-ready .skel-sidebar,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue