diff --git a/core/includes/form.inc b/core/includes/form.inc index 16353d8..3ecbfd6 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -213,14 +213,18 @@ function template_preprocess_fieldset(&$variables) { $variables['legend']['attributes'] = new Attribute(); $variables['legend_span']['attributes'] = new Attribute(); + $variables['description'] = NULL; if (!empty($element['#description'])) { - $description_id = $element['#attributes']['id'] . '--description'; - $description_attributes['id'] = $description_id; + $variables['description_display'] = $element['#description_display']; + $description_attributes = []; + if ($element['#description_display'] === 'invisible') { + $description_attributes['class'][] = 'visually-hidden'; + } + if (!empty($element['#id'])) { + $description_attributes['id'] = $element['#id'] . '--description'; + } $variables['description']['attributes'] = new Attribute($description_attributes); $variables['description']['content'] = $element['#description']; - - // Add the description's id to the fieldset aria attributes. - $variables['attributes']['aria-describedby'] = $description_id; } // Display any error messages. diff --git a/core/modules/language/config/optional/tour.tour.language-edit.yml b/core/modules/language/config/optional/tour.tour.language-edit.yml index 0d37ead..df615a5 100644 --- a/core/modules/language/config/optional/tour.tour.language-edit.yml +++ b/core/modules/language/config/optional/tour.tour.language-edit.yml @@ -36,7 +36,7 @@ tips: body: '

Choose if the language is a "Left to right" or "Right to left" language.

Note that not all themes support "Right to left" layouts, so test your theme if you are using "Right to left".

' weight: 4 attributes: - data-id: edit-direction--wrapper--description + data-id: edit-direction--description language-edit-continue: id: language-edit-continue plugin: text diff --git a/core/modules/system/src/Tests/Form/ElementsFieldsetTest.php b/core/modules/system/src/Tests/Form/ElementsFieldsetTest.php new file mode 100644 index 0000000..82b3d79 --- /dev/null +++ b/core/modules/system/src/Tests/Form/ElementsFieldsetTest.php @@ -0,0 +1,52 @@ +drupalGet('form-test/group-fieldset'); + + // Check #description placement with #description_display='before'. + $field_id = 'edit-fieldset-before'; + $description_id = $field_id . '--description'; + $elements = $this->xpath('//fieldset[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]//div[@id="edit-meta-before"]/preceding-sibling::div[@id="' . $description_id . '"]'); + $this->assertTrue(isset($elements[0]), t('Properly places the #description element before the form item.')); + + // Check #description placement with #description_display='after'. + $field_id = 'edit-fieldset-after'; + $description_id = $field_id . '--description'; + $elements = $this->xpath('//fieldset[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]//div[@id="edit-meta-after"]/following-sibling::div[@id="' . $description_id . '"]'); + $this->assertTrue(isset($elements[0]), t('Properly places the #description element after the form item.')); + + // Check if the class is 'visually-hidden' on the form fieldset description + // for the option with #description_display='invisible' and also check that + // the description is placed after the form element. + $field_id = 'edit-fieldset-invisible'; + $description_id = $field_id . '--description'; + $elements = $this->xpath('//fieldset[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]//div[@id="edit-meta-invisible"]/following-sibling::div[contains(@class, "visually-hidden")]'); + $this->assertTrue(isset($elements[0]), t('Properly renders the #description element visually-hidden.')); + } +} \ No newline at end of file diff --git a/core/modules/system/templates/fieldset.html.twig b/core/modules/system/templates/fieldset.html.twig index b67ec85..54247e4 100644 --- a/core/modules/system/templates/fieldset.html.twig +++ b/core/modules/system/templates/fieldset.html.twig @@ -13,6 +13,12 @@ * - description: The description element containing the following properties: * - content: The description content of the fieldset. * - attributes: HTML attributes to apply to the description container. + * - description_display: Description display setting. It can have these values: + * - before: The description is output before the element. + * - after: The description is output after the element. This is the default + * value. + * - invisible: The description is output after the element, hidden visually + * but available to screen readers. * - children: The rendered child elements of the fieldset. * - prefix: The content to add before the fieldset children. * - suffix: The content to add after the fieldset children. @@ -43,6 +49,11 @@ {{ legend.title }}
+ {% if description_display == 'before' and description.content %} + + {{ description.content }} +
+ {% endif %} {% if errors %}
{{ errors }} @@ -55,8 +66,10 @@ {% if suffix %} {{ suffix }} {% endif %} - {% if description.content %} - {{ description.content }}
+ {% if description_display in ['after', 'invisible'] and description.content %} + + {{ description.content }} + {% endif %} diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupFieldsetForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupFieldsetForm.php index e55b1af..58d6136 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupFieldsetForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupFieldsetForm.php @@ -26,19 +26,67 @@ public function getFormId() { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { - $form['fieldset'] = array( + $form['fieldset'] = [ '#type' => 'fieldset', '#title' => 'Fieldset', - ); - $form['meta'] = array( + ]; + $form['meta'] = [ '#type' => 'container', '#title' => 'Group element', '#group' => 'fieldset', - ); - $form['meta']['element'] = array( + ]; + $form['meta']['element'] = [ '#type' => 'textfield', '#title' => 'Nest in container element', - ); + ]; + + $form['fieldset_before'] = [ + '#type' => 'fieldset', + '#title' => 'Fieldset test for description before element', + '#description' => 'Fieldset test for description before element.', + '#description_display' => 'before', + ]; + $form['meta_before'] = [ + '#type' => 'container', + '#title' => 'Group element', + '#group' => 'fieldset_before', + ]; + $form['meta_before']['element'] = [ + '#type' => 'textfield', + '#title' => 'Nest in container element', + ]; + + $form['fieldset_after'] = [ + '#type' => 'fieldset', + '#title' => 'Fieldset test for description after element', + '#description' => 'Fieldset test for description after element.', + '#description_display' => 'after', + ]; + $form['meta_after'] = [ + '#type' => 'container', + '#title' => 'Group element', + '#group' => 'fieldset_after', + ]; + $form['meta_after']['element'] = [ + '#type' => 'textfield', + '#title' => 'Nest in container element', + ]; + + $form['fieldset_invisible'] = [ + '#type' => 'fieldset', + '#title' => 'Fieldset test for visually-hidden description', + '#description' => 'Fieldset test for visually-hidden description.', + '#description_display' => 'invisible', + ]; + $form['meta_invisible'] = [ + '#type' => 'container', + '#title' => 'Group element', + '#group' => 'fieldset_invisible', + ]; + $form['meta_invisible']['element'] = [ + '#type' => 'textfield', + '#title' => 'Nest in container element', + ]; return $form; } diff --git a/core/themes/classy/templates/form/fieldset.html.twig b/core/themes/classy/templates/form/fieldset.html.twig index 4bd7d0a..85f5228 100644 --- a/core/themes/classy/templates/form/fieldset.html.twig +++ b/core/themes/classy/templates/form/fieldset.html.twig @@ -13,6 +13,12 @@ * - description: The description element containing the following properties: * - content: The description content of the fieldset. * - attributes: HTML attributes to apply to the description container. + * - description_display: Description display setting. It can have these values: + * - before: The description is output before the element. + * - after: The description is output after the element. This is the default + * value. + * - invisible: The description is output after the element, hidden visually + * but available to screen readers. * - children: The rendered child elements of the fieldset. * - prefix: The content to add before the fieldset children. * - suffix: The content to add after the fieldset children. @@ -41,6 +47,11 @@ {{ legend.title }}
+ {% if description_display == 'before' and description.content %} + + {{ description.content }} +
+ {% endif %} {% if errors %}
{{ errors }} @@ -53,8 +64,10 @@ {% if suffix %} {{ suffix }} {% endif %} - {% if description.content %} - {{ description.content }}
+ {% if description_display in ['after', 'invisible'] and description.content %} + + {{ description.content }} + {% endif %}