fix: make navigation menus accessible

This commit is contained in:
SimpleTest 2026-07-23 05:11:24 +03:00
parent a167d2ba97
commit bf1eeee8f0
4 changed files with 77 additions and 19 deletions

View File

@ -582,6 +582,43 @@ export const mountStaticAidMaps = root => {
}
export const Hooks = {
AccessibleDisclosure: {
mounted() {
this.summary = this.el.querySelector(":scope > summary")
this.syncExpanded = () => {
this.summary?.setAttribute("aria-expanded", String(this.el.open))
}
this.onKeydown = event => {
if (event.key !== "Escape" || !this.el.open) return
event.preventDefault()
event.stopPropagation()
this.el.open = false
this.syncExpanded()
this.summary?.focus()
}
this.onPointerDown = event => {
if (this.el.open && !this.el.contains(event.target)) {
this.el.open = false
this.syncExpanded()
}
}
this.el.addEventListener("toggle", this.syncExpanded)
this.el.addEventListener("keydown", this.onKeydown)
document.addEventListener("pointerdown", this.onPointerDown)
this.syncExpanded()
},
destroyed() {
this.el.removeEventListener("toggle", this.syncExpanded)
this.el.removeEventListener("keydown", this.onKeydown)
document.removeEventListener("pointerdown", this.onPointerDown)
}
},
NotificationTimeZone: {
mounted() {
const timeZoneInput = this.el.querySelector("[data-time-zone]")

View File

@ -98,10 +98,15 @@ defmodule WhoNeedHelpWeb.Layouts do
</div>
</div>
<details class="dropdown dropdown-end xl:hidden">
<details
id="primary-navigation-disclosure"
phx-hook="AccessibleDisclosure"
class="dropdown dropdown-end xl:hidden"
>
<summary
class="btn btn-ghost btn-square"
aria-label={gettext("Primary navigation")}
aria-expanded="false"
>
<.icon name="hero-bars-3" class="size-6" />
</summary>
@ -130,6 +135,18 @@ defmodule WhoNeedHelpWeb.Layouts do
<li>
<.link href={~p"/users/settings"}>{gettext("Account settings")}</.link>
</li>
<li
:if={@current_scope.user.role in [:moderator, :admin]}
class="menu-title mt-1 border-t border-base-300 pt-2"
>
{gettext("Operations")}
</li>
<li :if={@current_scope.user.role in [:moderator, :admin]}>
<.link navigate={~p"/moderation"}>{gettext("Moderation")}</.link>
</li>
<li :if={@current_scope.user.role in [:moderator, :admin]}>
<.link navigate={~p"/support/operations"}>{gettext("Support queue")}</.link>
</li>
<li>
<.link href={~p"/users/log-out"} method="delete">{gettext("Log out")}</.link>
</li>
@ -218,16 +235,6 @@ defmodule WhoNeedHelpWeb.Layouts do
{gettext("Helpers")}
</.link>
</li>
<li :if={@current_scope && @current_scope.user.role in [:moderator, :admin]}>
<.link navigate={~p"/moderation"} class={["btn-warning", @link_class]}>
{gettext("Moderation")}
</.link>
</li>
<li :if={@current_scope && @current_scope.user.role in [:moderator, :admin]}>
<.link navigate={~p"/support/operations"} class={["btn-warning", @link_class]}>
{gettext("Support queue")}
</.link>
</li>
"""
end
@ -279,8 +286,12 @@ defmodule WhoNeedHelpWeb.Layouts do
defp account_menu(assigns) do
~H"""
<details class="dropdown dropdown-end">
<summary class="btn btn-ghost btn-sm gap-1">
<details
id="account-navigation-disclosure"
phx-hook="AccessibleDisclosure"
class="dropdown dropdown-end"
>
<summary class="btn btn-ghost btn-sm gap-1" aria-expanded="false">
<.icon name="hero-user-circle" class="size-5" />
<span class="flex max-w-36 flex-col items-start overflow-hidden leading-tight">
<span class="max-w-full truncate">
@ -306,6 +317,18 @@ defmodule WhoNeedHelpWeb.Layouts do
<li>
<.link href={~p"/users/settings"}>{gettext("Account settings")}</.link>
</li>
<li
:if={@current_scope.user.role in [:moderator, :admin]}
class="menu-title mt-1 border-t border-base-300 pt-2"
>
{gettext("Operations")}
</li>
<li :if={@current_scope.user.role in [:moderator, :admin]}>
<.link navigate={~p"/moderation"}>{gettext("Moderation")}</.link>
</li>
<li :if={@current_scope.user.role in [:moderator, :admin]}>
<.link navigate={~p"/support/operations"}>{gettext("Support queue")}</.link>
</li>
<li>
<.link href={~p"/users/log-out"} method="delete">{gettext("Log out")}</.link>
</li>

View File

@ -1261,9 +1261,7 @@ defmodule WhoNeedHelpWeb.RequestLive.Show do
class="aid-map"
/>
<div
:if={
@request_coordinates || map_size(@positions) > 0
}
:if={@request_coordinates || map_size(@positions) > 0}
class="flex flex-wrap gap-x-4 gap-y-1 px-1 text-xs text-base-content/65"
aria-label={gettext("Map legend")}
>
@ -1278,8 +1276,7 @@ defmodule WhoNeedHelpWeb.RequestLive.Show do
@request.location_visibility != :approximate_public && "bg-error"
]}
aria-hidden="true"
>
</span>
></span>
<span>
{if @request.location_visibility == :approximate_public,
do: gettext("Request area"),

View File

@ -1018,6 +1018,7 @@ defmodule WhoNeedHelpWeb.MutualAidLiveTest do
assert stopped_session.ended_at
assert stopped_session.sample_count == 0
refute Repo.get_by(WhoNeedHelp.Tracking.Position,
tracking_session_id: stopped_session.id
)