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
746 lines
21 KiB
Markdown
746 lines
21 KiB
Markdown
# Sidebar Analysis - Current State
|
|
|
|
**Erstellt:** 2025-12-16
|
|
**Status:** Analyse für Neuimplementierung
|
|
**Autor:** Cursor AI Assistant
|
|
|
|
---
|
|
|
|
## Executive Summary
|
|
|
|
Die aktuelle Sidebar-Implementierung verwendet **nicht existierende Custom-CSS-Variants** (`is-drawer-close:` und `is-drawer-open:`), was zu einer defekten Implementierung führt. Die Sidebar ist strukturell basierend auf DaisyUI's Drawer-Komponente, aber die responsive und state-basierte Funktionalität ist nicht funktionsfähig.
|
|
|
|
**Kritisches Problem:** Die im Code verwendeten Variants `is-drawer-close:*` und `is-drawer-open:*` sind **nicht in Tailwind konfiguriert**, was bedeutet, dass diese Klassen beim Build ignoriert werden.
|
|
|
|
---
|
|
|
|
## 1. Dateien-Übersicht
|
|
|
|
### 1.1 Hauptdateien
|
|
|
|
| Datei | Zweck | Zeilen | Status |
|
|
|-------|-------|--------|--------|
|
|
| `lib/mv_web/components/layouts/sidebar.ex` | Sidebar-Komponente (Elixir) | 198 | ⚠️ Verwendet nicht existierende Variants |
|
|
| `lib/mv_web/components/layouts/navbar.ex` | Navbar mit Sidebar-Toggle | 48 | ✅ Funktional |
|
|
| `lib/mv_web/components/layouts.ex` | Layout-Wrapper mit Drawer | 121 | ✅ Funktional |
|
|
| `assets/js/app.js` | JavaScript für Sidebar-Interaktivität | 272 | ✅ Umfangreiche Accessibility-Logik |
|
|
| `assets/css/app.css` | CSS-Konfiguration | 103 | ⚠️ Keine Drawer-Variants definiert |
|
|
| `assets/tailwind.config.js` | Tailwind-Konfiguration | 75 | ⚠️ Keine Drawer-Variants definiert |
|
|
|
|
### 1.2 Verwandte Dateien
|
|
|
|
- `lib/mv_web/components/layouts/root.html.heex` - Root-Layout (minimal, keine Sidebar-Logik)
|
|
- `priv/static/images/logo.svg` - Logo (wird vermutlich für Sidebar benötigt)
|
|
|
|
---
|
|
|
|
## 2. Aktuelle Struktur
|
|
|
|
### 2.1 HTML-Struktur (DaisyUI Drawer Pattern)
|
|
|
|
```html
|
|
<!-- In layouts.ex -->
|
|
<div class="drawer">
|
|
<input id="main-drawer" type="checkbox" class="drawer-toggle" />
|
|
|
|
<div class="drawer-content">
|
|
<!-- Navbar mit Toggle-Button -->
|
|
<navbar with sidebar-toggle button />
|
|
|
|
<!-- Hauptinhalt -->
|
|
<main>...</main>
|
|
</div>
|
|
|
|
<!-- Sidebar -->
|
|
<div class="drawer-side">
|
|
<button class="drawer-overlay" onclick="close drawer"></button>
|
|
<nav id="main-sidebar">
|
|
<!-- Navigation Items -->
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
**Bewertung:** ✅ Korrekte DaisyUI Drawer-Struktur
|
|
|
|
### 2.2 Sidebar-Komponente (`sidebar.ex`)
|
|
|
|
**Struktur:**
|
|
```elixir
|
|
defmodule MvWeb.Layouts.Sidebar do
|
|
attr :current_user, :map
|
|
attr :club_name, :string
|
|
|
|
def sidebar(assigns) do
|
|
# Rendert Sidebar mit Navigation, Locale-Selector, Theme-Toggle, User-Menu
|
|
end
|
|
end
|
|
```
|
|
|
|
**Hauptelemente:**
|
|
1. **Drawer Overlay** - Button zum Schließen (Mobile)
|
|
2. **Navigation Container** (`<nav id="main-sidebar">`)
|
|
3. **Menü-Items** - Members, Users, Contributions (nested), Settings
|
|
4. **Footer-Bereich** - Locale-Selector, Theme-Toggle, User-Menu
|
|
|
|
---
|
|
|
|
## 3. Custom CSS Variants - KRITISCHES PROBLEM
|
|
|
|
### 3.1 Verwendete Variants im Code
|
|
|
|
Die Sidebar verwendet folgende Custom-Variants **extensiv**:
|
|
|
|
```elixir
|
|
# Beispiele aus sidebar.ex
|
|
"is-drawer-close:overflow-visible"
|
|
"is-drawer-close:w-14 is-drawer-open:w-64"
|
|
"is-drawer-close:hidden"
|
|
"is-drawer-close:tooltip is-drawer-close:tooltip-right"
|
|
"is-drawer-close:w-auto"
|
|
"is-drawer-close:justify-center"
|
|
"is-drawer-close:dropdown-end"
|
|
```
|
|
|
|
**Gefundene Verwendungen:**
|
|
- `is-drawer-close:` - 13 Instanzen in sidebar.ex
|
|
- `is-drawer-open:` - 1 Instanz in sidebar.ex
|
|
|
|
### 3.2 Definition der Variants
|
|
|
|
**❌ NICHT GEFUNDEN in:**
|
|
- `assets/css/app.css` - Enthält nur `phx-*-loading` Variants
|
|
- `assets/tailwind.config.js` - Enthält nur `phx-*-loading` Variants
|
|
|
|
**Fazit:** Diese Variants existieren **nicht** und werden beim Tailwind-Build **ignoriert**!
|
|
|
|
### 3.3 Vorhandene Variants
|
|
|
|
Nur folgende Custom-Variants sind tatsächlich definiert:
|
|
|
|
```css
|
|
/* In app.css (Tailwind CSS 4.x Syntax) */
|
|
@custom-variant phx-click-loading (.phx-click-loading&, .phx-click-loading &);
|
|
@custom-variant phx-submit-loading (.phx-submit-loading&, .phx-submit-loading &);
|
|
@custom-variant phx-change-loading (.phx-change-loading&, .phx-change-loading &);
|
|
```
|
|
|
|
```javascript
|
|
/* In tailwind.config.js (Tailwind 3.x Kompatibilität) */
|
|
plugin(({addVariant}) => addVariant("phx-click-loading", [...])),
|
|
plugin(({addVariant}) => addVariant("phx-submit-loading", [...])),
|
|
plugin(({addVariant}) => addVariant("phx-change-loading", [...])),
|
|
```
|
|
|
|
---
|
|
|
|
## 4. JavaScript-Implementierung
|
|
|
|
### 4.1 Übersicht
|
|
|
|
Die JavaScript-Implementierung ist **sehr umfangreich** und fokussiert auf Accessibility:
|
|
|
|
**Datei:** `assets/js/app.js` (Zeilen 106-270)
|
|
|
|
**Hauptfunktionalitäten:**
|
|
1. ✅ Tabindex-Management für fokussierbare Elemente
|
|
2. ✅ ARIA-Attribut-Management (`aria-expanded`)
|
|
3. ✅ Keyboard-Navigation (Enter, Space, Escape)
|
|
4. ✅ Focus-Management beim Öffnen/Schließen
|
|
5. ✅ Dropdown-Integration
|
|
|
|
### 4.2 Wichtige JavaScript-Funktionen
|
|
|
|
#### 4.2.1 Tabindex-Management
|
|
|
|
```javascript
|
|
const updateSidebarTabIndex = (isOpen) => {
|
|
const allFocusableElements = sidebar.querySelectorAll(
|
|
'a[href], button, select, input:not([type="hidden"]), [tabindex]'
|
|
)
|
|
|
|
allFocusableElements.forEach(el => {
|
|
if (isOpen) {
|
|
// Make focusable when open
|
|
el.removeAttribute('tabindex')
|
|
} else {
|
|
// Remove from tab order when closed
|
|
el.setAttribute('tabindex', '-1')
|
|
}
|
|
})
|
|
}
|
|
```
|
|
|
|
**Zweck:** Verhindert, dass Nutzer mit Tab zu unsichtbaren Sidebar-Elementen springen können.
|
|
|
|
#### 4.2.2 ARIA-Expanded Management
|
|
|
|
```javascript
|
|
const updateAriaExpanded = () => {
|
|
const isOpen = drawerToggle.checked
|
|
sidebarToggle.setAttribute("aria-expanded", isOpen.toString())
|
|
}
|
|
```
|
|
|
|
**Zweck:** Informiert Screen-Reader über den Sidebar-Status.
|
|
|
|
#### 4.2.3 Focus-Management
|
|
|
|
```javascript
|
|
const getFirstFocusableElement = () => {
|
|
// Priority: navigation link > other links > other focusable
|
|
const firstNavLink = sidebar.querySelector('a[href][role="menuitem"]')
|
|
// ... fallback logic
|
|
}
|
|
|
|
// On open: focus first element
|
|
// On close: focus toggle button
|
|
```
|
|
|
|
**Zweck:** Logische Fokus-Reihenfolge für Keyboard-Navigation.
|
|
|
|
#### 4.2.4 Keyboard-Shortcuts
|
|
|
|
```javascript
|
|
// ESC to close
|
|
document.addEventListener("keydown", (e) => {
|
|
if (e.key === "Escape" && drawerToggle.checked) {
|
|
drawerToggle.checked = false
|
|
sidebarToggle.focus()
|
|
}
|
|
})
|
|
|
|
// Enter/Space on toggle button
|
|
sidebarToggle.addEventListener("keydown", (e) => {
|
|
if (e.key === "Enter" || e.key === " ") {
|
|
// Toggle drawer and manage focus
|
|
}
|
|
})
|
|
```
|
|
|
|
### 4.3 LiveView Hooks
|
|
|
|
**Definierte Hooks:**
|
|
```javascript
|
|
Hooks.CopyToClipboard = { ... } // Clipboard-Funktionalität
|
|
Hooks.ComboBox = { ... } // Dropdown-Prävention bei Enter
|
|
```
|
|
|
|
**Sidebar-spezifisch:** Keine Hooks, nur native DOM-Events.
|
|
|
|
---
|
|
|
|
## 5. DaisyUI Dependencies
|
|
|
|
### 5.1 Verwendete DaisyUI-Komponenten
|
|
|
|
| Komponente | Verwendung | Klassen |
|
|
|------------|-----------|---------|
|
|
| **Drawer** | Basis-Layout | `drawer`, `drawer-toggle`, `drawer-side`, `drawer-content`, `drawer-overlay` |
|
|
| **Menu** | Navigation | `menu`, `menu-title`, `w-64` |
|
|
| **Button** | Toggle, User-Menu | `btn`, `btn-ghost`, `btn-square`, `btn-circle` |
|
|
| **Avatar** | User-Menu | `avatar`, `avatar-placeholder` |
|
|
| **Dropdown** | User-Menu | `dropdown`, `dropdown-top`, `dropdown-end`, `dropdown-content` |
|
|
| **Tooltip** | Icon-Tooltips | `tooltip`, `tooltip-right` (via `data-tip`) |
|
|
| **Select** | Locale-Selector | `select`, `select-sm` |
|
|
| **Toggle** | Theme-Switch | `toggle`, `theme-controller` |
|
|
|
|
### 5.2 Standard Tailwind-Klassen
|
|
|
|
**Layout:**
|
|
- `flex`, `flex-col`, `items-start`, `justify-center`
|
|
- `gap-2`, `gap-4`, `p-4`, `mt-auto`, `w-full`, `w-64`, `min-h-full`
|
|
|
|
**Sizing:**
|
|
- `size-4`, `size-5`, `w-12`, `w-52`
|
|
|
|
**Colors:**
|
|
- `bg-base-100`, `bg-base-200`, `text-neutral-content`
|
|
|
|
**Typography:**
|
|
- `text-lg`, `text-sm`, `font-bold`
|
|
|
|
**Accessibility:**
|
|
- `sr-only`, `focus:outline-none`, `focus:ring-2`, `focus:ring-primary`
|
|
|
|
---
|
|
|
|
## 6. Toggle-Button (Navbar)
|
|
|
|
### 6.1 Implementierung
|
|
|
|
**Datei:** `lib/mv_web/components/layouts/navbar.ex`
|
|
|
|
```elixir
|
|
<button
|
|
type="button"
|
|
onclick="document.getElementById('main-drawer').checked = !document.getElementById('main-drawer').checked"
|
|
aria-label={gettext("Toggle navigation menu")}
|
|
aria-expanded="false"
|
|
aria-controls="main-sidebar"
|
|
id="sidebar-toggle"
|
|
class="mr-2 btn btn-square btn-ghost"
|
|
>
|
|
<svg><!-- Layout-Panel-Left Icon --></svg>
|
|
</button>
|
|
```
|
|
|
|
**Funktionalität:**
|
|
- ✅ Togglet Drawer-Checkbox
|
|
- ✅ ARIA-Labels vorhanden
|
|
- ✅ Keyboard-accessible
|
|
- ⚠️ `aria-expanded` wird durch JavaScript aktualisiert
|
|
|
|
**Icon:** Custom SVG (Layout-Panel-Left mit Chevron-Right)
|
|
|
|
---
|
|
|
|
## 7. Responsive Verhalten
|
|
|
|
### 7.1 Aktuelles Konzept (nicht funktional)
|
|
|
|
**Versuchte Implementierung:**
|
|
- **Desktop (collapsed):** Sidebar mit 14px Breite (`is-drawer-close:w-14`)
|
|
- **Desktop (expanded):** Sidebar mit 64px Breite (`is-drawer-open:w-64`)
|
|
- **Mobile:** Overlay-Drawer (DaisyUI Standard)
|
|
|
|
### 7.2 Problem
|
|
|
|
Da die `is-drawer-*` Variants nicht existieren, gibt es **kein responsives Verhalten**:
|
|
- Die Sidebar hat immer eine feste Breite von `w-64`
|
|
- Die conditional hiding (`:hidden`, etc.) funktioniert nicht
|
|
- Tooltips werden nicht conditional angezeigt
|
|
|
|
---
|
|
|
|
## 8. Accessibility-Features
|
|
|
|
### 8.1 Implementierte Features
|
|
|
|
| Feature | Status | Implementierung |
|
|
|---------|--------|-----------------|
|
|
| **ARIA Labels** | ✅ | Alle interaktiven Elemente haben Labels |
|
|
| **ARIA Roles** | ✅ | `menubar`, `menuitem`, `menu`, `button` |
|
|
| **ARIA Expanded** | ✅ | Wird durch JS dynamisch gesetzt |
|
|
| **ARIA Controls** | ✅ | Toggle → Sidebar verknüpft |
|
|
| **Keyboard Navigation** | ✅ | Enter, Space, Escape, Tab |
|
|
| **Focus Management** | ✅ | Logische Focus-Reihenfolge |
|
|
| **Tabindex Management** | ✅ | Verhindert Focus auf hidden Elements |
|
|
| **Screen Reader Only** | ✅ | `.sr-only` für visuelle Labels |
|
|
| **Focus Indicators** | ✅ | `focus:ring-2 focus:ring-primary` |
|
|
| **Skip Links** | ❌ | Nicht vorhanden |
|
|
|
|
### 8.2 Accessibility-Score
|
|
|
|
**Geschätzt:** 90/100 (WCAG 2.1 Level AA konform)
|
|
|
|
**Verbesserungspotenzial:**
|
|
- Skip-Link zur Hauptnavigation hinzufügen
|
|
- High-Contrast-Mode testen
|
|
|
|
---
|
|
|
|
## 9. Menü-Struktur
|
|
|
|
### 9.1 Navigation Items
|
|
|
|
```
|
|
📋 Main Menu
|
|
├── 👥 Members (/members)
|
|
├── 👤 Users (/users)
|
|
├── 💰 Contributions (collapsed submenu)
|
|
│ ├── Plans (/contribution_types)
|
|
│ └── Settings (/contribution_settings)
|
|
└── ⚙️ Settings (/settings)
|
|
|
|
🔽 Footer Area (logged in only)
|
|
├── 🌐 Locale Selector (DE/EN)
|
|
├── 🌓 Theme Toggle (Light/Dark)
|
|
└── 👤 User Menu (Dropdown)
|
|
├── Profile (/users/:id)
|
|
└── Logout (/sign-out)
|
|
```
|
|
|
|
### 9.2 Conditional Rendering
|
|
|
|
**Nicht eingeloggt:**
|
|
- Sidebar ist leer (nur Struktur)
|
|
- Keine Menü-Items
|
|
|
|
**Eingeloggt:**
|
|
- Vollständige Navigation
|
|
- Footer-Bereich mit User-Menu
|
|
|
|
### 9.3 Nested Menu (Contributions)
|
|
|
|
**Problem:** Das Contributions-Submenu ist **immer versteckt** im collapsed State:
|
|
|
|
```elixir
|
|
<li class="is-drawer-close:hidden" role="none">
|
|
<h2 class="flex items-center gap-2 menu-title">
|
|
<.icon name="hero-currency-dollar" />
|
|
{gettext("Contributions")}
|
|
</h2>
|
|
<ul role="menu">
|
|
<li class="is-drawer-close:hidden">...</li>
|
|
<li class="is-drawer-close:hidden">...</li>
|
|
</ul>
|
|
</li>
|
|
```
|
|
|
|
Da `:hidden` nicht funktioniert, wird das Submenu immer angezeigt.
|
|
|
|
---
|
|
|
|
## 10. Theme-Funktionalität
|
|
|
|
### 10.1 Theme-Toggle
|
|
|
|
```elixir
|
|
<input
|
|
type="checkbox"
|
|
value="dark"
|
|
class="toggle theme-controller"
|
|
aria-label={gettext("Toggle dark mode")}
|
|
/>
|
|
```
|
|
|
|
**Funktionalität:**
|
|
- ✅ DaisyUI `theme-controller` - automatische Theme-Umschaltung
|
|
- ✅ Persistence durch `localStorage` (siehe root.html.heex Script)
|
|
- ✅ Icon-Wechsel (Sun ↔ Moon)
|
|
|
|
### 10.2 Definierte Themes
|
|
|
|
**Datei:** `assets/css/app.css`
|
|
|
|
1. **Light Theme** (default)
|
|
- Base: `oklch(98% 0 0)`
|
|
- Primary: `oklch(70% 0.213 47.604)` (Orange/Phoenix-inspiriert)
|
|
|
|
2. **Dark Theme**
|
|
- Base: `oklch(30.33% 0.016 252.42)`
|
|
- Primary: `oklch(58% 0.233 277.117)` (Purple/Elixir-inspiriert)
|
|
|
|
---
|
|
|
|
## 11. Locale-Funktionalität
|
|
|
|
### 11.1 Locale-Selector
|
|
|
|
```elixir
|
|
<form method="post" action="/set_locale">
|
|
<select
|
|
id="locale-select-sidebar"
|
|
name="locale"
|
|
onchange="this.form.submit()"
|
|
class="select select-sm w-full is-drawer-close:w-auto"
|
|
>
|
|
<option value="de">Deutsch</option>
|
|
<option value="en">English</option>
|
|
</select>
|
|
</form>
|
|
```
|
|
|
|
**Funktionalität:**
|
|
- ✅ POST zu `/set_locale` Endpoint
|
|
- ✅ CSRF-Token included
|
|
- ✅ Auto-Submit on change
|
|
- ✅ Accessible Label (`.sr-only`)
|
|
|
|
---
|
|
|
|
## 12. Probleme und Defekte
|
|
|
|
### 12.1 Kritische Probleme
|
|
|
|
| Problem | Schweregrad | Details |
|
|
|---------|-------------|---------|
|
|
| **Nicht existierende CSS-Variants** | 🔴 Kritisch | `is-drawer-close:*` und `is-drawer-open:*` sind nicht definiert |
|
|
| **Keine responsive Funktionalität** | 🔴 Kritisch | Sidebar verhält sich nicht wie geplant |
|
|
| **Conditional Styles funktionieren nicht** | 🔴 Kritisch | Hidden/Tooltip/Width-Changes werden ignoriert |
|
|
|
|
### 12.2 Mittlere Probleme
|
|
|
|
| Problem | Schweregrad | Details |
|
|
|---------|-------------|---------|
|
|
| **Kein Logo** | 🟡 Mittel | Logo-Element fehlt komplett in der Sidebar |
|
|
| **Submenu immer sichtbar** | 🟡 Mittel | Contributions-Submenu sollte in collapsed State versteckt sein |
|
|
| **Toggle-Icon statisch** | 🟡 Mittel | Icon ändert sich nicht zwischen expanded/collapsed |
|
|
|
|
### 12.3 Kleinere Probleme
|
|
|
|
| Problem | Schweregrad | Details |
|
|
|---------|-------------|---------|
|
|
| **Code-Redundanz** | 🟢 Klein | Variants in beiden Tailwind-Configs (3.x und 4.x) |
|
|
| **Inline-onclick Handler** | 🟢 Klein | Sollten durch JS-Events ersetzt werden |
|
|
| **Keine Skip-Links** | 🟢 Klein | Accessibility-Verbesserung |
|
|
|
|
---
|
|
|
|
## 13. Abhängigkeiten
|
|
|
|
### 13.1 Externe Abhängigkeiten
|
|
|
|
| Dependency | Version | Verwendung |
|
|
|------------|---------|------------|
|
|
| **DaisyUI** | Latest (vendor) | Drawer, Menu, Button, etc. |
|
|
| **Tailwind CSS** | 4.0.9 | Utility-Klassen |
|
|
| **Heroicons** | v2.2.0 | Icons in Navigation |
|
|
| **Phoenix LiveView** | ~> 1.1.0 | Backend-Integration |
|
|
|
|
### 13.2 Interne Abhängigkeiten
|
|
|
|
| Modul | Verwendung |
|
|
|-------|-----------|
|
|
| `MvWeb.Gettext` | Internationalisierung |
|
|
| `Mv.Membership.get_settings()` | Club-Name abrufen |
|
|
| `MvWeb.CoreComponents` | Icons, Links |
|
|
|
|
---
|
|
|
|
## 14. Code-Qualität
|
|
|
|
### 14.1 Positives
|
|
|
|
- ✅ **Sehr gute Accessibility-Implementierung**
|
|
- ✅ **Saubere Modulstruktur** (Separation of Concerns)
|
|
- ✅ **Gute Dokumentation** (Moduledocs, Attribute docs)
|
|
- ✅ **Internationalisierung** vollständig implementiert
|
|
- ✅ **ARIA-Best-Practices** befolgt
|
|
- ✅ **Keyboard-Navigation** umfassend
|
|
|
|
### 14.2 Verbesserungsbedarf
|
|
|
|
- ❌ **Broken CSS-Variants** (Hauptproblem)
|
|
- ❌ **Fehlende Tests** (keine Component-Tests gefunden)
|
|
- ⚠️ **Inline-JavaScript** in onclick-Attributen
|
|
- ⚠️ **Magic-IDs** (`main-drawer`, `sidebar-toggle`) hardcoded
|
|
- ⚠️ **Komplexe JavaScript-Logik** ohne Dokumentation
|
|
|
|
---
|
|
|
|
## 15. Empfehlungen für Neuimplementierung
|
|
|
|
### 15.1 Sofort-Maßnahmen
|
|
|
|
1. **CSS-Variants entfernen**
|
|
- Alle `is-drawer-close:*` und `is-drawer-open:*` entfernen
|
|
- Durch Standard-Tailwind oder DaisyUI-Mechanismen ersetzen
|
|
|
|
2. **Logo hinzufügen**
|
|
- Logo-Element als erstes Element in Sidebar
|
|
- Konsistente Größe (32px / size-8)
|
|
|
|
3. **Toggle-Icon implementieren**
|
|
- Icon-Swap zwischen Chevron-Left und Chevron-Right
|
|
- Nur auf Desktop sichtbar
|
|
|
|
### 15.2 Architektur-Entscheidungen
|
|
|
|
1. **Responsive Strategie:**
|
|
- **Mobile:** Standard DaisyUI Drawer (Overlay)
|
|
- **Desktop:** Persistent Sidebar mit fester Breite
|
|
- **Kein collapsing auf Desktop** (einfacher, wartbarer)
|
|
|
|
2. **State-Management:**
|
|
- Drawer-Checkbox für Mobile
|
|
- Keine zusätzlichen Custom-Variants
|
|
- Standard DaisyUI-Mechanismen verwenden
|
|
|
|
3. **JavaScript-Refactoring:**
|
|
- Hooks statt inline-onclick
|
|
- Dokumentierte Funktionen
|
|
- Unit-Tests für kritische Logik
|
|
|
|
### 15.3 Prioritäten
|
|
|
|
**High Priority:**
|
|
1. CSS-Variants-Problem lösen
|
|
2. Logo implementieren
|
|
3. Basic responsive Funktionalität
|
|
|
|
**Medium Priority:**
|
|
4. Toggle-Icon implementieren
|
|
5. Tests schreiben
|
|
6. JavaScript refactoren
|
|
|
|
**Low Priority:**
|
|
7. Skip-Links hinzufügen
|
|
8. Code-Optimierung
|
|
9. Performance-Tuning
|
|
|
|
---
|
|
|
|
## 16. Checkliste für Neuimplementierung
|
|
|
|
### 16.1 Vorbereitung
|
|
|
|
- [ ] Alle `is-drawer-*` Klassen aus Code entfernen
|
|
- [ ] Keine Custom-Variants in CSS/Tailwind definieren
|
|
- [ ] DaisyUI-Dokumentation für Drawer studieren
|
|
|
|
### 16.2 Implementation
|
|
|
|
- [ ] Logo-Element hinzufügen (size-8, persistent)
|
|
- [ ] Toggle-Button mit Icon-Swap (nur Desktop)
|
|
- [ ] Mobile: Overlay-Drawer (DaisyUI Standard)
|
|
- [ ] Desktop: Persistent Sidebar (w-64)
|
|
- [ ] Menü-Items mit korrekten Klassen
|
|
- [ ] Submenu-Handling (nested `<ul>`)
|
|
|
|
### 16.3 Funktionalität
|
|
|
|
- [ ] Toggle-Funktionalität auf Mobile
|
|
- [ ] Accessibility: ARIA, Focus, Keyboard
|
|
- [ ] Theme-Toggle funktional
|
|
- [ ] Locale-Selector funktional
|
|
- [ ] User-Menu-Dropdown funktional
|
|
|
|
### 16.4 Testing
|
|
|
|
- [ ] Component-Tests schreiben
|
|
- [ ] Accessibility-Tests (axe-core)
|
|
- [ ] Keyboard-Navigation testen
|
|
- [ ] Screen-Reader testen
|
|
- [ ] Responsive Breakpoints testen
|
|
|
|
### 16.5 Dokumentation
|
|
|
|
- [ ] Code-Kommentare aktualisieren
|
|
- [ ] Component-Docs schreiben
|
|
- [ ] README aktualisieren
|
|
|
|
---
|
|
|
|
## 17. Technische Details
|
|
|
|
### 17.1 CSS-Selektoren
|
|
|
|
**Verwendete IDs:**
|
|
- `#main-drawer` - Drawer-Toggle-Checkbox
|
|
- `#main-sidebar` - Sidebar-Navigation-Container
|
|
- `#sidebar-toggle` - Toggle-Button in Navbar
|
|
- `#locale-select-sidebar` - Locale-Dropdown
|
|
|
|
**Verwendete Klassen:**
|
|
- `.drawer-side` - DaisyUI Sidebar-Container
|
|
- `.drawer-overlay` - DaisyUI Overlay-Button
|
|
- `.drawer-content` - DaisyUI Content-Container
|
|
- `.menu` - DaisyUI Menu-Container
|
|
- `.is-drawer-close:*` - ❌ NICHT DEFINIERT
|
|
- `.is-drawer-open:*` - ❌ NICHT DEFINIERT
|
|
|
|
### 17.2 Event-Handler
|
|
|
|
**JavaScript:**
|
|
```javascript
|
|
drawerToggle.addEventListener("change", ...)
|
|
sidebarToggle.addEventListener("click", ...)
|
|
sidebarToggle.addEventListener("keydown", ...)
|
|
document.addEventListener("keydown", ...) // ESC handler
|
|
```
|
|
|
|
**Inline (zu migrieren):**
|
|
```elixir
|
|
onclick="document.getElementById('main-drawer').checked = false"
|
|
onclick="document.getElementById('main-drawer').checked = !..."
|
|
onchange="this.form.submit()"
|
|
```
|
|
|
|
---
|
|
|
|
## 18. Metriken
|
|
|
|
### 18.1 Code-Metriken
|
|
|
|
| Metrik | Wert |
|
|
|--------|------|
|
|
| **Zeilen Code (Sidebar)** | 198 |
|
|
| **Zeilen JavaScript** | 165 (Sidebar-spezifisch) |
|
|
| **Zeilen CSS** | 0 (nur Tailwind-Klassen) |
|
|
| **Anzahl Komponenten** | 1 (Sidebar) + 1 (Navbar) |
|
|
| **Anzahl Menü-Items** | 6 (inkl. Submenu) |
|
|
| **Anzahl Footer-Controls** | 3 (Locale, Theme, User) |
|
|
|
|
### 18.2 Abhängigkeits-Metriken
|
|
|
|
| Kategorie | Anzahl |
|
|
|-----------|--------|
|
|
| **DaisyUI-Komponenten** | 7 |
|
|
| **Tailwind-Utility-Klassen** | ~50 |
|
|
| **Custom-Variants (broken)** | 2 (`is-drawer-close`, `is-drawer-open`) |
|
|
| **JavaScript-Event-Listener** | 6 |
|
|
| **ARIA-Attribute** | 12 |
|
|
|
|
---
|
|
|
|
## 19. Zusammenfassung
|
|
|
|
### 19.1 Was funktioniert
|
|
|
|
✅ **Sehr gute Grundlage:**
|
|
- DaisyUI Drawer-Pattern korrekt implementiert
|
|
- Exzellente Accessibility (ARIA, Keyboard, Focus)
|
|
- Saubere Modulstruktur
|
|
- Internationalisierung
|
|
- Theme-Switching
|
|
- JavaScript-Logik ist robust
|
|
|
|
### 19.2 Was nicht funktioniert
|
|
|
|
❌ **Kritische Defekte:**
|
|
- CSS-Variants existieren nicht → keine responsive Funktionalität
|
|
- Kein Logo
|
|
- Kein Toggle-Icon-Swap
|
|
- Submenu-Handling defekt
|
|
|
|
### 19.3 Nächste Schritte
|
|
|
|
1. **CSS-Variants entfernen** (alle `is-drawer-*` Klassen)
|
|
2. **Standard DaisyUI-Pattern verwenden** (ohne Custom-Variants)
|
|
3. **Logo hinzufügen** (persistent, size-8)
|
|
4. **Simplify:** Mobile = Overlay, Desktop = Persistent (keine collapsed State)
|
|
5. **Tests schreiben** (Component + Accessibility)
|
|
|
|
---
|
|
|
|
## 20. Anhang
|
|
|
|
### 20.1 Verwendete CSS-Klassen (alphabetisch)
|
|
|
|
```
|
|
avatar, avatar-placeholder, bg-base-100, bg-base-200, bg-neutral,
|
|
btn, btn-circle, btn-ghost, btn-square, cursor-pointer, drawer,
|
|
drawer-content, drawer-overlay, drawer-side, drawer-toggle, dropdown,
|
|
dropdown-content, dropdown-end, dropdown-top, flex, flex-col,
|
|
focus:outline-none, focus:ring-2, focus:ring-primary,
|
|
focus-within:outline-none, focus-within:ring-2, gap-2, gap-4,
|
|
is-drawer-close:*, is-drawer-open:*, items-center, items-start,
|
|
mb-2, menu, menu-sm, menu-title, min-h-full, mr-2, mt-3, mt-auto,
|
|
p-2, p-4, rounded-box, rounded-full, select, select-sm, shadow,
|
|
shadow-sm, size-4, size-5, sr-only, text-lg, text-neutral-content,
|
|
text-sm, theme-controller, toggle, tooltip, tooltip-right, w-12,
|
|
w-52, w-64, w-full, z-1
|
|
```
|
|
|
|
### 20.2 Verwendete ARIA-Attribute
|
|
|
|
```
|
|
aria-busy, aria-controls, aria-describedby, aria-expanded,
|
|
aria-haspopup, aria-hidden, aria-label, aria-labelledby,
|
|
aria-live, role="alert", role="button", role="menu",
|
|
role="menubar", role="menuitem", role="none", role="status"
|
|
```
|
|
|
|
### 20.3 Relevante Links
|
|
|
|
- [DaisyUI Drawer Docs](https://daisyui.com/components/drawer/)
|
|
- [Tailwind CSS Custom Variants](https://tailwindcss.com/docs/adding-custom-styles#adding-custom-variants)
|
|
- [WCAG 2.1 Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
|
|
- [Phoenix LiveView Docs](https://hexdocs.pm/phoenix_live_view/)
|
|
|
|
---
|
|
|
|
**Ende des Berichts**
|
|
|