accessibility and poller updates
This commit is contained in:
parent
902d21eeee
commit
06fde717c0
5 changed files with 86 additions and 13 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"""
|
||||
<div class="mb-4">
|
||||
|
|
@ -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
|
|||
/>
|
||||
<span class="text-sm font-medium text-gray-900 dark:text-white">{@label}</span>
|
||||
</label>
|
||||
<.error :for={msg <- @errors}>{msg}</.error>
|
||||
<.error :if={@errors != []} id={@error_id}>
|
||||
<span :for={msg <- @errors}>{msg}</span>
|
||||
</.error>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
def input(%{type: "select"} = assigns) do
|
||||
assigns = assign_new(assigns, :error_id, fn -> assigns.id && "#{assigns.id}-error" end)
|
||||
|
||||
~H"""
|
||||
<div class="mb-4">
|
||||
<label :if={@label} for={@id} class="block text-sm/6 font-medium text-gray-900 dark:text-white">
|
||||
|
|
@ -293,6 +301,8 @@ defmodule ToweropsWeb.CoreComponents do
|
|||
<select
|
||||
id={@id}
|
||||
name={@name}
|
||||
aria-describedby={@errors != [] && @error_id}
|
||||
aria-invalid={to_string(@errors != [])}
|
||||
class={[
|
||||
@class ||
|
||||
"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white py-1.5 pr-8 pl-3 text-base text-gray-900 outline-1 -outline-offset-1 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 sm:text-sm/6 dark:bg-white/5 dark:text-white dark:outline-white/10 dark:*:bg-gray-800",
|
||||
|
|
@ -322,12 +332,16 @@ defmodule ToweropsWeb.CoreComponents do
|
|||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<.error :for={msg <- @errors}>{msg}</.error>
|
||||
<.error :if={@errors != []} id={@error_id}>
|
||||
<span :for={msg <- @errors}>{msg}</span>
|
||||
</.error>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
def input(%{type: "textarea"} = assigns) do
|
||||
assigns = assign_new(assigns, :error_id, fn -> assigns.id && "#{assigns.id}-error" end)
|
||||
|
||||
~H"""
|
||||
<div class="mb-4">
|
||||
<label>
|
||||
|
|
@ -337,6 +351,8 @@ defmodule ToweropsWeb.CoreComponents do
|
|||
<textarea
|
||||
id={@id}
|
||||
name={@name}
|
||||
aria-describedby={@errors != [] && @error_id}
|
||||
aria-invalid={to_string(@errors != [])}
|
||||
class={[
|
||||
@class ||
|
||||
"block w-full rounded-lg border-0 py-2 px-3 text-gray-900 shadow-sm ring-1 ring-inset focus:ring-2 focus:ring-inset sm:text-sm sm:leading-6 dark:bg-gray-800 dark:text-white",
|
||||
|
|
@ -349,13 +365,17 @@ defmodule ToweropsWeb.CoreComponents do
|
|||
{@rest}
|
||||
>{Phoenix.HTML.Form.normalize_value("textarea", @value)}</textarea>
|
||||
</label>
|
||||
<.error :for={msg <- @errors}>{msg}</.error>
|
||||
<.error :if={@errors != []} id={@error_id}>
|
||||
<span :for={msg <- @errors}>{msg}</span>
|
||||
</.error>
|
||||
</div>
|
||||
"""
|
||||
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"""
|
||||
<div class="mb-4">
|
||||
<label>
|
||||
|
|
@ -367,6 +387,8 @@ defmodule ToweropsWeb.CoreComponents do
|
|||
name={@name}
|
||||
id={@id}
|
||||
value={Phoenix.HTML.Form.normalize_value(@type, @value)}
|
||||
aria-describedby={@errors != [] && @error_id}
|
||||
aria-invalid={to_string(@errors != [])}
|
||||
class={[
|
||||
@class ||
|
||||
"block w-full rounded-lg border-0 py-2 px-3 text-gray-900 shadow-sm ring-1 ring-inset focus:ring-2 focus:ring-inset sm:text-sm sm:leading-6 dark:bg-gray-800 dark:text-white",
|
||||
|
|
@ -379,7 +401,9 @@ defmodule ToweropsWeb.CoreComponents do
|
|||
{@rest}
|
||||
/>
|
||||
</label>
|
||||
<.error :for={msg <- @errors}>{msg}</.error>
|
||||
<.error :if={@errors != []} id={@error_id}>
|
||||
<span :for={msg <- @errors}>{msg}</span>
|
||||
</.error>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<span class="sr-only">Open main menu</span>
|
||||
<span class="sr-only">Toggle main menu</span>
|
||||
<span id="mobile-menu-icon-open"><.icon name="hero-bars-3" class="size-6" /></span>
|
||||
<span id="mobile-menu-icon-close" class="hidden">
|
||||
<.icon name="hero-x-mark" class="size-6" />
|
||||
|
|
@ -215,7 +219,13 @@ defmodule ToweropsWeb.Layouts do
|
|||
<button
|
||||
type="button"
|
||||
id="org-menu-button"
|
||||
phx-click={JS.toggle(to: "#org-menu")}
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-controls="org-menu"
|
||||
phx-click={
|
||||
JS.toggle(to: "#org-menu")
|
||||
|> JS.toggle_attribute({"aria-expanded", "true", "false"}, to: "#org-menu-button")
|
||||
}
|
||||
class="inline-flex items-center justify-center gap-x-1 rounded-md bg-white px-2 py-1.5 sm:px-3 sm:py-2 text-xs sm:text-sm font-semibold text-gray-900 shadow-xs inset-ring-1 inset-ring-gray-300 hover:bg-gray-50 dark:bg-white/10 dark:text-white dark:shadow-none dark:inset-ring-white/5 dark:hover:bg-white/20"
|
||||
>
|
||||
<span class="hidden sm:inline">
|
||||
|
|
@ -243,12 +253,17 @@ defmodule ToweropsWeb.Layouts do
|
|||
|
||||
<div
|
||||
id="org-menu"
|
||||
role="menu"
|
||||
class="hidden absolute top-full right-0 mt-2 w-56 origin-top-right rounded-md bg-white shadow-lg outline-1 outline-black/5 z-50 dark:bg-gray-800 dark:shadow-none dark:-outline-offset-1 dark:outline-white/10"
|
||||
phx-click-away={JS.hide(to: "#org-menu")}
|
||||
phx-click-away={
|
||||
JS.hide(to: "#org-menu")
|
||||
|> JS.set_attribute({"aria-expanded", "false"}, to: "#org-menu-button")
|
||||
}
|
||||
>
|
||||
<div class="py-1">
|
||||
<.link
|
||||
:if={@current_organization}
|
||||
role="menuitem"
|
||||
navigate={~p"/orgs"}
|
||||
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-hidden dark:text-gray-300 dark:hover:bg-white/5 dark:hover:text-white"
|
||||
phx-click={JS.hide(to: "#org-menu")}
|
||||
|
|
@ -257,6 +272,7 @@ defmodule ToweropsWeb.Layouts do
|
|||
</.link>
|
||||
<.link
|
||||
:if={@current_organization}
|
||||
role="menuitem"
|
||||
navigate={~p"/orgs/#{@current_organization.slug}/settings"}
|
||||
class="flex items-center gap-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-hidden dark:text-gray-300 dark:hover:bg-white/5 dark:hover:text-white"
|
||||
phx-click={JS.hide(to: "#org-menu")}
|
||||
|
|
@ -265,6 +281,7 @@ defmodule ToweropsWeb.Layouts do
|
|||
</.link>
|
||||
<%= if @current_scope && @current_scope.user && @current_scope.user.is_superuser do %>
|
||||
<.link
|
||||
role="menuitem"
|
||||
navigate={~p"/admin"}
|
||||
class="flex items-center gap-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-hidden dark:text-gray-300 dark:hover:bg-white/5 dark:hover:text-white"
|
||||
phx-click={JS.hide(to: "#org-menu")}
|
||||
|
|
@ -273,6 +290,7 @@ defmodule ToweropsWeb.Layouts do
|
|||
</.link>
|
||||
<% end %>
|
||||
<.link
|
||||
role="menuitem"
|
||||
navigate={~p"/users/settings"}
|
||||
class="flex items-center gap-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-hidden dark:text-gray-300 dark:hover:bg-white/5 dark:hover:text-white"
|
||||
phx-click={JS.hide(to: "#org-menu")}
|
||||
|
|
@ -280,6 +298,7 @@ defmodule ToweropsWeb.Layouts do
|
|||
<.icon name="hero-user-circle" class="w-4 h-4" /> User Settings
|
||||
</.link>
|
||||
<.link
|
||||
role="menuitem"
|
||||
href={~p"/users/log-out"}
|
||||
method="delete"
|
||||
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-hidden dark:text-gray-300 dark:hover:bg-white/5 dark:hover:text-white"
|
||||
|
|
@ -329,7 +348,7 @@ defmodule ToweropsWeb.Layouts do
|
|||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="flex-1 py-6 sm:py-10">
|
||||
<main id="main-content" tabindex="-1" class="flex-1 py-6 sm:py-10">
|
||||
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
{render_slot(@inner_block)}
|
||||
</div>
|
||||
|
|
@ -440,7 +459,13 @@ defmodule ToweropsWeb.Layouts do
|
|||
<button
|
||||
type="button"
|
||||
id="theme-menu-button"
|
||||
phx-click={JS.toggle(to: "#theme-menu")}
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-controls="theme-menu"
|
||||
phx-click={
|
||||
JS.toggle(to: "#theme-menu")
|
||||
|> JS.toggle_attribute({"aria-expanded", "true", "false"}, to: "#theme-menu-button")
|
||||
}
|
||||
class="flex items-center justify-center p-2 rounded-md text-gray-500 hover:text-gray-700 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-200 dark:hover:bg-gray-800"
|
||||
aria-label="Toggle theme"
|
||||
>
|
||||
|
|
@ -450,12 +475,17 @@ defmodule ToweropsWeb.Layouts do
|
|||
|
||||
<div
|
||||
id="theme-menu"
|
||||
role="menu"
|
||||
class="hidden absolute top-full right-0 mt-2 w-36 origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black/5 z-50 dark:bg-gray-800 dark:ring-white/10"
|
||||
phx-click-away={JS.hide(to: "#theme-menu")}
|
||||
phx-click-away={
|
||||
JS.hide(to: "#theme-menu")
|
||||
|> JS.set_attribute({"aria-expanded", "false"}, to: "#theme-menu-button")
|
||||
}
|
||||
>
|
||||
<div class="py-1">
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
class="flex w-full items-center gap-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700"
|
||||
phx-click={JS.dispatch("phx:set-theme") |> JS.hide(to: "#theme-menu")}
|
||||
data-phx-theme="system"
|
||||
|
|
@ -464,6 +494,7 @@ defmodule ToweropsWeb.Layouts do
|
|||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
class="flex w-full items-center gap-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700"
|
||||
phx-click={JS.dispatch("phx:set-theme") |> JS.hide(to: "#theme-menu")}
|
||||
data-phx-theme="light"
|
||||
|
|
@ -472,6 +503,7 @@ defmodule ToweropsWeb.Layouts do
|
|||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
class="flex w-full items-center gap-2 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700"
|
||||
phx-click={JS.dispatch("phx:set-theme") |> JS.hide(to: "#theme-menu")}
|
||||
data-phx-theme="dark"
|
||||
|
|
@ -619,6 +651,13 @@ defmodule ToweropsWeb.Layouts do
|
|||
>
|
||||
Privacy Policy
|
||||
</.link>
|
||||
<span class="mx-2">·</span>
|
||||
<.link
|
||||
href="/changelog.txt"
|
||||
class="hover:text-gray-900 dark:hover:text-gray-200 underline decoration-dotted underline-offset-2"
|
||||
>
|
||||
Changelog
|
||||
</.link>
|
||||
</p>
|
||||
<p class="text-xs">
|
||||
Last deploy <span title={@formatted_time}>{@time_ago}</span> · {@formatted_time}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@
|
|||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a
|
||||
href="#main-content"
|
||||
class="sr-only focus:not-sr-only focus:absolute focus:top-0 focus:left-0 focus:z-50 focus:p-4 focus:bg-blue-600 focus:text-white focus:rounded-md focus:m-2"
|
||||
>
|
||||
Skip to main content
|
||||
</a>
|
||||
{@inner_content}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
4
priv/static/changelog.txt
Normal file
4
priv/static/changelog.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
2025-01-26
|
||||
* Cloud poller improvements
|
||||
* Accessability improved
|
||||
|
||||
Loading…
Add table
Reference in a new issue