fix(a11y/password form): describedby rel with input and password rules

This commit is contained in:
Colin Darie 2023-02-15 11:33:42 +01:00
parent 31c99e935a
commit c968aa63d3
5 changed files with 28 additions and 22 deletions

View file

@ -40,17 +40,19 @@ class Dsfr::InputComponent < ApplicationComponent
'fr-mb-0': true,
'fr-input--error': errors_on_attribute?))
if errors_on_attribute? || describedby
@opts = @opts.deep_merge(aria: {
describedby: error_message_id,
if errors_on_attribute? || describedby?
@opts.deep_merge!(aria: {
describedby: describedby_id,
invalid: errors_on_attribute?
})
end
if @required
@opts[:required] = true
end
if email?
@opts = @opts.deep_merge(data: {
@opts.deep_merge!(data: {
action: "blur->email-input#checkEmail",
'email-input-target': 'input'
})
@ -63,14 +65,14 @@ class Dsfr::InputComponent < ApplicationComponent
errors.has_key?(attribute_or_rich_body)
end
def error_message_id
dom_id(object, @attribute)
end
def error_messages
errors.full_messages_for(attribute_or_rich_body)
end
def describedby_id
dom_id(object, "#{@attribute}-messages")
end
# i18n lookups
def label
object.class.human_attribute_name(@attribute)

View file

@ -7,13 +7,13 @@
- if hint?
%span.fr-hint-text= hint
= @form.send(@input_type, @attribute, input_opts)
= @form.public_send(@input_type, @attribute, input_opts)
- if errors_on_attribute?
- if error_messages.size == 1
%p.fr-error-text{ id: error_message_id }= error_messages.first
%p.fr-error-text{ id: describedby_id }= error_messages.first
- else
.fr-error-text{ id: error_message_id }
.fr-error-text{ id: describedby_id }
%ul.list-style-type-none.fr-pl-0
- error_messages.map do |error_message|
%li= error_message

View file

@ -0,0 +1,3 @@
.fr-messages-group{ "aria-live" => "off", id: id }
%p.fr-message= t('views.registrations.new.password_message')
%p.fr-message.fr-message--info= t('views.registrations.new.password_placeholder', min_length: PASSWORD_MIN_LENGTH)

View file

@ -18,11 +18,14 @@
.fr-fieldset__element
= render Dsfr::InputComponent.new(form: f, attribute: :password, input_type: :password_field,
opts: { autofocus: 'true', autocomplete: 'new-password', data: { controller: populated_resource.validate_password_complexity? ? 'turbo-input' : false, turbo_input_url_value: show_password_complexity_path }})
opts: { autofocus: 'true', autocomplete: 'new-password', minlength: PASSWORD_MIN_LENGTH, data: { controller: populated_resource.validate_password_complexity? ? 'turbo-input' : false, turbo_input_url_value: show_password_complexity_path }}) do |c|
- c.describedby do
- if populated_resource.validate_password_complexity?
%div{ id: c.describedby_id }
#password_complexity
= render PasswordComplexityComponent.new
- else
= render partial: "devise/password_rules", locals: { id: c.describedby_id }
.fr-fieldset__element
= render Dsfr::InputComponent.new(form: f, attribute: :password_confirmation, input_type: :password_field, opts: { autocomplete: 'new-password' })

View file

@ -18,10 +18,8 @@
.fr-fieldset__element= render Dsfr::InputComponent.new(form: f, attribute: :email, input_type: :email_field, opts: { autocomplete: 'email', autofocus: true })
.fr-fieldset__element
= render Dsfr::InputComponent.new(form: f, attribute: :password, input_type: :password_field, opts: { autocomplete: 'new-password', min_length: PASSWORD_MIN_LENGTH }) do |c|
= render Dsfr::InputComponent.new(form: f, attribute: :password, input_type: :password_field, opts: { autocomplete: 'new-password', minlength: PASSWORD_MIN_LENGTH }) do |c|
- c.describedby do
#password-input-messages.fr-messages-group{ "aria-live" => "off" }
%p#password-input-message.fr-message= t('views.registrations.new.password_message')
%p#password-input-message-info.fr-message.fr-message--info= t('views.registrations.new.password_placeholder', min_length: PASSWORD_MIN_LENGTH)
= render partial: "devise/password_rules", locals: { id: c.describedby_id }
= f.submit t('views.shared.account.create'), class: "fr-btn fr-btn--lg"