Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion templates/input/form-element-label.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
title_display == 'invisible' and not (is_checkbox or is_radio) ? 'sr-only',
required ? 'js-form-required',
required ? 'form-required',
required ? 'required'
required and not (is_checkbox or is_radio) ? 'required'
]
-%}
{% if title is not empty and title_display == 'invisible' and (is_checkbox or is_radio) -%}
Expand Down
14 changes: 12 additions & 2 deletions templates/input/form-element.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,12 @@
'js-form-item-' ~ name|clean_class,
title_display not in ['after', 'before'] ? 'form-no-label',
disabled == 'disabled' ? 'form-disabled',
is_form_group ? 'form-group',
is_radio ? 'radio',
is_checkbox ? 'checkbox',
is_single_checkbox ? 'checkbox-standalone',
is_autocomplete ? 'form-autocomplete',
has_error ? 'error has-error'
has_error ? 'error has-error',
required ? 'required',
]
%}{%
set description_classes = [
Expand All @@ -70,6 +71,11 @@
description_display == 'invisible' ? 'visually-hidden',
]
%}

{% if is_form_group %}
<div class="form-group">
{% endif %}

<div{{ attributes.addClass(classes) }}>
{% if label_display in ['before', 'invisible'] %}
{{ label }}
Expand Down Expand Up @@ -99,3 +105,7 @@
</div>
{% endif %}
</div>

{% if is_form_group %}
</div>
{% endif %}
79 changes: 79 additions & 0 deletions templates/system/fieldset.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{#
/**
* @file
* Default theme implementation for a fieldset element and its children.
*
* Available variables:
* - attributes: HTML attributes for the <fieldset> element.
* - errors: (optional) Any errors for this <fieldset> element, may not be set.
* - required: Boolean indicating whether the <fieldset> element is required.
* - legend: The <legend> element containing the following properties:
* - title: Title of the <fieldset>, intended for use as the text
of the <legend>.
* - attributes: HTML attributes to apply to the <legend> element.
* - 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 (default).
* - 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.
*
* @see template_preprocess_fieldset()
*
* @ingroup themeable
*/
#}
{%
set classes = [
'js-form-item',
'form-item',
'js-form-wrapper',
'form-wrapper',
]
%}
<fieldset{{ attributes.addClass(classes) }}>
{%
set legend_span_classes = [
'fieldset-legend',
required ? 'js-form-required',
required ? 'form-required',
]
%}
{%
set legend_classes = [
required ? 'required',
]
%}
{# Always wrap fieldset legends in a <span> for CSS positioning. #}
<legend{{ legend.attributes.addClass(legend_classes) }}>
<span{{ legend_span.attributes.addClass(legend_span_classes) }}>{{ legend.title }}</span>
{% if required %}
<strong class="required">({{ 'required'|t }})</strong>
{% endif %}
</legend>
<div class="fieldset-wrapper">
{% if description_display == 'before' and description.content %}
<div{{ description.attributes.addClass('description') }}>{{ description.content }}</div>
{% endif %}
{% if errors %}
<div>
{{ errors }}
</div>
{% endif %}
{% if prefix %}
<span class="field-prefix">{{ prefix }}</span>
{% endif %}
{{ children }}
{% if suffix %}
<span class="field-suffix">{{ suffix }}</span>
{% endif %}
{% if description_display in ['after', 'invisible'] and description.content %}
<div{{ description.attributes.addClass('description') }}>{{ description.content }}</div>
{% endif %}
</div>
</fieldset>
39 changes: 39 additions & 0 deletions wxt_bootstrap.theme
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,42 @@ function wxt_bootstrap_preprocess_paragraph(&$variables) {
$variables['link_provider_label'] = $allowed_values[$key] ?? $key;
}
}

/**
* Implements hook_preprocess_form_element().
*/
function wxt_bootstrap_preprocess_form_element(array &$variables) {
// Mirror #required from the render array to Twig's $required so the template
// can add required classes/markers (used by GCWeb/WET and legend styling).
if (!empty($variables['element']['#required'])) {
$variables['required'] = TRUE;
}

// Webform context: if this is the single "checkbox" plugin, force Bootstrap's
// form-group wrapper and flag it as a single checkbox so spacing/markup match
if (!empty($variables['element']['#webform_plugin_id'])) {
if ($variables['element']['#webform_plugin_id'] == 'checkbox') {
$variables['is_form_group'] = TRUE;
$variables['is_single_checkbox'] = TRUE;
}
}
}

/**
* Implements hook_preprocess_fieldset().
*/
function wxt_bootstrap_preprocess_fieldset(array &$variables) {
$element = $variables['element'] ?? [];
$checkbox_radio_group = [
'radios',
'checkboxes',
];

// When the fieldset is a radios/checkboxes group, add a marker class so
// WET/GCWeb can style spacing/legend consistently.
if (in_array($element['#type'], $checkbox_radio_group)) {
if (isset($variables['attributes'])) {
$variables['attributes']['class'][] = 'chkbxrdio-grp';
}
}
}