diff --git a/core/lib/Drupal/Core/Render/Element/RenderElement.php b/core/lib/Drupal/Core/Render/Element/RenderElement.php
index 243a9af..e7b48dc 100644
--- a/core/lib/Drupal/Core/Render/Element/RenderElement.php
+++ b/core/lib/Drupal/Core/Render/Element/RenderElement.php
@@ -204,6 +204,15 @@ public static function preRenderGroup($element) {
}
}
+ // Set attributes to indicate that there is a child with an error.
+ if (!empty($element['#children_errors'])) {
+ $element['#attributes']['class'][] = 'form-wrapper--child-error';
+ if ($element['#type'] === 'details') {
+ $element['#attributes']['class'][] = 'details--child-error';
+ }
+ $element['#attributes']['data-children-errors-count'] = count($element['#children_errors']);
+ }
+
return $element;
}
diff --git a/core/misc/vertical-tabs.es6.js b/core/misc/vertical-tabs.es6.js
index c7ad2fd..1c1c28d 100644
--- a/core/misc/vertical-tabs.es6.js
+++ b/core/misc/vertical-tabs.es6.js
@@ -60,7 +60,8 @@
var $that = $(this);
var vertical_tab = new Drupal.verticalTab({
title: $that.find('> summary').text(),
- details: $that
+ details: $that,
+ children_errors: $that.data('children-errors-count')
});
tab_list.append(vertical_tab.item);
$that
@@ -246,6 +247,11 @@
.append(tab.summary = $('')
)
);
+
+ if (settings.children_errors) {
+ tab.item.addClass('vertical-tab__menu-item--child-error');
+ }
+
return tab;
};
diff --git a/core/misc/vertical-tabs.js b/core/misc/vertical-tabs.js
index c47a7cb..0eb23da 100644
--- a/core/misc/vertical-tabs.js
+++ b/core/misc/vertical-tabs.js
@@ -35,7 +35,8 @@
var $that = $(this);
var vertical_tab = new Drupal.verticalTab({
title: $that.find('> summary').text(),
- details: $that
+ details: $that,
+ children_errors: $that.data('children-errors-count')
});
tab_list.append(vertical_tab.item);
$that.removeClass('collapsed').attr('open', true).addClass('vertical-tabs__pane').data('verticalTab', vertical_tab);
@@ -137,6 +138,11 @@
Drupal.theme.verticalTab = function (settings) {
var tab = {};
tab.item = $('
').append(tab.link = $('').append(tab.title = $('').text(settings.title)).append(tab.summary = $('')));
+
+ if (settings.children_errors) {
+ tab.item.addClass('vertical-tab__menu-item--child-error');
+ }
+
return tab;
};
})(jQuery, Drupal, drupalSettings);
\ No newline at end of file
diff --git a/core/modules/node/tests/src/Functional/NodeEditFormTest.php b/core/modules/node/tests/src/Functional/NodeEditFormTest.php
index ce032e5..13d04a0 100644
--- a/core/modules/node/tests/src/Functional/NodeEditFormTest.php
+++ b/core/modules/node/tests/src/Functional/NodeEditFormTest.php
@@ -126,7 +126,7 @@ public function testNodeEdit() {
$open_details_elements = count($this->cssSelect('details[open="open"]'));
$this->drupalPostForm(NULL, $edit, t('Save'));
// The node author details must be open.
- $this->assertRaw('');
+ $this->assertRaw('');
// Only one extra details element should now be open.
$open_details_elements++;
$this->assertEqual(count($this->cssSelect('details[open="open"]')), $open_details_elements, 'Exactly one extra open <details> element found.');
diff --git a/core/themes/bartik/bartik.libraries.yml b/core/themes/bartik/bartik.libraries.yml
index 3bbecd9..bace5d0 100644
--- a/core/themes/bartik/bartik.libraries.yml
+++ b/core/themes/bartik/bartik.libraries.yml
@@ -10,6 +10,7 @@ global-styling:
css/components/captions.css: {}
css/components/comments.css: {}
css/components/contextual.css: {}
+ css/components/details.css: {}
css/components/demo-block.css: {}
# @see https://www.drupal.org/node/2389735
css/components/dropbutton.component.css: {}
diff --git a/core/themes/bartik/css/components/details.css b/core/themes/bartik/css/components/details.css
new file mode 100644
index 0000000..2277e9d
--- /dev/null
+++ b/core/themes/bartik/css/components/details.css
@@ -0,0 +1,33 @@
+/**
+ * @file
+ * Collapsible details.
+ *
+ * @see collapse.js
+ */
+
+/* Errors */
+.details--child-error:not([open]) summary {
+ background-color: #f1f1f1;
+}
+.details--child-error:not([open]) summary:before {
+ content: '';
+ display: inline-block;
+ height: 20px;
+ width: 14px;
+ background: url(../../../../misc/icons/e32700/error.svg) no-repeat center;
+ background-size: contain;
+ float: right; /* LTR */
+}
+[dir="rtl"] .details--child-error:not([open]) summary:before {
+ float: left;
+}
+.details--child-error:not([open]) {
+ border: 2px solid red;
+ box-shadow: inset 7px 0 0 red; /* LTR */
+ padding-left: 7px; /* LTR */
+}
+[dir="rtl"] .details--child-error:not([open]) {
+ box-shadow: inset -7px 0 0 red;
+ padding-left: 0;
+ padding-right: 7px;
+}
diff --git a/core/themes/bartik/css/components/vertical-tabs.component.css b/core/themes/bartik/css/components/vertical-tabs.component.css
index ce4d6cd..95cd421 100644
--- a/core/themes/bartik/css/components/vertical-tabs.component.css
+++ b/core/themes/bartik/css/components/vertical-tabs.component.css
@@ -14,3 +14,40 @@
/* This is required to win specificity over [dir="rtl"] .region-content ul */
padding: 0;
}
+.vertical-tab__menu-item--child-error.is-selected {
+ padding-top: 1px;
+}
+.vertical-tab__menu-item--child-error:not(.is-selected) {
+ border-top: 1px solid red;
+ background-color: #f1f1f1;
+ box-shadow: inset 7px 0 0 red; /* LTR */
+ border-radius: 2px 0 0 2px; /* LTR */
+ padding-left: 7px; /* LTR */
+}
+.vertical-tab__menu-item--child-error:not(.is-selected) a {
+ padding-left: 7px; /* LTR */
+ border-bottom: 1px solid red;
+ color: #e32700;
+}
+[dir="rtl"] .vertical-tab__menu-item--child-error:not(.is-selected) {
+ box-shadow: inset -7px 0 0 red;
+ border-radius: 0 2px 2px 0;
+ padding-left: 0;
+ padding-right: 7px;
+}
+[dir="rtl"] .vertical-tab__menu-item--child-error:not(.is-selected) a {
+ padding-left: 7px;
+ padding-right: 7px;
+}
+.vertical-tab__menu-item--child-error:not(.is-selected) .vertical-tabs__menu-item-title:before {
+ content: '';
+ display: inline-block;
+ height: 20px;
+ width: 14px;
+ background: url(../../../../misc/icons/e32700/error.svg) no-repeat center;
+ background-size: contain;
+ float: right;
+}
+[dir="rtl"] .vertical-tab__menu-item--child-error:not(.is-selected) .vertical-tabs__menu-item-title:before {
+ float: left;
+}
diff --git a/core/themes/seven/css/components/details.css b/core/themes/seven/css/components/details.css
new file mode 100644
index 0000000..07d33be
--- /dev/null
+++ b/core/themes/seven/css/components/details.css
@@ -0,0 +1,33 @@
+/**
+ * @file
+ * Collapsible details.
+ *
+ * @see collapse.js
+ */
+
+/* Errors */
+.details--child-error:not([open]) summary:before {
+ content: '';
+ display: inline-block;
+ height: 16px;
+ width: 14px;
+ background: url(../../../../misc/icons/e32700/error.svg) no-repeat center;
+ background-size: contain;
+ float: right; /* LTR */
+}
+[dir="rtl"] .details--child-error:not([open]) summary:before {
+ float: left;
+}
+.details--child-error:not([open]) {
+ border: 1px solid #e62600;
+ box-shadow: inset 7px 0 0 #e62600; /* LTR */
+ border-radius: 2px 0 0 2px; /* LTR */
+ padding-left: 7px; /* LTR */
+ color: #e62600;
+}
+[dir="rtl"] .details--child-error:not([open]) {
+ box-shadow: inset -7px 0 0 #e62600;
+ border-radius: 0 2px 2px 0;
+ padding-left: 0;
+ padding-right: 7px;
+}
diff --git a/core/themes/seven/css/components/entity-meta.css b/core/themes/seven/css/components/entity-meta.css
index 701e8dc..a0f6151 100644
--- a/core/themes/seven/css/components/entity-meta.css
+++ b/core/themes/seven/css/components/entity-meta.css
@@ -57,3 +57,21 @@
.entity-meta details .summary {
display: none; /* Hide JS summaries. @todo Rethink summaries. */
}
+.entity-meta .details--child-error:not([open]) {
+ padding-left: 6px;
+}
+.entity-meta .details--child-error:not([open]) > * {
+ position: relative;
+ left: -7px;
+ margin-right: -12px;
+}
+[dir="rtl"] .entity-meta details.error:not([open]) {
+ padding-left: 0;
+ padding-right: 7px;
+}
+[dir="rtl"] .entity-meta details.error:not([open]) > * {
+ right: -8px;
+ left: auto;
+ margin-left: -12px;
+ margin-right: 0;
+}
diff --git a/core/themes/seven/css/components/vertical-tabs.css b/core/themes/seven/css/components/vertical-tabs.css
index 34b5a52..cefae6d 100644
--- a/core/themes/seven/css/components/vertical-tabs.css
+++ b/core/themes/seven/css/components/vertical-tabs.css
@@ -37,6 +37,44 @@
.vertical-tabs__menu-item.last {
border-bottom: none;
}
+.vertical-tab__menu-item--child-error.is-selected {
+ padding-top: 1px;
+}
+.vertical-tab__menu-item--child-error:not(.is-selected) {
+ border: 1px solid #e62600;
+ border-right: 0;
+ border-bottom-color: #ccc;
+ box-shadow: inset 7px 0 0 #e62600; /* LTR */
+ border-radius: 2px 0 0 2px; /* LTR */
+ padding-left: 7px; /* LTR */
+}
+.vertical-tab__menu-item--child-error:not(.is-selected) a {
+ padding-left: 7px; /* LTR */
+ padding-right: 10px;
+ border-bottom: 1px solid #e62600;
+ color: #e62600;
+}
+[dir="rtl"] .vertical-tab__menu-item--child-error:not(.is-selected) {
+ box-shadow: inset -7px 0 0 #e62600;
+ border-radius: 0 2px 2px 0;
+ padding-left: 0;
+ padding-right: 7px;
+}
+[dir="rtl"] .vertical-tab__menu-item--child-error:not(.is-selected) a {
+ padding-right: 7px;
+}
+.vertical-tab__menu-item--child-error:not(.is-selected) .vertical-tabs__menu-item-title:before {
+ content: '';
+ display: inline-block;
+ height: 14px;
+ width: 14px;
+ background: url(../../../../misc/icons/e32700/error.svg) no-repeat center;
+ background-size: contain;
+ float: right;
+}
+[dir="rtl"] .vertical-tab__menu-item--child-error:not(.is-selected) .vertical-tabs__menu-item-title:before {
+ float: left;
+}
[dir="rtl"] .vertical-tabs__menu-item.is-selected {
border-left: 1px solid #fcfcfa;
border-right: none;
diff --git a/core/themes/seven/seven.libraries.yml b/core/themes/seven/seven.libraries.yml
index 424e7f5..2010f6d 100644
--- a/core/themes/seven/seven.libraries.yml
+++ b/core/themes/seven/seven.libraries.yml
@@ -12,6 +12,7 @@ global-styling:
css/components/buttons.css: {}
css/components/colors.css: {}
css/components/messages.css: {}
+ css/components/details.css: {}
css/components/dropbutton.component.css: {}
css/components/entity-meta.css: {}
css/components/field-ui.css: {}