feat: improve sidebar handling
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Simon 2026-01-06 10:29:20 +01:00
parent 16ca4efc03
commit aba8737c38
Signed by: simon
GPG key ID: 40E7A58C4AA1EDB2
6 changed files with 93 additions and 15 deletions

View file

@ -117,16 +117,27 @@
width: 4rem; /* Collapsed: w-16 */
}
/* ============================================
Header - Logo Centering
============================================ */
/* Header container with smooth transition for gap */
.sidebar > div:first-child {
@apply transition-all duration-300;
}
/* ============================================
Text Labels - Hide in Collapsed State
============================================ */
.menu-label {
@apply transition-all duration-200 whitespace-nowrap;
transition-delay: 0ms; /* Expanded: sofort sichtbar */
}
[data-sidebar-expanded="false"] .sidebar .menu-label {
@apply opacity-0 w-0 overflow-hidden pointer-events-none;
transition-delay: 300ms; /* Warte bis Sidebar eingeklappt ist (300ms = duration der Sidebar width transition) */
}
/* ============================================
@ -165,6 +176,11 @@
@apply block;
}
/* Collapsed menu group button: center icon under logo */
.sidebar .collapsed-menu-group button {
padding-left: 14px;
}
/* ============================================
Elements Only Visible in Expanded State
============================================ */
@ -192,20 +208,79 @@
}
/* ============================================
Menu Item Alignment - Center in Collapsed State
Menu Item Alignment - Icons Centered Under Logo
============================================ */
/* Base alignment: Icons centered under logo (32px from left edge)
- Logo center: 16px padding + 16px (half of 32px) = 32px
- Icon center should be at 32px: 22px start + 10px (half of 20px) = 32px
- Menu has p-2 (8px), so links need 14px additional padding-left */
.sidebar .menu > li > a,
.sidebar .menu > li > button {
@apply transition-all duration-300;
padding-left: 14px;
}
/* Collapsed state: same padding to keep icons at same position
- Remove gap so label (which is opacity-0 w-0) doesn't create space
- Keep padding-left at 14px so icons stay centered under logo */
[data-sidebar-expanded="false"] .sidebar .menu > li > a,
[data-sidebar-expanded="false"] .sidebar .menu > li > button {
@apply justify-center px-0;
@apply gap-0;
padding-left: 14px;
padding-right: 14px; /* Center icon horizontally in 64px sidebar */
}
/* ============================================
Footer Button Alignment - Center in Collapsed State
Footer Button Alignment - Left Aligned in Collapsed State
============================================ */
[data-sidebar-expanded="false"] .sidebar .dropdown > button {
@apply justify-center px-0;
@apply px-0;
/* Buttons stay at left position, only label disappears */
}
/* ============================================
User Menu Button - Focus Ring on Avatar
============================================ */
/* Focus ring appears on the avatar when button is focused */
.user-menu-button:focus .avatar > div {
@apply ring-2 ring-primary ring-offset-2 ring-offset-base-200;
}
/* ============================================
User Menu Button - Smooth Centering Transition
============================================ */
/* User menu button transitions smoothly to center */
.user-menu-button {
@apply transition-all duration-300;
}
/* In collapsed state, center avatar under logo
- Avatar is 32px (w-8), center it in 64px sidebar
- (64px - 32px) / 2 = 16px padding avatar center at 32px (same as logo center) */
[data-sidebar-expanded="false"] .sidebar .user-menu-button {
@apply gap-0;
padding-left: 16px;
padding-right: 16px;
justify-content: center;
}
/* ============================================
User Menu Button - Hover Ring on Avatar
============================================ */
/* Smooth transition for avatar ring effects */
.user-menu-button .avatar > div {
@apply transition-all duration-200;
}
/* Hover ring appears on the avatar when button is hovered */
.user-menu-button:hover .avatar > div {
@apply ring-1 ring-neutral ring-offset-1 ring-offset-base-200;
}
/* ============================================

View file

@ -530,3 +530,4 @@ The DaisyUI drawer pattern provides:
**Recommended approach**: Use `lg:drawer-open` for desktop with hidden mobile toggle for best responsive experience.

View file

@ -744,3 +744,4 @@ role="menubar", role="menuitem", role="none", role="status"
**Ende des Berichts**

View file

@ -1248,3 +1248,4 @@ if (localStorage.getItem('sidebar-expanded') === 'false') {
**Ende der Spezifikation**

View file

@ -143,7 +143,7 @@ defmodule MvWeb.Layouts.Sidebar do
<button
type="button"
tabindex="0"
class="flex items-center justify-center w-full p-2 rounded-lg hover:bg-base-300 tooltip tooltip-right focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
class="flex items-center w-full p-2 rounded-lg hover:bg-base-300 tooltip tooltip-right focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
data-tip={@label}
aria-haspopup="menu"
aria-label={@label}
@ -251,18 +251,18 @@ defmodule MvWeb.Layouts.Sidebar do
assigns = assign(assigns, :user_id, user_id)
~H"""
<div class="dropdown dropdown-top dropdown-right w-full">
<div class="dropdown dropdown-top dropdown-end w-full">
<button
type="button"
tabindex="0"
class="btn btn-ghost w-full justify-start gap-3 px-4 h-12 min-h-12 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
class="user-menu-button flex items-center w-full justify-start gap-3 px-4 h-12 min-h-12 rounded-lg cursor-pointer focus:outline-none"
aria-label={gettext("User menu")}
aria-haspopup="menu"
>
<!-- Avatar: Zentriert, erste Buchstabe -->
<!-- Avatar: Placeholder with first letter -->
<div class="avatar placeholder shrink-0">
<div class="w-8 h-8 rounded-full bg-neutral text-neutral-content flex items-center justify-center">
<span class="text-sm font-semibold leading-none flex items-center justify-center" style="margin-top: 1px;">
<div class="w-8 h-8 rounded-full bg-neutral text-neutral-content">
<span class="text-sm font-semibold">
{@first_letter}
</span>
</div>

View file

@ -712,19 +712,19 @@ defmodule MvWeb.Layouts.SidebarTest do
html = render_sidebar(authenticated_assigns(false))
# Toggle button has onclick handler
assert html =~ ~s(onclick="toggleSidebar()")
assert html =~ ~r/onclick="toggleSidebar\(\)"/
end
test "no duplicate IDs in layout" do
html = render_sidebar(authenticated_assigns())
# Check that main-sidebar ID appears only once
id_count = html |> String.split(~s(id="main-sidebar")) |> length() |> Kernel.-(1)
id_count = html |> String.split(~r/id="main-sidebar"/) |> length() |> Kernel.-(1)
assert id_count == 1, "main-sidebar ID should appear exactly once"
# Check that sidebar-toggle ID appears only once (if present)
if html =~ ~s(id="sidebar-toggle") do
toggle_count = html |> String.split(~s(id="sidebar-toggle")) |> length() |> Kernel.-(1)
if html =~ ~r/id="sidebar-toggle"/ do
toggle_count = html |> String.split(~r/id="sidebar-toggle"/) |> length() |> Kernel.-(1)
assert toggle_count == 1, "sidebar-toggle ID should appear exactly once"
end
end
@ -844,7 +844,7 @@ defmodule MvWeb.Layouts.SidebarTest do
assert has_class?(html, "dropdown-content")
# Should have both Profile and Logout links
assert html =~ ~s(href="/sign-out")
assert html =~ "sign-out"
end
end
end