feat: Add WCAG-compliant handling for boolean custom fields
This commit is contained in:
parent
e3ff3e610c
commit
4e101ea36e
2 changed files with 24 additions and 4 deletions
|
|
@ -333,7 +333,8 @@ defmodule MvWeb.CoreComponents do
|
||||||
attr :error_class, :string, default: nil, doc: "the input error class to use over defaults"
|
attr :error_class, :string, default: nil, doc: "the input error class to use over defaults"
|
||||||
|
|
||||||
attr :rest, :global,
|
attr :rest, :global,
|
||||||
include: ~w(accept autocomplete capture cols disabled form list max maxlength min minlength
|
include:
|
||||||
|
~w(accept autocomplete aria-required capture cols disabled form list max maxlength min minlength
|
||||||
multiple pattern placeholder readonly required rows size step)
|
multiple pattern placeholder readonly required rows size step)
|
||||||
|
|
||||||
def input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
|
def input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
|
||||||
|
|
@ -353,6 +354,24 @@ defmodule MvWeb.CoreComponents do
|
||||||
Phoenix.HTML.Form.normalize_value("checkbox", assigns[:value])
|
Phoenix.HTML.Form.normalize_value("checkbox", assigns[:value])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
# For checkboxes, we don't use HTML required attribute (means "must be checked")
|
||||||
|
# Instead, we use aria-required for screen readers (WCAG 2.1, Success Criterion 3.3.2)
|
||||||
|
# Extract required from rest and remove it, but keep aria-required if provided
|
||||||
|
rest = assigns.rest || %{}
|
||||||
|
is_required = Map.get(rest, :required, false)
|
||||||
|
aria_required = Map.get(rest, :aria_required, if(is_required, do: "true", else: nil))
|
||||||
|
|
||||||
|
# Remove required from rest (we don't want HTML required on checkbox)
|
||||||
|
rest_without_required = Map.delete(rest, :required)
|
||||||
|
# Ensure aria-required is set if field is required
|
||||||
|
rest_final =
|
||||||
|
if aria_required,
|
||||||
|
do: Map.put(rest_without_required, :aria_required, aria_required),
|
||||||
|
else: rest_without_required
|
||||||
|
|
||||||
|
assigns = assign(assigns, :rest, rest_final)
|
||||||
|
assigns = assign(assigns, :is_required, is_required)
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<fieldset class="mb-2 fieldset">
|
<fieldset class="mb-2 fieldset">
|
||||||
<label>
|
<label>
|
||||||
|
|
@ -367,9 +386,9 @@ defmodule MvWeb.CoreComponents do
|
||||||
class={@class || "checkbox checkbox-sm"}
|
class={@class || "checkbox checkbox-sm"}
|
||||||
{@rest}
|
{@rest}
|
||||||
/>{@label}<span
|
/>{@label}<span
|
||||||
:if={@rest[:required]}
|
:if={@is_required}
|
||||||
class="text-red-700 tooltip tooltip-right"
|
class="text-red-700 tooltip tooltip-right"
|
||||||
data-tip={gettext("This field cannot be empty")}
|
data-tip={gettext("This field is required")}
|
||||||
>*</span>
|
>*</span>
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,8 @@ defmodule MvWeb.MemberLive.Form do
|
||||||
field={value_form[:value]}
|
field={value_form[:value]}
|
||||||
label={cf.name}
|
label={cf.name}
|
||||||
type={custom_field_input_type(cf.value_type)}
|
type={custom_field_input_type(cf.value_type)}
|
||||||
required={cf.required}
|
required={if cf.value_type == :boolean, do: false, else: cf.required}
|
||||||
|
aria-required={if cf.required, do: "true", else: nil}
|
||||||
/>
|
/>
|
||||||
</.inputs_for>
|
</.inputs_for>
|
||||||
<input
|
<input
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue