diff --git a/css/components.css b/css/components.css index 0c17001..862c151 100644 --- a/css/components.css +++ b/css/components.css @@ -391,7 +391,7 @@ app-shell main { .dropdown-menu { position: absolute; - top: 100%; + top: 45px; right: 0; min-width: 150px; background-color: var(--color-bg); @@ -413,12 +413,20 @@ app-shell main { } .dropdown-item { - display: block; + display: flex; + align-items: center; + gap: var(--space-sm); width: 100%; padding: var(--space-sm) var(--space-md); text-align: left; border-radius: var(--radius-sm); color: var(--color-text); + background: none; + border: none; + font-size: inherit; + cursor: pointer; + text-decoration: none; + white-space: nowrap; } .dropdown-item:hover { @@ -429,3 +437,32 @@ app-shell main { background-color: var(--color-primary-light); color: var(--color-primary); } + +.dropdown-item svg { + flex-shrink: 0; + opacity: 0.7; +} + +.dropdown-item-danger { + color: var(--color-error); +} + +.dropdown-item-danger:hover { + background-color: var(--color-error); + color: white; +} + +.dropdown-item-danger:hover svg { + opacity: 1; +} + +.dropdown-divider { + height: 1px; + background-color: var(--color-border); + margin: var(--space-xs) 0; +} + +.dropdown-menu-right { + right: 0; + left: auto; +} diff --git a/js/components/app-header.js b/js/components/app-header.js index 4c36f15..cbee66a 100644 --- a/js/components/app-header.js +++ b/js/components/app-header.js @@ -6,6 +6,7 @@ class AppHeader extends HTMLElement { constructor() { super() this.langDropdownOpen = false + this.profileDropdownOpen = false this.handleOutsideClick = this.handleOutsideClick.bind(this) this.handleKeydown = this.handleKeydown.bind(this) this.handleScroll = this.handleScroll.bind(this) @@ -38,7 +39,10 @@ class AppHeader extends HTMLElement { handleOutsideClick() { if (this.langDropdownOpen) { - this.closeDropdown() + this.closeLangDropdown() + } + if (this.profileDropdownOpen) { + this.closeProfileDropdown() } } @@ -51,7 +55,7 @@ class AppHeader extends HTMLElement { switch (e.key) { case 'Escape': e.preventDefault() - this.closeDropdown() + this.closeLangDropdown() this.querySelector('#lang-toggle')?.focus() break case 'ArrowDown': @@ -67,7 +71,7 @@ class AppHeader extends HTMLElement { } } - closeDropdown() { + closeLangDropdown() { this.langDropdownOpen = false const langDropdown = this.querySelector('#lang-dropdown') const langToggle = this.querySelector('#lang-toggle') @@ -75,13 +79,29 @@ class AppHeader extends HTMLElement { langToggle?.setAttribute('aria-expanded', 'false') } - openDropdown() { + openLangDropdown() { this.langDropdownOpen = true const langDropdown = this.querySelector('#lang-dropdown') const langToggle = this.querySelector('#lang-toggle') langDropdown?.classList.add('open') langToggle?.setAttribute('aria-expanded', 'true') - this.querySelector('.dropdown-item.active')?.focus() + this.querySelector('#lang-dropdown .dropdown-item.active')?.focus() + } + + closeProfileDropdown() { + this.profileDropdownOpen = false + const dropdown = this.querySelector('#profile-dropdown') + const toggle = this.querySelector('#profile-toggle') + dropdown?.classList.remove('open') + toggle?.setAttribute('aria-expanded', 'false') + } + + openProfileDropdown() { + this.profileDropdownOpen = true + const dropdown = this.querySelector('#profile-dropdown') + const toggle = this.querySelector('#profile-toggle') + dropdown?.classList.add('open') + toggle?.setAttribute('aria-expanded', 'true') } render() { @@ -151,13 +171,60 @@ class AppHeader extends HTMLElement { ${auth.isLoggedIn() ? ` - +