diff --git a/assets/js/app.ts b/assets/js/app.ts index 69e90563..70a8ccdd 100644 --- a/assets/js/app.ts +++ b/assets/js/app.ts @@ -1375,18 +1375,30 @@ const StatusTitle = { } } -// Sidebar collapse - restore state from localStorage and persist toggle +// Sidebar collapse - restore state from localStorage and persist toggle. +// Uses both mounted() and updated() because LiveView DOM patching can +// strip the client-side "sidebar-collapsed" class on live navigations. const SidebarCollapse = { mounted(this: any) { + this._apply() + this._listen() + }, + updated(this: any) { + this._apply() + }, + _apply(this: any) { if (localStorage.getItem('sidebarCollapsed') === 'true') { this.el.classList.add('sidebar-collapsed') } - this.el.querySelector('[data-sidebar-toggle]')?.addEventListener('click', () => { - // The JS.toggle_class will fire, so we check after a tick - requestAnimationFrame(() => { - const collapsed = this.el.classList.contains('sidebar-collapsed') - localStorage.setItem('sidebarCollapsed', String(collapsed)) - }) + }, + _listen(this: any) { + this.el.addEventListener('click', (e: Event) => { + if ((e.target as HTMLElement).closest('[data-sidebar-toggle]')) { + requestAnimationFrame(() => { + const collapsed = this.el.classList.contains('sidebar-collapsed') + localStorage.setItem('sidebarCollapsed', String(collapsed)) + }) + } }) } } diff --git a/lib/towerops_web/components/layouts.ex b/lib/towerops_web/components/layouts.ex index d878590a..2b4b4884 100644 --- a/lib/towerops_web/components/layouts.ex +++ b/lib/towerops_web/components/layouts.ex @@ -149,6 +149,15 @@ defmodule ToweropsWeb.Layouts do ~H"""