feat: implement standard-compliant sidebar with comprehensive tests
Some checks failed
continuous-integration/drone/push Build is failing

Implement a new sidebar component based on DaisyUI Drawer pattern without
custom CSS variants. The sidebar supports desktop (expanded/collapsed states)
and mobile (overlay drawer) with full accessibility compliance.

Sidebar Implementation:
- Refactor sidebar component with sidebar_header, menu_item, menu_group,
  sidebar_footer sub-components
- Add logo (mila.svg) with size-8 (32px) always visible
- Implement toggle button with icon swap (chevron-left/right) for desktop
- Add nested menu support with details/summary (expanded) and dropdown
  (collapsed) patterns
- Implement footer with language selector (expanded-only), theme toggle,
  and user menu with avatar
- Update layouts.ex to use drawer pattern with data-sidebar-expanded
  attribute for state management

CSS & JavaScript:
- Add CSS styles for sidebar state management via data-attribute selectors
- Implement SidebarState JavaScript hook for localStorage persistence
- Add smooth width transitions (w-64 ↔ w-16) for desktop collapsed state
- Add CSS classes for expanded-only, menu-label, and icon visibility

Documentation:
- Add sidebar-analysis-current-state.md: Analysis of current implementation
- Add sidebar-requirements-v2.md: Complete specification for new sidebar
- Add daisyui-drawer-pattern.md: DaisyUI pattern documentation
- Add umsetzung-sidebar.md: Step-by-step implementation guide

Testing:
- Add comprehensive component tests for all sidebar sub-components
- Add integration tests for sidebar state management and mobile drawer
- Extend accessibility tests (ARIA labels, roles, keyboard navigation)
- Add regression tests for duplicate IDs, hover effects, and tooltips
- Ensure full test coverage per specification requirements
This commit is contained in:
Simon 2025-12-18 16:33:44 +01:00
parent b0097ab99d
commit 16ca4efc03
Signed by: simon
GPG key ID: 40E7A58C4AA1EDB2
10 changed files with 5439 additions and 194 deletions

View file

@ -9,7 +9,6 @@ defmodule MvWeb.Layouts do
"""
use MvWeb, :html
use Gettext, backend: MvWeb.Gettext
import MvWeb.Layouts.Navbar
import MvWeb.Layouts.Sidebar
embed_templates "layouts/*"
@ -44,21 +43,39 @@ defmodule MvWeb.Layouts do
assigns = assign(assigns, :club_name, club_name)
~H"""
<div class="drawer">
<input id="main-drawer" type="checkbox" class="drawer-toggle" />
<div class="drawer-content">
<%= if @current_user do %>
<.navbar current_user={@current_user} />
<% end %>
<main class="px-4 py-20 sm:px-6 lg:px-16">
<div class="mx-auto space-y-4 max-full">
{render_slot(@inner_block)}
</div>
</main>
</div>
<%= if @current_user do %>
<div id="app-layout" class="drawer lg:drawer-open" data-sidebar-expanded="true" phx-hook="SidebarState">
<input id="mobile-drawer" type="checkbox" class="drawer-toggle" />
<.sidebar current_user={@current_user} club_name={@club_name} />
</div>
<div class="drawer-content flex flex-col relative z-0">
<!-- Mobile Header (only visible on mobile) -->
<header class="lg:hidden sticky top-0 z-10 navbar bg-base-100 shadow-sm">
<label for="mobile-drawer" class="btn btn-square btn-ghost" aria-label={gettext("Open navigation menu")}>
<.icon name="hero-bars-3" class="size-6" aria-hidden="true" />
</label>
<span class="font-bold">{@club_name}</span>
</header>
<!-- Main Content (shared between mobile and desktop) -->
<main class="px-4 py-8 sm:px-6 lg:px-8">
<div class="mx-auto space-y-4 max-full">
{render_slot(@inner_block)}
</div>
</main>
</div>
<div class="drawer-side z-40">
<.sidebar current_user={@current_user} club_name={@club_name} mobile={false} />
</div>
</div>
<% else %>
<!-- Not logged in -->
<main class="px-4 py-8 sm:px-6">
<div class="mx-auto space-y-4 max-full">
{render_slot(@inner_block)}
</div>
</main>
<% end %>
<.flash_group flash={@flash} />
"""