';
+ $variables['children'] = !empty($element['#children']) ? $element['#children'] : '';
}
/**
@@ -3410,11 +3399,9 @@ function form_process_container($element, &$form_state) {
}
/**
- * Returns HTML to wrap child elements in a container.
+ * Prepares variables for container templates.
*
- * Used for grouped form items. Can also be used as a #theme_wrapper for any
- * renderable element, to surround it with a
and add attributes such as
- * classes or an HTML id.
+ * Default template: container.html.twig.
*
* @param $variables
* An associative array containing:
@@ -3423,7 +3410,7 @@ function form_process_container($element, &$form_state) {
*
* @ingroup themeable
*/
-function theme_container($variables) {
+function template_preprocess_container(&$variables) {
$element = $variables['element'];
// Special handling for form elements.
@@ -3436,11 +3423,12 @@ function theme_container($variables) {
$element['#attributes']['class'][] = 'form-wrapper';
}
- return '
' . $element['#children'] . '
';
+ $variables['children'] = $element['#children'];
+ $variables['attributes'] = new Attribute($element['#attributes']);
}
/**
- * Returns HTML for a table with radio buttons or checkboxes.
+ * Prepares variables for a table with radio buttons or checkboxes.
*
* @param $variables
* An associative array containing:
@@ -3478,11 +3466,8 @@ function theme_container($variables) {
* '#empty' => t('No content available.'),
* );
* @endcode
- *
- * @ingroup themeable
*/
-function theme_tableselect($variables) {
- $element = $variables['element'];
+function form_pre_render_tableselect(array $element) {
$rows = array();
$header = $element['#header'];
if (!empty($element['#options'])) {
@@ -3522,7 +3507,7 @@ function theme_tableselect($variables) {
// checkboxes/radios in the first table column.
if ($element['#js_select']) {
// Add a "Select all" checkbox.
- drupal_add_library('system', 'drupal.tableselect');
+ $element['#attached']['library'][] = array('system', 'drupal.tableselect');
array_unshift($header, array('class' => array('select-all')));
}
else {
@@ -3531,7 +3516,11 @@ function theme_tableselect($variables) {
array_unshift($header, '');
}
}
- return theme('table', array('header' => $header, 'rows' => $rows, 'empty' => $element['#empty'], 'attributes' => $element['#attributes']));
+ // This is all we really change.
+ $element['#header'] = $header;
+ $element['#rows'] = $rows;
+
+ return $element;
}
/**
@@ -3922,11 +3911,13 @@ function form_process_group(&$element, &$form_state) {
* The modified element.
*/
function form_pre_render_details($element) {
- // The .form-wrapper class is required for #states to treat details like
- // containers.
+ element_set_attributes($element, array('id'));
if (!isset($element['#attributes']['class'])) {
$element['#attributes']['class'] = array();
}
+ // The .form-wrapper class is required for #states to treat details like
+ // containers.
+ _form_set_attributes($element, array('form-wrapper'));
// Collapsible details.
$element['#attached']['library'][] = array('system', 'drupal.collapse');
@@ -4060,18 +4051,17 @@ function form_pre_render_vertical_tabs($element) {
}
/**
- * Returns HTML for an element's children details as vertical tabs.
+ * Preapres an element's children details for vertical tabs templates.
+ *
+ * Default template: vertical-tabs.html.twig.
*
* @param $variables
* An associative array containing:
* - element: An associative array containing the properties and children of
* the details element. Properties used: #children.
- *
- * @ingroup themeable
*/
-function theme_vertical_tabs($variables) {
- $element = $variables['element'];
- return '
' . $element['#children'] . '
';
+function template_preprocess_vertical_tabs(&$variables) {
+ $variables['children'] = $variables['element']['#children'];
}
/**
@@ -4113,33 +4103,17 @@ function form_process_autocomplete($element, &$form_state) {
}
/**
- * Preprocesses variables for theme_input().
- *
- * @param array $variables
- * An associative array containing:
- * - element: An associative array containing the properties of the element.
+ * Prepares variables for input templates.
*
- * @ingroup themeable
- */
-function template_preprocess_input(&$variables) {
- $element = $variables['element'];
- $variables['attributes'] = new Attribute($element['#attributes']);
-}
-
-/**
- * Returns HTML for an input form element.
+ * Default template: input.html.twig.
*
* @param array $variables
* An associative array containing:
* - element: An associative array containing the properties of the element.
- * Properties used: #attributes.
- *
- * @ingroup themeable
*/
-function theme_input($variables) {
- $element = $variables['element'];
- $attributes = $variables['attributes'];
- return '' . drupal_render_children($element);
+function template_preprocess_input(&$variables) {
+ $variables['attributes'] = new Attribute($variables['element']['#attributes']);
+ $variables['children'] = drupal_render_children($variables['element']);
}
/**
@@ -4499,7 +4473,9 @@ function form_pre_render_color($element) {
}
/**
- * Returns HTML for a form.
+ * Prepares variables for form templates.
+ *
+ * Default template: form.html.twig.
*
* @param $variables
* An associative array containing:
@@ -4508,48 +4484,40 @@ function form_pre_render_color($element) {
*
* @ingroup themeable
*/
-function theme_form($variables) {
+function template_preprocess_form(&$variables) {
$element = $variables['element'];
+ element_set_attributes($element, array('method', 'id'));
if (isset($element['#action'])) {
$element['#attributes']['action'] = drupal_strip_dangerous_protocols($element['#action']);
}
- element_set_attributes($element, array('method', 'id'));
if (empty($element['#attributes']['accept-charset'])) {
$element['#attributes']['accept-charset'] = "UTF-8";
}
- // Anonymous DIV to satisfy XHTML compliance.
- return '';
+ $variables['attributes'] = new Attribute($element['#attributes']);
+ $variables['children'] = $element['#children'];
}
/**
- * Returns HTML for a textarea form element.
+ * Prepares variables for textarea form element templates.
+ *
+ * Default template: textarea.html.twig.
*
* @param $variables
* An associative array containing:
* - element: An associative array containing the properties of the element.
* Properties used: #title, #value, #description, #rows, #cols,
* #placeholder, #required, #attributes, #resizable
- *
- * @ingroup themeable
*/
-function theme_textarea($variables) {
+function template_preprocess_textarea(&$variables) {
$element = $variables['element'];
element_set_attributes($element, array('id', 'name', 'rows', 'cols', 'placeholder'));
_form_set_attributes($element, array('form-textarea'));
-
- $wrapper_attributes = array(
- 'class' => array('form-textarea-wrapper'),
- );
-
- // Add resizable behavior.
if (!empty($element['#resizable'])) {
$element['#attributes']['class'][] = 'resize-' . $element['#resizable'];
}
- $output = '
';
- $output .= '';
- $output .= '
';
- return $output;
+ $variables['attributes'] = new Attribute($element['#attributes']);
+ $variables['value'] = check_plain($element['#value']);
}
/**
@@ -4621,7 +4589,9 @@ function form_pre_render_file($element) {
}
/**
- * Returns HTML for a form element.
+ * Prepares variables for form element templates.
+ *
+ * Default template: form-element.html.twig.
*
* Each form element is wrapped in a DIV container having the following CSS
* classes:
@@ -4663,102 +4633,77 @@ function form_pre_render_file($element) {
* - element: An associative array containing the properties of the element.
* Properties used: #title, #title_display, #description, #id, #required,
* #children, #type, #name.
- *
- * @ingroup themeable
*/
-function theme_form_element($variables) {
- $element = &$variables['element'];
+function template_preprocess_form_element(&$variables) {
+ $element = $variables['element'];
// This function is invoked as theme wrapper, but the rendered form element
// may not necessarily have been processed by form_builder().
$element += array(
'#title_display' => 'before',
);
-
+ // If #title is not set, we don't display any label or required marker.
+ if (!isset($element['#title'])) {
+ $element['#title_display'] = 'none';
+ }
+ // We call it a label, though.
+ $variables['label_display'] = $element['#title_display'];
+ // Label returns empty tring in some cases.
+ $variables['label'] = theme('form_element_label', $variables);
// Take over any #wrapper_attributes defined by the element.
// @todo Temporary hack for #type 'item'.
// @see http://drupal.org/node/1829202
- if (isset($element['#wrapper_attributes'])) {
- $attributes = $element['#wrapper_attributes'];
- }
- // Add element #id for #type 'item'.
- if (isset($element['#markup']) && !empty($element['#id'])) {
- $attributes['id'] = $element['#id'];
- }
+ $variables['wrapper_attributes'] = new Attribute((isset($element['#wrapper_attributes'])) ? $element['#wrapper_attributes'] : array('class' => array()));
// Add element's #type and #name as class to aid with JS/CSS selectors.
- $attributes['class'][] = 'form-item';
+ $variables['wrapper_attributes']['class'][] = 'form-item';
if (!empty($element['#type'])) {
- $attributes['class'][] = 'form-type-' . strtr($element['#type'], '_', '-');
+ $variables['wrapper_attributes']['class'][] = 'form-type-' . strtr($element['#type'], '_', '-');
}
if (!empty($element['#name'])) {
- $attributes['class'][] = 'form-item-' . strtr($element['#name'], array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
+ $variables['wrapper_attributes']['class'][] = 'form-item-' . strtr($element['#name'], array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
}
// Add a class for disabled elements to facilitate cross-browser styling.
if (!empty($element['#attributes']['disabled'])) {
- $attributes['class'][] = 'form-disabled';
- }
- $output = '
\n";
-
- return $output;
}
/**
- * Returns HTML for a marker for required form elements.
+ * Prepares variables for form element required marker templates.
+ *
+ * Default template: form-element-required.html.twig.
*
* @param $variables
* An associative array containing:
* - element: An associative array containing the properties of the element.
- *
- * @ingroup themeable
*/
-function theme_form_required_marker($variables) {
+function template_preprocess_form_required_marker(&$variables) {
// This is also used in the installer, pre-database setup.
$t = get_t();
- $attributes = array(
+ $variables['attributes'] = new Attribute(array(
'class' => 'form-required',
'title' => $t('This field is required.'),
- );
- return '*';
+ ));
}
/**
- * Returns HTML for a form element label and required marker.
+ * Prepares variables for form element label templates.
+ *
+ * Default template: form-label.html.twig.
*
* Form element labels include the #title and a #required marker. The label is
* associated with the element itself by the element #id. Labels may appear
@@ -4777,39 +4722,40 @@ function theme_form_required_marker($variables) {
* An associative array containing:
* - element: An associative array containing the properties of the element.
* Properties used: #required, #title, #id, #value, #description.
- *
- * @ingroup themeable
*/
-function theme_form_element_label($variables) {
+function template_preprocess_form_element_label(&$variables) {
$element = $variables['element'];
// This is also used in the installer, pre-database setup.
$t = get_t();
- // If title and required marker are both empty, output no label.
- if ((!isset($element['#title']) || $element['#title'] === '') && empty($element['#required'])) {
- return '';
- }
-
- // If the element is required, a required marker is appended to the label.
- $required = !empty($element['#required']) ? theme('form_required_marker', array('element' => $element)) : '';
-
- $title = filter_xss_admin($element['#title']);
-
- $attributes = array();
- // Style the label as class option to display inline with the element.
- if ($element['#title_display'] == 'after') {
- $attributes['class'] = 'option';
- }
- // Show label only to screen readers to avoid disruption in visual flows.
- elseif ($element['#title_display'] == 'invisible') {
- $attributes['class'] = 'element-invisible';
+ // If title and required marker are both empty, prepare no label.
+ if (empty($element['#required']) && (!isset($element['#title']) || $element['#title'] === '')) {
+ $variables['label'] = FALSE;
+ $variables['required'] = FALSE;
+ return;
}
-
- if (!empty($element['#id'])) {
- $attributes['for'] = $element['#id'];
+ else {
+ // If the element is required, a required marker is appended to the label.
+ $variables['label'] = (isset($element['#title'])) ? $t(filter_xss_admin($element['#title'])) : NULL;
+ $variables['required'] = (!empty($element['#required'])) ? array('#theme' => 'form_required_marker', '#element' => $element) : '';
+ $variables['attributes'] = new Attribute(array('class' => array()));
+ // Associate the label with the field it is for.
+ if (!empty($element['#id'])) {
+ $variables['attributes']['for'] = $element['#id'];
+ }
+ // Add label positioning classes.
+ if (!empty($element['#title_display'])) {
+ // Style the label as class 'option' to display inline with the element.
+ // @todo: Use a more semantic class name like 'layout-inline-after'?
+ if ($element['#title_display'] == 'after') {
+ $variables['attributes']['class'][] = 'option';
+ }
+ // Show label only to screen readers to avoid disruption in visual flows.
+ elseif ($element['#title_display'] == 'invisible') {
+ $variables['attributes']['class'][] = 'element-invisible';
+ }
+ }
}
-
- return '';
}
/**
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index d2e461e..05c9f69 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -7,6 +7,7 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -374,6 +375,31 @@ function install_begin_request(&$install_state) {
))
->addMethodCall('setUserAgent', array('Drupal (+http://drupal.org/)'));
+ // Register the Twig theme engine.
+ $container->register('twig.loader.filesystem', 'Twig_Loader_Filesystem')
+ ->addArgument(DRUPAL_ROOT);
+ $container->register('twig', 'Drupal\Core\Template\TwigEnvironment')
+ ->addArgument(new Reference('twig.loader.filesystem'))
+ ->addArgument(array(
+ // Twig templates are saved / loaded via drupal_php_storage().
+ // All files can be refreshed by clearing caches.
+ // @todo ensure garbage collection of expired files.
+ 'cache' => TRUE,
+ 'base_template_class' => 'Drupal\Core\Template\TwigTemplate',
+ // @todo Implement Twig autoescape.
+ // @see http://drupal.org/node/1712444.
+ 'autoescape' => FALSE,
+ // @todo Decide on strict variables option.
+ // @see http://drupal.org/node/1806538.
+ 'strict_variables' => FALSE,
+ 'debug' => FALSE,
+ 'auto_reload' => FALSE,
+ ))
+ ->addMethodCall('addExtension', array(new Definition('Drupal\Core\Template\TwigExtension')))
+ // @todo Figure out what to do about debugging functions.
+ // @see http://drupal.org/node/1804998
+ ->addMethodCall('addExtension', array(new Definition('Twig_Extension_Debug')));
+
Drupal::setContainer($container);
}
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 1ed2caa..2d18766 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -3271,51 +3271,58 @@ function drupal_common_theme() {
// From form.inc.
'input' => array(
'render element' => 'element',
+ 'template' => 'input',
),
'select' => array(
'render element' => 'element',
+ 'template' => 'select',
),
'fieldset' => array(
'render element' => 'element',
+ 'template' => 'fieldset',
),
'details' => array(
'render element' => 'element',
+ 'template' => 'details',
),
'radios' => array(
'render element' => 'element',
- ),
- 'date' => array(
- 'render element' => 'element',
+ 'template' => 'radios',
),
'exposed_filters' => array(
'render element' => 'form',
),
'checkboxes' => array(
'render element' => 'element',
+ 'template' => 'checkboxes',
),
'form' => array(
'render element' => 'element',
+ 'template' => 'form',
),
'textarea' => array(
'render element' => 'element',
- ),
- 'tableselect' => array(
- 'render element' => 'element',
+ 'template' => 'textarea',
),
'form_element' => array(
'render element' => 'element',
+ 'template' => 'form-element',
),
'form_required_marker' => array(
'render element' => 'element',
+ 'template' => 'form-required-marker',
),
'form_element_label' => array(
'render element' => 'element',
+ 'template' => 'form-element-label',
),
'vertical_tabs' => array(
'render element' => 'element',
+ 'template' => 'vertical-tabs',
),
'container' => array(
'render element' => 'element',
+ 'template' => 'container',
),
);
}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
index 07591f5..2a727fb 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
@@ -94,7 +94,7 @@ function testRequiredFields() {
$elements['file']['empty_values'] = $empty_strings;
// Regular expression to find the expected marker on required elements.
- $required_marker_preg = '@\*@';
+ $required_marker_preg = '@\*\s*?@';
// Go through all the elements and all the empty values for them.
foreach ($elements as $type => $data) {
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 2c51ae0..e6e7bc7 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -299,7 +299,7 @@ function system_element_info() {
'#limit_validation_errors' => FALSE,
'#process' => array('form_process_button', 'ajax_process_form'),
'#pre_render' => array('form_pre_render_button'),
- '#theme_wrappers' => array('input__submit'),
+ '#theme' => 'input__submit',
);
$types['button'] = array(
'#input' => TRUE,
@@ -309,7 +309,7 @@ function system_element_info() {
'#limit_validation_errors' => FALSE,
'#process' => array('form_process_button', 'ajax_process_form'),
'#pre_render' => array('form_pre_render_button'),
- '#theme_wrappers' => array('input__button'),
+ '#theme' => 'input__button',
);
$types['image_button'] = array(
'#input' => TRUE,
@@ -321,7 +321,7 @@ function system_element_info() {
'#has_garbage_value' => TRUE,
'#src' => NULL,
'#pre_render' => array('form_pre_render_image_button'),
- '#theme_wrappers' => array('input__image_button'),
+ '#theme' => 'input__image_button',
);
$types['textfield'] = array(
'#input' => TRUE,
@@ -490,7 +490,8 @@ function system_element_info() {
);
$types['date'] = array(
'#input' => TRUE,
- '#theme' => 'date',
+ '#theme' => 'input__date',
+ '#pre_render' => array('form_pre_render_date'),
'#theme_wrappers' => array('form_element'),
);
$types['file'] = array(
@@ -504,10 +505,11 @@ function system_element_info() {
'#input' => TRUE,
'#js_select' => TRUE,
'#multiple' => TRUE,
+ '#pre_render' => array('form_pre_render_tableselect'),
'#process' => array('form_process_tableselect'),
'#options' => array(),
'#empty' => '',
- '#theme' => 'tableselect',
+ '#theme' => 'table__tableselect',
);
// Form structure.
diff --git a/core/modules/system/templates/checkboxes.html.twig b/core/modules/system/templates/checkboxes.html.twig
new file mode 100644
index 0000000..eda7291
--- /dev/null
+++ b/core/modules/system/templates/checkboxes.html.twig
@@ -0,0 +1,18 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a 'checkboxes' #type form element.
+ *
+ * Available variables
+ * - attributes: HTML attributes for the checkboxes wrapper element.
+ * - children: HTML markup for the child checkboxes.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_checkboxes()
+ *
+ * @ingroup themeable
+ */
+ @todo: remove this file once http://drupal.org/node/1819284 is resolved.
+ This is identical to core/themes/stark/templates/form.inc/container.html.twig
+#}
+
{{ children }}
diff --git a/core/modules/system/templates/container.html.twig b/core/modules/system/templates/container.html.twig
new file mode 100644
index 0000000..9d4446e
--- /dev/null
+++ b/core/modules/system/templates/container.html.twig
@@ -0,0 +1,16 @@
+{#
+/**
+ * @file
+ * Default theme implementation of a container used to wrap child elements.
+ *
+ * Available variables:
+ * - attributes: Remaining html attributes for the containing element.
+ * - children: The rendered child elements of the container.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_container()
+ *
+ * @ingroup themeable
+ */
+#}
+
{{ children }}
diff --git a/core/modules/system/templates/datetime.html.twig b/core/modules/system/templates/datetime.html.twig
index 5ea386e..f811f56 100644
--- a/core/modules/system/templates/datetime.html.twig
+++ b/core/modules/system/templates/datetime.html.twig
@@ -1,6 +1,7 @@
{#
/**
- * Returns HTML for a date / time.
+ * @file
+ * Default theme implementation for a date / time element.
*
* Available variables
* - timestamp: (optional) A UNIX timestamp for the datetime attribute. If the
@@ -25,4 +26,4 @@
*/
#}
{# @todo Revisit once http://drupal.org/node/1825952 is resolved. #}
-
+
diff --git a/core/modules/system/templates/details.html.twig b/core/modules/system/templates/details.html.twig
new file mode 100644
index 0000000..2aa10b8
--- /dev/null
+++ b/core/modules/system/templates/details.html.twig
@@ -0,0 +1,34 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a details element.
+ *
+ * Available variables
+ * - attributes: An array of HTML attributes for the details element.
+ * - title: The title of the element, or NULL if not set.
+ * - description: The description of the element, or NULL if not set.
+ * - children: The children of the element, or NULL if not set.
+ * - value: The value of the element, or NULL if not set.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_details()
+ *
+ * @ingroup themeable
+ */
+#}
+
+ {% if title %}
+ {{ title }}
+ {% endif %}
+
+ {% if description %}
+
{{ description }}
+ {% endif %}
+ {% if children %}
+ {{ children }}
+ {% endif %}
+ {% if value %}
+ {{ value }}
+ {% endif %}
+
+
diff --git a/core/modules/system/templates/fieldset.html.twig b/core/modules/system/templates/fieldset.html.twig
new file mode 100644
index 0000000..0a3f895
--- /dev/null
+++ b/core/modules/system/templates/fieldset.html.twig
@@ -0,0 +1,36 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a fieldset element and its children.
+ *
+ * Available variables:
+ * - attributes: An array of HTML attributes for the fieldset element.
+ * - title: Title of the fieldset, intended for use as the text of the legend.
+ * - title_attributes: An array of HTML attributes to apply to the legend.
+ * - description: The description of the fieldset.
+ * - description_attributes: An array of HTML attributes to apply to the
+ * description container.
+ * - children: The rendered child elements of the fieldset.
+ * - value: The value of the fieldset.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_fieldset()
+ *
+ * @ingroup themeable
+ */
+#}
+
diff --git a/core/modules/system/templates/form-element-label.html.twig b/core/modules/system/templates/form-element-label.html.twig
new file mode 100644
index 0000000..9acee29
--- /dev/null
+++ b/core/modules/system/templates/form-element-label.html.twig
@@ -0,0 +1,29 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a form element label.
+ *
+ * Available variables:
+ * - label: The text of the label, or FALSE if there is no title and the element
+ * is not required.
+ * - required: A rendered marker indicating the field is required, or
+ * an empty string if the field is not required.
+ * - attributes: An array of HTML attributes to apply to the label.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_form_label()
+ * @see form-required-marker.html.twig
+ *
+ * @ingroup themeable
+ */
+#}
+{% if (label is not empty) or (required is not empty) %}
+
+{% endif %}
diff --git a/core/modules/system/templates/form-element.html.twig b/core/modules/system/templates/form-element.html.twig
new file mode 100644
index 0000000..bb07a5e
--- /dev/null
+++ b/core/modules/system/templates/form-element.html.twig
@@ -0,0 +1,58 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a form element.
+ *
+ * Available variables:
+ * - wrapper_attributes: An array of HTML attributes to apply to the wrapper.
+ * - prefix: The form element prefix, or NULL.
+ * - suffix: The form element suffix, or NULL.
+ * - label: The rendered label. @see form-element-label.html.twig.
+ * - label_display: Label display setting. It can have these values:
+ * - before: The label is output before the element. This is the default. The
+ * label includes the #title and the required marker, if #required.
+ * - after: The label is output after the element. For example, this is used
+ * for radio and checkbox #type elements as set in system_element_info().
+ * If the #title is empty but the field is #required, the label will
+ * contain only the required marker.
+ * - invisible: Labels are critical for screen readers to enable them to
+ * properly navigate through forms but can be visually distracting. This
+ * property hides the label for everyone except screen readers.
+ * - attribute: Set the title attribute on the element to create a tooltip
+ * but output no label element. This is supported only for checkboxes and
+ * radios in form_pre_render_conditional_form_element(). It is used where
+ * a visual label is not needed, such as a table of checkboxes where the
+ * row and column provide the context. The tooltip will include the title
+ * and required marker.
+ * - description: A description of the form element, or NULL if not set.
+ * - description_attributes: An array of HTML attributes to apply to the wrapper
+ * of the description. Will only be set when description is not NULL.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_form_element()
+ *
+ * @ingroup themeable
+ */
+#}
+
+ {% if (label is not empty) and (label_display in ['before', 'invisible']) %}
+ {{ label }}
+ {% endif %}
+ {% if prefix is not empty %}
+ {{ prefix }}
+ {% endif %}
+ {% if children is not empty %}
+ {{ children }}
+ {% endif %}
+ {% if suffix is not empty %}
+ {{ suffix }}
+ {% endif %}
+ {% if (label is not empty) and (label_display == 'after') %}
+ {{ label }}
+ {% endif %}
+ {% if description is not empty %}
+
+ {{ description }}
+
+ {% endif %}
+
diff --git a/core/modules/system/templates/form-required-marker.html.twig b/core/modules/system/templates/form-required-marker.html.twig
new file mode 100644
index 0000000..2c26446
--- /dev/null
+++ b/core/modules/system/templates/form-required-marker.html.twig
@@ -0,0 +1,15 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a form element required marker.
+ *
+ * Available variables:
+ * - attributes: An array of HTML attributes for the label.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_form_required_marker()
+ *
+ * @ingroup themeable
+ */
+#}
+*
diff --git a/core/modules/system/templates/form.html.twig b/core/modules/system/templates/form.html.twig
new file mode 100644
index 0000000..71fb632
--- /dev/null
+++ b/core/modules/system/templates/form.html.twig
@@ -0,0 +1,19 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a form.
+ *
+ * Available variables:
+ * - attributes: An array of HTML attributes for the form element.
+ * - children: Rendered child form elements.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_form()
+ *
+ * @ingroup themeable
+ */
+ @todo: remove the inner div once http://drupal.org/node/1822210 is resolved.
+#}
+
diff --git a/core/modules/system/templates/input.html.twig b/core/modules/system/templates/input.html.twig
new file mode 100644
index 0000000..7e3b5a8
--- /dev/null
+++ b/core/modules/system/templates/input.html.twig
@@ -0,0 +1,34 @@
+{#
+/**
+ * @file
+ * Default theme implementation for an input element.
+ *
+ * This covers input types:
+ * - button
+ * - checkbox
+ * - date
+ * - email
+ * - file
+ * - hidden
+ * - image_button
+ * - number
+ * - radio
+ * - range
+ * - password
+ * - tel
+ * - textfield
+ *
+ * Available variables:
+ * - attributes: An array of HTML attributes for the input element.
+ * - children: An array of child elements.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_input()
+ *
+ * @ingroup themeable
+ */
+#}
+
+{% if children is not empty %}
+ {{ children }}
+{% endif %}
diff --git a/core/modules/system/templates/radios.html.twig b/core/modules/system/templates/radios.html.twig
new file mode 100644
index 0000000..4e44796
--- /dev/null
+++ b/core/modules/system/templates/radios.html.twig
@@ -0,0 +1,18 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a #type 'radios' form element.
+ *
+ * Available variables:
+ * - attributes: An array of HTML attributes for the container element.
+ * - children: An array of rendered child radio elements.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_radios()
+ *
+ * @ingroup themeable
+ */
+ @todo: remove this file once http://drupal.org/node/1819284 is resolved.
+ This is identical to core/themes/stark/templates/form.inc/container.html.twig
+#}
+
{{ children }}
diff --git a/core/modules/system/templates/select.html.twig b/core/modules/system/templates/select.html.twig
new file mode 100644
index 0000000..e8c6920
--- /dev/null
+++ b/core/modules/system/templates/select.html.twig
@@ -0,0 +1,16 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a select element.
+ *
+ * Available variables:
+ * - attributes: An array of HTML attributes for the select element.
+ * - options: The rendered list of select options.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_select()
+ *
+ * @ingroup themeable
+ */
+#}
+
diff --git a/core/modules/system/templates/textarea.html.twig b/core/modules/system/templates/textarea.html.twig
new file mode 100644
index 0000000..96f6aac
--- /dev/null
+++ b/core/modules/system/templates/textarea.html.twig
@@ -0,0 +1,16 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a textarea element.
+ *
+ * Available variables:
+ * - attributes: An array of HTML attributes for the textarea element.
+ * - value: Plain text value of the textarea.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_textarea()
+ *
+ * @ingroup themeable
+ */
+#}
+
diff --git a/core/modules/system/templates/vertical-tabs.html.twig b/core/modules/system/templates/vertical-tabs.html.twig
new file mode 100644
index 0000000..206081b
--- /dev/null
+++ b/core/modules/system/templates/vertical-tabs.html.twig
@@ -0,0 +1,15 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a set of vertical tabs.
+ *
+ * Available variables
+ * - children: The rendered child fieldsets elements.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_vertical_tabs()
+ *
+ * @ingroup themeable
+ */
+#}
+