Merge pull request #8300 from mfo/a11y/contact-apge
correctif(a11y.contact-page): #8058 (utiliser le type email sur l'input prenant l'email de l'usager), #8056 (ajuster les erreurs de contraste par l'usage des composants du DSFR)
This commit is contained in:
commit
fdb252ed7a
6 changed files with 84 additions and 144 deletions
|
@ -12,7 +12,6 @@
|
|||
|
||||
a {
|
||||
color: #FFFFFF;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
48
app/javascript/controllers/support_controller.ts
Normal file
48
app/javascript/controllers/support_controller.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
import { ApplicationController } from './application_controller';
|
||||
import { hide, show } from '@utils';
|
||||
|
||||
export class SupportController extends ApplicationController {
|
||||
static targets = ['inputRadio', 'content'];
|
||||
|
||||
declare readonly inputRadioTargets: HTMLInputElement[];
|
||||
declare readonly contentTargets: HTMLElement[];
|
||||
|
||||
connect() {
|
||||
this.inputRadioTargets.forEach((inputRadio) => {
|
||||
inputRadio.addEventListener('change', this.onChange.bind(this));
|
||||
inputRadio.addEventListener('keydown', this.onChange.bind(this));
|
||||
});
|
||||
}
|
||||
|
||||
onChange(event: Event) {
|
||||
const target = event.target as HTMLInputElement;
|
||||
const content = this.getContentForTarget(target);
|
||||
|
||||
this.contentTargets.forEach((content) => {
|
||||
hide(content);
|
||||
content.setAttribute('aria-hidden', 'true');
|
||||
});
|
||||
|
||||
if (target.checked && content) {
|
||||
show(content);
|
||||
content.setAttribute('aria-hidden', 'false');
|
||||
}
|
||||
}
|
||||
|
||||
getLabelForTarget(target: HTMLInputElement) {
|
||||
const labelSelector = `label[for="${target.id}"]`;
|
||||
return document.querySelector(labelSelector);
|
||||
}
|
||||
|
||||
getContentForTarget(target: HTMLInputElement) {
|
||||
const label = this.getLabelForTarget(target);
|
||||
if (!label) {
|
||||
return null;
|
||||
}
|
||||
const contentSelector = label.getAttribute('aria-controls');
|
||||
|
||||
if (contentSelector) {
|
||||
return document.getElementById(contentSelector);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@ import { registerControllers } from '../shared/stimulus-loader';
|
|||
import '../new_design/form-validation';
|
||||
import '../new_design/procedure-context';
|
||||
import '../new_design/procedure-form';
|
||||
import '../new_design/support';
|
||||
|
||||
import {
|
||||
toggleCondidentielExplanation,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
/* Verify README of each component to insert them in the expected order. */
|
||||
@import '@gouvfr/dsfr/dist/component/alert/alert.css';
|
||||
@import '@gouvfr/dsfr/dist/component/radio/radio.css';
|
||||
@import '@gouvfr/dsfr/dist/component/badge/badge.css';
|
||||
@import '@gouvfr/dsfr/dist/component/breadcrumb/breadcrumb.css';
|
||||
@import '@gouvfr/dsfr/dist/component/callout/callout.css';
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
//
|
||||
// This content is inspired by w3c aria example, rewritten for better RGAA compatibility.
|
||||
// https://www.w3.org/TR/wai-aria-practices-1.1/examples/disclosure/disclosure-faq.html
|
||||
//
|
||||
|
||||
class ButtonExpand {
|
||||
constructor(domNode) {
|
||||
this.domNode = domNode;
|
||||
|
||||
this.keyCode = Object.freeze({
|
||||
RETURN: 13
|
||||
});
|
||||
|
||||
this.allButtons = [];
|
||||
this.controlledNode = false;
|
||||
|
||||
var id = this.domNode.getAttribute('aria-controls');
|
||||
|
||||
if (id) {
|
||||
this.controlledNode = document.getElementById(id);
|
||||
}
|
||||
|
||||
this.radioInput = this.domNode.querySelector('input[type="radio"]');
|
||||
|
||||
this.hideContent();
|
||||
|
||||
this.domNode.addEventListener('keydown', this.handleKeydown.bind(this));
|
||||
this.domNode.addEventListener('click', this.handleClick.bind(this));
|
||||
}
|
||||
|
||||
showContent() {
|
||||
this.radioInput.checked = true;
|
||||
|
||||
if (this.controlledNode) {
|
||||
this.controlledNode.setAttribute('aria-hidden', 'false');
|
||||
this.controlledNode.classList.remove('hidden');
|
||||
}
|
||||
|
||||
this.allButtons.forEach((b) => {
|
||||
if (b != this) {
|
||||
b.hideContent();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
hideContent() {
|
||||
this.radioInput.checked = false;
|
||||
|
||||
if (this.controlledNode) {
|
||||
this.controlledNode.setAttribute('aria-hidden', 'true');
|
||||
this.controlledNode.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
toggleExpand() {
|
||||
if (
|
||||
this.controlledNode &&
|
||||
this.controlledNode.getAttribute('aria-hidden') === 'true'
|
||||
) {
|
||||
this.showContent();
|
||||
} else {
|
||||
this.hideContent();
|
||||
}
|
||||
}
|
||||
|
||||
setAllButtons(buttons) {
|
||||
this.allButtons = buttons;
|
||||
}
|
||||
|
||||
handleKeydown(event) {
|
||||
switch (event.keyCode) {
|
||||
case this.keyCode.RETURN:
|
||||
this.showContent();
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
// NOTE: click event is also fired on input and label activations
|
||||
// ie., not necessarily by a mouse click but any user inputs, like keyboard navigation with arrows keys.
|
||||
// Cf https://www.w3.org/TR/2012/WD-html5-20121025/content-models.html#interactive-content
|
||||
|
||||
this.showContent();
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize Hide/Show Buttons */
|
||||
|
||||
if (document.querySelector('#contact-form')) {
|
||||
window.addEventListener(
|
||||
'DOMContentLoaded',
|
||||
function () {
|
||||
var buttons = document.querySelectorAll('fieldset[name=type] label');
|
||||
var expandButtons = [];
|
||||
|
||||
buttons.forEach((button) => {
|
||||
var be = new ButtonExpand(button);
|
||||
expandButtons.push(be);
|
||||
});
|
||||
expandButtons.forEach((button) => button.setAllButtons(expandButtons));
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
%h1.new-h1
|
||||
= t('.contact')
|
||||
|
||||
= form_tag contact_path, method: :post, multipart: true, class: 'form' do
|
||||
= form_tag contact_path, method: :post, multipart: true, class: 'fr-form-group', data: {controller: :support } do
|
||||
|
||||
.description
|
||||
%h2= t('.intro_html')
|
||||
|
@ -15,59 +15,62 @@
|
|||
%p.mandatory-explanation= t('asterisk_html', scope: [:utils])
|
||||
|
||||
- if !user_signed_in?
|
||||
.contact-champ
|
||||
= label_tag :email do
|
||||
.fr-input-group
|
||||
= label_tag :email, class: 'fr-label' do
|
||||
Email
|
||||
%span.mandatory *
|
||||
= text_field_tag :email, params[:email], required: true, autocomplete: 'email'
|
||||
= email_field_tag :email, params[:email], required: true, autocomplete: 'email', class: 'fr-input'
|
||||
|
||||
%fieldset.radios.vertical{ name: "type" }
|
||||
%legend.form-label
|
||||
%fieldset.fr-fieldset{ name: "type" }
|
||||
%legend.fr-fieldset__legend
|
||||
= t('.your_question')
|
||||
%span.mandatory *
|
||||
.fr-fieldset__content
|
||||
- @options.each do |(question, question_type, link)|
|
||||
.fr-radio-group
|
||||
= radio_button_tag :type, question_type, false, required: true, data: {"support-target": "inputRadio" }
|
||||
= label_tag "type_#{question_type}", { 'aria-controls': link ? "card-#{question_type}" : nil, class: 'fr-label' } do
|
||||
= question
|
||||
|
||||
- @options.each do |(question, question_type, link)|
|
||||
= label_tag "type_#{question_type}", { 'aria-controls': link ? "card-#{question_type}" : nil } do
|
||||
= radio_button_tag :type, question_type, false, required: true
|
||||
= question
|
||||
|
||||
- if link.present?
|
||||
.support.card.featured.mb-4.ml-5.hidden{ id: "card-#{question_type}", "aria-hidden": true }
|
||||
.card-title
|
||||
= t('.our_answer')
|
||||
.card-content
|
||||
-# i18n-tasks-use t("support.index.#{question_type}.answer_html")
|
||||
= t('answer_html', scope: [:support, :index, question_type], base_url: APPLICATION_BASE_URL, "link_#{question_type}": link)
|
||||
- if link.present?
|
||||
.support.card.featured.mb-4.ml-4.hidden{ id: "card-#{question_type}", "aria-hidden": true , data: { "support-target": "content" } }
|
||||
.card-title
|
||||
= t('.our_answer')
|
||||
.card-content
|
||||
-# i18n-tasks-use t("support.index.#{question_type}.answer_html")
|
||||
= t('answer_html', scope: [:support, :index, question_type], base_url: APPLICATION_BASE_URL, "link_#{question_type}": link)
|
||||
|
||||
|
||||
.contact-champ
|
||||
= label_tag :dossier_id, t('file_number', scope: [:utils])
|
||||
= text_field_tag :dossier_id, @dossier_id
|
||||
.fr-input-group
|
||||
= label_tag :dossier_id, t('file_number', scope: [:utils]), class: 'fr-label'
|
||||
= text_field_tag :dossier_id, @dossier_id, class: 'fr-input'
|
||||
|
||||
.contact-champ
|
||||
= label_tag :subject do
|
||||
.fr-input-group
|
||||
= label_tag :subject, class: 'fr-label' do
|
||||
= t('subject', scope: [:utils])
|
||||
%span.mandatory *
|
||||
= text_field_tag :subject, params[:subject], required: true
|
||||
= text_field_tag :subject, params[:subject], required: true, class: 'fr-input'
|
||||
|
||||
.contact-champ
|
||||
= label_tag :text do
|
||||
.fr-input-group
|
||||
= label_tag :text, class: 'fr-label' do
|
||||
= t('message', scope: [:utils])
|
||||
%span.mandatory *
|
||||
= text_area_tag :text, params[:text], rows: 6, required: true
|
||||
= text_area_tag :text, params[:text], rows: 6, required: true, class: 'fr-input'
|
||||
|
||||
.contact-champ
|
||||
= label_tag :piece_jointe do
|
||||
.fr-upload-group
|
||||
= label_tag :piece_jointe, class: 'fr-label' do
|
||||
= t('pj', scope: [:utils])
|
||||
%span.fr-hint-text Taille maximale : 200 Mo. Formats supportés : jpg, png, pdf.
|
||||
|
||||
%p.notice.hidden{ data: { 'contact-type-only': Helpscout::FormAdapter::TYPE_AMELIORATION } }
|
||||
= t('.notice_pj_product')
|
||||
%p.notice.hidden{ data: { 'contact-type-only': Helpscout::FormAdapter::TYPE_AUTRE } }
|
||||
= t('.notice_pj_other')
|
||||
= file_field_tag :piece_jointe
|
||||
= file_field_tag :piece_jointe, class: 'fr-upload', max: 200.megabytes
|
||||
|
||||
= hidden_field_tag :tags, @tags&.join(',')
|
||||
|
||||
= invisible_captcha
|
||||
|
||||
.send-wrapper
|
||||
= button_tag t('send_mail', scope: [:utils]), type: :submit, class: 'button send primary'
|
||||
.send-wrapper.fr-my-3w
|
||||
= button_tag t('send_mail', scope: [:utils]), type: :submit, class: 'fr-btn send'
|
||||
|
|
Loading…
Reference in a new issue