diff --git a/lib/mv_web/components/core_components.ex b/lib/mv_web/components/core_components.ex index a1020ef..ccec5a5 100644 --- a/lib/mv_web/components/core_components.ex +++ b/lib/mv_web/components/core_components.ex @@ -333,7 +333,8 @@ defmodule MvWeb.CoreComponents do attr :error_class, :string, default: nil, doc: "the input error class to use over defaults" 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) 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]) 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"""
diff --git a/lib/mv_web/live/member_live/form.ex b/lib/mv_web/live/member_live/form.ex index 3378504..dc32824 100644 --- a/lib/mv_web/live/member_live/form.ex +++ b/lib/mv_web/live/member_live/form.ex @@ -144,7 +144,8 @@ defmodule MvWeb.MemberLive.Form do field={value_form[:value]} label={cf.name} 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} />