From 06fde717c09ef65f1468b3afd491b5c9f8a4e159 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Mon, 26 Jan 2026 13:02:03 -0600 Subject: [PATCH] accessibility and poller updates --- lib/towerops_web.ex | 2 +- .../components/core_components.ex | 34 ++++++++++-- lib/towerops_web/components/layouts.ex | 53 ++++++++++++++++--- .../components/layouts/root.html.heex | 6 +++ priv/static/changelog.txt | 4 ++ 5 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 priv/static/changelog.txt diff --git a/lib/towerops_web.ex b/lib/towerops_web.ex index a1aaa6c1..8a989a24 100644 --- a/lib/towerops_web.ex +++ b/lib/towerops_web.ex @@ -17,7 +17,7 @@ defmodule ToweropsWeb do those modules here. """ - def static_paths, do: ~w(assets fonts images favicon.ico robots.txt) + def static_paths, do: ~w(assets fonts images favicon.ico robots.txt changelog.txt) def router do quote do diff --git a/lib/towerops_web/components/core_components.ex b/lib/towerops_web/components/core_components.ex index 18b56dd0..d7acde65 100644 --- a/lib/towerops_web/components/core_components.ex +++ b/lib/towerops_web/components/core_components.ex @@ -250,9 +250,11 @@ defmodule ToweropsWeb.CoreComponents do def input(%{type: "checkbox"} = assigns) do assigns = - assign_new(assigns, :checked, fn -> + assigns + |> assign_new(:checked, fn -> Form.normalize_value("checkbox", assigns[:value]) end) + |> assign_new(:error_id, fn -> assigns.id && "#{assigns.id}-error" end) ~H"""
@@ -270,6 +272,8 @@ defmodule ToweropsWeb.CoreComponents do name={@name} value="true" checked={@checked} + aria-describedby={@errors != [] && @error_id} + aria-invalid={to_string(@errors != [])} class={ @class || "h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-800" @@ -278,12 +282,16 @@ defmodule ToweropsWeb.CoreComponents do /> {@label} - <.error :for={msg <- @errors}>{msg} + <.error :if={@errors != []} id={@error_id}> + {msg} +
""" end def input(%{type: "select"} = assigns) do + assigns = assign_new(assigns, :error_id, fn -> assigns.id && "#{assigns.id}-error" end) + ~H"""
- <.error :for={msg <- @errors}>{msg} + <.error :if={@errors != []} id={@error_id}> + {msg} +
""" end # All other inputs text, datetime-local, url, password, etc. are handled here... def input(assigns) do + assigns = assign_new(assigns, :error_id, fn -> assigns.id && "#{assigns.id}-error" end) + ~H"""
- <.error :for={msg <- @errors}>{msg} + <.error :if={@errors != []} id={@error_id}> + {msg} +
""" end diff --git a/lib/towerops_web/components/layouts.ex b/lib/towerops_web/components/layouts.ex index 35d47f77..c3826c81 100644 --- a/lib/towerops_web/components/layouts.ex +++ b/lib/towerops_web/components/layouts.ex @@ -142,15 +142,19 @@ defmodule ToweropsWeb.Layouts do :if={@current_organization} type="button" id="mobile-menu-button" + aria-expanded="false" + aria-controls="mobile-menu" phx-click={ JS.toggle(to: "#mobile-menu") |> JS.toggle(to: "#mobile-menu-icon-open") |> JS.toggle(to: "#mobile-menu-icon-close") + |> JS.toggle_attribute({"aria-expanded", "true", "false"}, + to: "#mobile-menu-button" + ) } class="inline-flex items-center justify-center rounded-md p-2 text-gray-500 hover:bg-gray-100 hover:text-gray-700 focus:outline-none dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-200 md:hidden" - aria-expanded="false" > - Open main menu + Toggle main menu <.icon name="hero-bars-3" class="size-6" />