Improve mobile staff accessibility
This commit is contained in:
parent
9f359da60a
commit
5be7b6186e
|
|
@ -1,6 +1,11 @@
|
|||
import AxeBuilder from "@axe-core/playwright";
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { newIsolatedContext, projectEmail, registerAndConfirm } from "./helpers";
|
||||
import {
|
||||
loginWithMagicLink,
|
||||
newIsolatedContext,
|
||||
projectEmail,
|
||||
registerAndConfirm,
|
||||
} from "./helpers";
|
||||
|
||||
const publicAccessibilityPaths = [
|
||||
"/",
|
||||
|
|
@ -154,3 +159,34 @@ test("authenticated core workflows remain accessible on a phone viewport", async
|
|||
|
||||
await user.context.close();
|
||||
});
|
||||
|
||||
test("staff workspaces remain accessible without horizontal overflow on a phone viewport", async ({
|
||||
browser,
|
||||
request,
|
||||
}) => {
|
||||
const admin = await loginWithMagicLink(browser, request, "e2e-admin@example.invalid");
|
||||
await admin.page.setViewportSize({ width: 390, height: 844 });
|
||||
|
||||
for (const path of [
|
||||
"/admin",
|
||||
"/admin/users",
|
||||
"/support/operations",
|
||||
"/moderation",
|
||||
"/analytics",
|
||||
"/admin/audit",
|
||||
]) {
|
||||
await admin.page.goto(path);
|
||||
await expectAccessible(admin.page);
|
||||
|
||||
const dimensions = await admin.page.evaluate(() => ({
|
||||
clientWidth: document.documentElement.clientWidth,
|
||||
scrollWidth: document.documentElement.scrollWidth,
|
||||
}));
|
||||
|
||||
expect(dimensions.scrollWidth, `${path} overflowed at 390px`).toBeLessThanOrEqual(
|
||||
dimensions.clientWidth,
|
||||
);
|
||||
}
|
||||
|
||||
await admin.context.close();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ defmodule WhoNeedHelpWeb.AdminAuditLive do
|
|||
<div class="flex flex-wrap items-center justify-between gap-3 border-b border-base-300 p-4">
|
||||
<div>
|
||||
<h2 class="font-black">{gettext("Recorded events")}</h2>
|
||||
<p class="text-sm text-base-content/55">
|
||||
<p class="text-sm text-base-content/70">
|
||||
{gettext(
|
||||
"Actor, action, and target remain visible; technical metadata opens on demand."
|
||||
)}
|
||||
|
|
@ -209,14 +209,14 @@ defmodule WhoNeedHelpWeb.AdminAuditLive do
|
|||
<time class="text-xs text-base-content/60">{format_datetime(event.inserted_at)}</time>
|
||||
<div class="min-w-0">
|
||||
<p class="truncate font-semibold">{actor_label(event)}</p>
|
||||
<p :if={event.actor_id} class="truncate font-mono text-[0.7rem] text-base-content/45">
|
||||
<p :if={event.actor_id} class="truncate font-mono text-[0.7rem] text-base-content/70">
|
||||
{event.actor_id}
|
||||
</p>
|
||||
</div>
|
||||
<code class="break-all text-xs font-bold text-primary">{event.action}</code>
|
||||
<div class="min-w-0">
|
||||
<p class="truncate text-sm font-semibold">{event.target_type}</p>
|
||||
<p class="truncate font-mono text-[0.7rem] text-base-content/45">{event.target_id}</p>
|
||||
<p class="truncate font-mono text-[0.7rem] text-base-content/70">{event.target_id}</p>
|
||||
</div>
|
||||
<span class="flex items-center gap-2 text-sm font-semibold text-base-content/65">
|
||||
{gettext("Details")}
|
||||
|
|
@ -246,6 +246,7 @@ defmodule WhoNeedHelpWeb.AdminAuditLive do
|
|||
<button
|
||||
type="button"
|
||||
phx-click="previous-page"
|
||||
aria-label={gettext("Previous")}
|
||||
disabled={@cursor_history == []}
|
||||
class="btn btn-sm btn-outline"
|
||||
>
|
||||
|
|
@ -256,6 +257,7 @@ defmodule WhoNeedHelpWeb.AdminAuditLive do
|
|||
<button
|
||||
type="button"
|
||||
phx-click="next-page"
|
||||
aria-label={gettext("Next")}
|
||||
disabled={is_nil(@next_cursor)}
|
||||
class="btn btn-sm btn-outline"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ defmodule WhoNeedHelpWeb.AdminUserLive do
|
|||
</span>
|
||||
</div>
|
||||
<p class="mt-1 break-all text-sm text-base-content/60">{@user.email}</p>
|
||||
<p class="mt-2 font-mono text-xs text-base-content/45">{@user.id}</p>
|
||||
<p class="mt-2 font-mono text-xs text-base-content/70">{@user.id}</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-1 sm:max-w-sm sm:justify-end">
|
||||
<span :if={Accounts.loaded_staff_roles(@user) == []} class="badge badge-ghost badge-sm">
|
||||
|
|
@ -241,7 +241,7 @@ defmodule WhoNeedHelpWeb.AdminUserLive do
|
|||
/>
|
||||
<span class="min-w-0">
|
||||
<span class="block font-bold">{role_label(role)}</span>
|
||||
<span class="block text-xs leading-5 text-base-content/55">
|
||||
<span class="block text-xs leading-5 text-base-content/70">
|
||||
{role_description(role)}
|
||||
</span>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ defmodule WhoNeedHelpWeb.AdminUsersLive do
|
|||
<p class="max-w-80 truncate font-bold" title={account_name(user)}>
|
||||
{account_name(user)}
|
||||
</p>
|
||||
<p class="max-w-80 truncate text-xs text-base-content/55" title={user.email}>
|
||||
<p class="max-w-80 truncate text-xs text-base-content/70" title={user.email}>
|
||||
{user.email}
|
||||
</p>
|
||||
</td>
|
||||
|
|
@ -293,7 +293,7 @@ defmodule WhoNeedHelpWeb.AdminUsersLive do
|
|||
<div class="flex items-start justify-between gap-3">
|
||||
<div class="min-w-0">
|
||||
<p class="truncate font-bold">{account_name(user)}</p>
|
||||
<p class="truncate text-sm text-base-content/55">{user.email}</p>
|
||||
<p class="truncate text-sm text-base-content/70">{user.email}</p>
|
||||
</div>
|
||||
<span class={["badge badge-sm shrink-0", status_class(user.moderation_status)]}>
|
||||
{status_label(user.moderation_status)}
|
||||
|
|
@ -311,7 +311,7 @@ defmodule WhoNeedHelpWeb.AdminUsersLive do
|
|||
</span>
|
||||
</div>
|
||||
<div class="mt-3 flex items-center justify-between gap-3">
|
||||
<span class="text-xs text-base-content/55">
|
||||
<span class="text-xs text-base-content/70">
|
||||
{gettext("Joined %{date}", date: joined_on(user.inserted_at))}
|
||||
</span>
|
||||
<.link navigate={~p"/admin/users/#{user.id}"} class="btn btn-outline btn-sm">
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ defmodule WhoNeedHelpWeb.CategoryProposalLive do
|
|||
else: gettext("Main category")}
|
||||
</span>
|
||||
<p class="mt-2 text-sm text-base-content/65">{proposal.reason}</p>
|
||||
<p class="mt-3 text-xs text-base-content/45">
|
||||
<p class="mt-3 text-xs text-base-content/70">
|
||||
{gettext("by %{name}", name: proposal.proposer.display_name)}
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -671,7 +671,7 @@ defmodule WhoNeedHelpWeb.ModerationLive do
|
|||
<summary class="grid cursor-pointer list-none gap-3 p-4 marker:hidden md:grid-cols-[minmax(0,1fr)_10rem_9rem_9rem_auto] md:items-center">
|
||||
<div class="min-w-0">
|
||||
<p class="truncate font-bold">{report.details}</p>
|
||||
<p class="mt-1 truncate text-xs text-base-content/55">
|
||||
<p class="mt-1 truncate text-xs text-base-content/70">
|
||||
{report.reporter.display_name || report.reporter.email}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -847,7 +847,7 @@ defmodule WhoNeedHelpWeb.ModerationLive do
|
|||
>
|
||||
<summary class="grid cursor-pointer list-none gap-3 p-4 marker:hidden md:grid-cols-[minmax(0,1fr)_14rem_9rem_10rem_auto] md:items-center">
|
||||
<div class="min-w-0">
|
||||
<p class="truncate font-bold">{signal.subject.display_name || signal.subject.email}</p><p class="mt-1 truncate text-xs text-base-content/55">
|
||||
<p class="truncate font-bold">{signal.subject.display_name || signal.subject.email}</p><p class="mt-1 truncate text-xs text-base-content/70">
|
||||
{signal.subject.email}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -968,7 +968,7 @@ defmodule WhoNeedHelpWeb.ModerationLive do
|
|||
>
|
||||
<summary class="grid cursor-pointer list-none gap-3 p-4 marker:hidden md:grid-cols-[minmax(0,1fr)_9rem_9rem_9rem_auto] md:items-center">
|
||||
<div class="min-w-0">
|
||||
<p class="truncate font-bold">{proposal.proposed_name}</p><p class="mt-1 truncate text-xs text-base-content/55">
|
||||
<p class="truncate font-bold">{proposal.proposed_name}</p><p class="mt-1 truncate text-xs text-base-content/70">
|
||||
{proposal.reason}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -1119,6 +1119,7 @@ defmodule WhoNeedHelpWeb.ModerationLive do
|
|||
<button
|
||||
type="button"
|
||||
phx-click="previous-page"
|
||||
aria-label={gettext("Previous")}
|
||||
disabled={@previous_disabled}
|
||||
class="btn btn-sm btn-outline"
|
||||
>
|
||||
|
|
@ -1127,13 +1128,14 @@ defmodule WhoNeedHelpWeb.ModerationLive do
|
|||
</button>
|
||||
<div class="text-center text-sm">
|
||||
<p class="font-bold">{gettext("Page %{page}", page: @page_number)}</p>
|
||||
<p :if={@entries != []} class="text-xs text-base-content/55">
|
||||
<p :if={@entries != []} class="text-xs text-base-content/70">
|
||||
{gettext("Showing %{first}–%{last}", first: elem(@range, 0), last: elem(@range, 1))}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
phx-click="next-page"
|
||||
aria-label={gettext("Next")}
|
||||
disabled={@next_disabled}
|
||||
class="btn btn-sm btn-outline"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ defmodule WhoNeedHelpWeb.NotificationLive do
|
|||
</div>
|
||||
|
||||
<div :if={@notifications == []} class="mt-5 rounded-2xl bg-base-200 p-6 text-center">
|
||||
<.icon name="hero-bell-slash" class="mx-auto size-8 text-base-content/45" />
|
||||
<.icon name="hero-bell-slash" class="mx-auto size-8 text-base-content/70" />
|
||||
<p class="mt-3 font-bold">{gettext("No notifications yet")}</p>
|
||||
<p class="mt-1 text-sm text-base-content/70">
|
||||
{gettext("Request, message, and nearby-alert updates will appear here.")}
|
||||
|
|
@ -306,7 +306,7 @@ defmodule WhoNeedHelpWeb.NotificationLive do
|
|||
value={notification.inserted_at}
|
||||
date_style="short"
|
||||
time_style="short"
|
||||
class="mt-2 block text-xs font-normal text-base-content/45"
|
||||
class="mt-2 block text-xs font-normal text-base-content/70"
|
||||
/>
|
||||
</span>
|
||||
<.icon name="hero-chevron-right" class="mt-2 size-4 shrink-0 opacity-45" />
|
||||
|
|
@ -401,7 +401,7 @@ defmodule WhoNeedHelpWeb.NotificationLive do
|
|||
value={device.last_seen_at}
|
||||
date_style="short"
|
||||
time_style="short"
|
||||
class="text-xs text-base-content/55"
|
||||
class="text-xs text-base-content/70"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ defmodule WhoNeedHelpWeb.ProductAnalyticsLive do
|
|||
<div class="flex flex-wrap items-center justify-between gap-3 border-b border-base-300 p-4">
|
||||
<div>
|
||||
<h2 class="font-black">{gettext("Daily counters")}</h2>
|
||||
<p class="text-sm text-base-content/55">
|
||||
<p class="text-sm text-base-content/70">
|
||||
{gettext("One row per date, metric, and non-identifying dimension.")}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -248,7 +248,7 @@ defmodule WhoNeedHelpWeb.ProductAnalyticsLive do
|
|||
<article :for={metric <- @metrics} class="grid grid-cols-[1fr_auto] gap-3 p-4">
|
||||
<div class="min-w-0">
|
||||
<p class="truncate font-bold capitalize">{metric_label(metric.metric)}</p>
|
||||
<p class="mt-1 text-sm text-base-content/55">{metric.date} · {metric.dimension}</p>
|
||||
<p class="mt-1 text-sm text-base-content/70">{metric.date} · {metric.dimension}</p>
|
||||
</div>
|
||||
<strong class="text-lg">{compact_number(metric.count)}</strong>
|
||||
</article>
|
||||
|
|
@ -282,6 +282,7 @@ defmodule WhoNeedHelpWeb.ProductAnalyticsLive do
|
|||
<button
|
||||
type="button"
|
||||
phx-click="previous-page"
|
||||
aria-label={gettext("Previous")}
|
||||
disabled={@cursor_history == []}
|
||||
class="btn btn-sm btn-outline"
|
||||
>
|
||||
|
|
@ -292,6 +293,7 @@ defmodule WhoNeedHelpWeb.ProductAnalyticsLive do
|
|||
<button
|
||||
type="button"
|
||||
phx-click="next-page"
|
||||
aria-label={gettext("Next")}
|
||||
disabled={is_nil(@next_cursor)}
|
||||
class="btn btn-sm btn-outline"
|
||||
>
|
||||
|
|
@ -314,7 +316,7 @@ defmodule WhoNeedHelpWeb.ProductAnalyticsLive do
|
|||
<.icon name={@icon} class="size-5" />
|
||||
</span>
|
||||
<div class="min-w-0">
|
||||
<p class="truncate text-sm text-base-content/55">{@label}</p>
|
||||
<p class="truncate text-sm text-base-content/70">{@label}</p>
|
||||
<p class="text-2xl font-black">{compact_number(@value)}</p>
|
||||
</div>
|
||||
</article>
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ defmodule WhoNeedHelpWeb.ReportLive do
|
|||
value={report.inserted_at}
|
||||
date_style="short"
|
||||
time_style="short"
|
||||
class="mt-4 block text-xs text-base-content/55"
|
||||
class="mt-4 block text-xs text-base-content/70"
|
||||
/>
|
||||
</article>
|
||||
|
||||
|
|
|
|||
|
|
@ -247,14 +247,14 @@ defmodule WhoNeedHelpWeb.SupportOperationLive do
|
|||
<div class="flex flex-wrap items-center justify-between gap-2">
|
||||
<strong>{if message.sender_role == :staff,
|
||||
do: gettext("Support team"),
|
||||
else: gettext("Requester")}</strong><time class="text-xs text-base-content/55">{format_datetime(
|
||||
else: gettext("Requester")}</strong><time class="text-xs text-base-content/70">{format_datetime(
|
||||
message.inserted_at
|
||||
)}</time>
|
||||
</div><p class="mt-1 whitespace-pre-wrap">{message.body}</p>
|
||||
</article>
|
||||
<p
|
||||
:if={@record.conversation_messages == []}
|
||||
class="rounded-xl bg-base-200 p-4 text-sm text-base-content/55"
|
||||
class="rounded-xl bg-base-200 p-4 text-sm text-base-content/70"
|
||||
>
|
||||
{gettext("No conversation messages yet.")}
|
||||
</p>
|
||||
|
|
@ -327,7 +327,7 @@ defmodule WhoNeedHelpWeb.SupportOperationLive do
|
|||
placeholder={gettext("Write the decision, next step, or information you need…")}
|
||||
/>
|
||||
</div>
|
||||
<p class="mt-2 text-xs text-base-content/55">
|
||||
<p class="mt-2 text-xs text-base-content/70">
|
||||
{if @record.contact_verified_at,
|
||||
do: gettext("The verified contact will receive a new reply by email."),
|
||||
else: gettext("Email is disabled until contact is verified.")}
|
||||
|
|
@ -431,7 +431,7 @@ defmodule WhoNeedHelpWeb.SupportOperationLive do
|
|||
/>
|
||||
</div>
|
||||
<div class="mt-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||
<p class="text-xs text-base-content/55">
|
||||
<p class="text-xs text-base-content/70">
|
||||
{if @record.contact_verified_at,
|
||||
do: gettext("The verified contact will receive this update by email."),
|
||||
else: gettext("Email is disabled until contact is verified.")}
|
||||
|
|
|
|||
|
|
@ -564,7 +564,7 @@ defmodule WhoNeedHelpWeb.SupportOperationsLive do
|
|||
>
|
||||
{request.subject}
|
||||
</p><p
|
||||
class="max-w-96 truncate text-xs text-base-content/55"
|
||||
class="max-w-96 truncate text-xs text-base-content/70"
|
||||
title={request.contact_email}
|
||||
>
|
||||
{request.contact_email}
|
||||
|
|
@ -609,7 +609,7 @@ defmodule WhoNeedHelpWeb.SupportOperationsLive do
|
|||
)}</span>
|
||||
</div>
|
||||
<div class="mt-3 flex items-center justify-between gap-3">
|
||||
<span class="text-xs text-base-content/55">{format_datetime(request.inserted_at)}</span><.link
|
||||
<span class="text-xs text-base-content/70">{format_datetime(request.inserted_at)}</span><.link
|
||||
navigate={~p"/support/operations/support/#{request.id}"}
|
||||
class="btn btn-outline btn-sm"
|
||||
>{gettext("Open")}</.link>
|
||||
|
|
@ -645,7 +645,7 @@ defmodule WhoNeedHelpWeb.SupportOperationsLive do
|
|||
>
|
||||
{removal_category(notice.category)}
|
||||
</p><p
|
||||
class="max-w-96 truncate text-xs text-base-content/55"
|
||||
class="max-w-96 truncate text-xs text-base-content/70"
|
||||
title={notice.contact_email}
|
||||
>
|
||||
{notice.contact_email || gettext("No contact email")}
|
||||
|
|
@ -690,7 +690,7 @@ defmodule WhoNeedHelpWeb.SupportOperationsLive do
|
|||
)}</span>
|
||||
</div>
|
||||
<div class="mt-3 flex items-center justify-between gap-3">
|
||||
<span class="text-xs text-base-content/55">{format_datetime(notice.inserted_at)}</span><.link
|
||||
<span class="text-xs text-base-content/70">{format_datetime(notice.inserted_at)}</span><.link
|
||||
navigate={~p"/support/operations/legal/#{notice.id}"}
|
||||
class="btn btn-outline btn-sm"
|
||||
>{gettext("Open")}</.link>
|
||||
|
|
|
|||
|
|
@ -7114,10 +7114,13 @@ msgstr ""
|
|||
msgid "Name, reason, or reference"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/admin_audit_live.ex:262
|
||||
#: lib/who_need_help_web/live/admin_audit_live.ex:260
|
||||
#: lib/who_need_help_web/live/admin_audit_live.ex:264
|
||||
#: lib/who_need_help_web/live/admin_users_live.ex:345
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:1140
|
||||
#: lib/who_need_help_web/live/product_analytics_live.ex:298
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:1138
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:1142
|
||||
#: lib/who_need_help_web/live/product_analytics_live.ex:296
|
||||
#: lib/who_need_help_web/live/product_analytics_live.ex:300
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:513
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Next"
|
||||
|
|
@ -7225,21 +7228,24 @@ msgstr ""
|
|||
msgid "Overview"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/admin_audit_live.ex:255
|
||||
#: lib/who_need_help_web/live/admin_audit_live.ex:256
|
||||
#: lib/who_need_help_web/live/admin_users_live.ex:227
|
||||
#: lib/who_need_help_web/live/admin_users_live.ex:338
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:1129
|
||||
#: lib/who_need_help_web/live/product_analytics_live.ex:291
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:1130
|
||||
#: lib/who_need_help_web/live/product_analytics_live.ex:292
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:506
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:537
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Page %{page}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/admin_audit_live.ex:253
|
||||
#: lib/who_need_help_web/live/admin_audit_live.ex:249
|
||||
#: lib/who_need_help_web/live/admin_audit_live.ex:254
|
||||
#: lib/who_need_help_web/live/admin_users_live.ex:336
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:1126
|
||||
#: lib/who_need_help_web/live/product_analytics_live.ex:289
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:1122
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:1127
|
||||
#: lib/who_need_help_web/live/product_analytics_live.ex:285
|
||||
#: lib/who_need_help_web/live/product_analytics_live.ex:290
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:504
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Previous"
|
||||
|
|
@ -7451,7 +7457,7 @@ msgid "Search users"
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/admin_users_live.ex:218
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:1131
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:1132
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:531
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Showing %{first}–%{last}"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user