diff --git a/core/misc/icons/0074bd/chevron-left.png b/core/misc/icons/0074bd/chevron-left.png
new file mode 100644
index 0000000..e42435d
--- /dev/null
+++ b/core/misc/icons/0074bd/chevron-left.png
@@ -0,0 +1,3 @@
+‰PNG
+
+
IHDR óÿa EIDATxÚÝ“Á É‘2„û8‰d´ª |5pÏË#´é‘”–'®ŒA,àÉ‚ž,p³¬nrõ‡ø§„‡/Ñÿ?µüzGæ IEND®B`‚
\ No newline at end of file
diff --git a/core/misc/icons/0074bd/chevron-left.svg b/core/misc/icons/0074bd/chevron-left.svg
new file mode 100644
index 0000000..122e1c0
--- /dev/null
+++ b/core/misc/icons/0074bd/chevron-left.svg
@@ -0,0 +1 @@
+
diff --git a/core/misc/icons/0074bd/chevron-right.png b/core/misc/icons/0074bd/chevron-right.png
new file mode 100644
index 0000000..e2ff9a9
--- /dev/null
+++ b/core/misc/icons/0074bd/chevron-right.png
@@ -0,0 +1,3 @@
+‰PNG
+
+
IHDR óÿa FIDATxÚÝ“Ë C;’#e÷qéh~P<¦H¥ß#‡V>N®i–…1ÚvÁtÁGB-ˆ#)—@Íü`·;€í^§•zG¸éç IEND®B`‚
\ No newline at end of file
diff --git a/core/misc/icons/0074bd/chevron-right.svg b/core/misc/icons/0074bd/chevron-right.svg
new file mode 100644
index 0000000..b16a8ce
--- /dev/null
+++ b/core/misc/icons/0074bd/chevron-right.svg
@@ -0,0 +1 @@
+
diff --git a/core/misc/jquery.collapse.js b/core/misc/jquery.collapse.js
new file mode 100644
index 0000000..5a21a66
--- /dev/null
+++ b/core/misc/jquery.collapse.js
@@ -0,0 +1,98 @@
+/**
+ * @file
+ */
+
+;( function( $, window, document, undefined ) {
+ 'use strict';
+
+ var pluginName = 'collapse';
+ var defaults = {
+ target: false,
+ trigger: false,
+ initState: 'closed'
+ };
+
+ function Collapse( element, options ) {
+ this.options = $.extend( {}, defaults, options );
+ this.element = element;
+ this.$element = $(element);
+ this.$target = null;
+ this.$trigger = null;
+
+ this._defaults = defaults;
+ this._name = pluginName;
+
+ this.init();
+ }
+
+ Collapse.prototype.init = function() {
+ var self = this;
+ var opts = self.options;
+
+ if (opts.target) {
+ if ( opts.target.jquery ) {
+ this.$target = opts.target;
+ } else {
+ this.$target = this.$element.withinOrUnique(opts.target);
+ }
+ }
+
+ if (opts.trigger) {
+ if ( opts.trigger.jquery ) {
+ this.$trigger = opts.trigger;
+ } else {
+ this.$trigger = this.$element.withinOrUnique(opts.trigger);
+ }
+ } else {
+ this.$trigger = this.$element;
+ }
+
+ this.refresh();
+
+ if (this.options.initState !== 'closed') {
+ this.$target.addClass('is-open');
+ }
+
+ this.$trigger.on('click', function(event) {
+ self.toggle(event);
+ });
+
+ this.$element.on('transitionend webkitTransitionEnd', function() {
+ if ( self.$target.hasClass('is-closing') ) {
+ self.$target.removeClass('is-closing is-open');
+ self.$target[0].style.removeProperty('max-height');
+ }
+ });
+ };
+
+ Collapse.prototype.refresh = function() {
+ this.$target.data( 'intrinsicHeight', this.$target.intrinsic('height') + 'px' );
+ };
+
+ Collapse.prototype.toggle = function(event) {
+ event.preventDefault();
+
+ if ( this.$target.hasClass('is-open') ) {
+ if ( Modernizr.csstransitions ) {
+ this.$target.css('max-height', '0').addClass('is-closing');
+ }
+ else {
+ this.$target.removeClass('is-open');
+ }
+ } else {
+ if ( Modernizr.csstransitions ) {
+ this.$target.css( 'max-height', this.$target.data('intrinsicHeight') );
+ }
+ this.$target.addClass('is-open');
+ }
+ };
+
+ $.fn[pluginName] = function( options ) {
+ return this.each( function() {
+ if ( ! $.data(this, 'plugin_' + pluginName) ) {
+ $.data( this, 'plugin_' + pluginName, new Collapse(this, options) );
+ }
+ });
+ };
+
+})( jQuery, window, document );
diff --git a/core/misc/jquery.dom-utils.js b/core/misc/jquery.dom-utils.js
new file mode 100644
index 0000000..641006b
--- /dev/null
+++ b/core/misc/jquery.dom-utils.js
@@ -0,0 +1,59 @@
+/**
+ * @file
+ * Lowish-level DOM utilities for UI components
+ */
+;( function( $, w, undefined ) {
+ 'use strict';
+
+ // Find a given selector only within the current scope, except ids, which
+ // are found anywhere.
+ $.fn.withinOrUnique = function(selector) {
+ if ( selector.charAt(0) === '#' ) {
+ return $(selector);
+ } else {
+ return this.find(selector);
+ }
+ };
+
+ $.extend({
+ kebabCase: function(string) {
+ return string.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
+ },
+
+ safeTrim: function(object) {
+ if (typeof object === 'string') {
+ return $.trim(object);
+ }
+ return object;
+ }
+ });
+
+ // Parse options passed via data-attribute component initialization and
+ // turn them into an object.
+ $.fn.dataOptions = function(pluginName, namespace) {
+ var options = {};
+ var optPair;
+ var key;
+ var value;
+ var dataPrefix = 'data-' + ( typeof namespace === 'string' ? namespace + '-' : '' );
+ var optionsArray = ($(this).attr(dataPrefix + $.kebabCase(pluginName)) || ':').split(';');
+
+ // parse options
+ for (var i = optionsArray.length - 1; i >= 0; i--) {
+ optPair = optionsArray[i].split(':');
+ key = optPair[0];
+ value = optPair[1];
+
+ if (/true/i.test(value)) { value = true; }
+ if (/false/i.test(value)) { value = false; }
+ if ($.isNumeric(value)) { value = parseFloat(value); }
+
+ if (optPair.length === 2 && key.length > 0) {
+ options[$.safeTrim(key)] = $.safeTrim(value);
+ }
+ }
+
+ return options;
+ };
+
+})( jQuery, window );
diff --git a/core/misc/jquery.intrinsic.js b/core/misc/jquery.intrinsic.js
new file mode 100644
index 0000000..e05beaf
--- /dev/null
+++ b/core/misc/jquery.intrinsic.js
@@ -0,0 +1,51 @@
+/**
+ * @file
+ * Measure an element’s intrinsic width or height when neither constrained by
+ * a container nor forced full width as in 'display: block'.
+ */
+(function ($) {
+ 'use strict';
+
+ // Style block applied momentarily in order to measure the element.
+ //
+ // 1. Shrink-wrap the element. Block display would give us the width of the
+ // container, not the element’s intrinsic width.
+ // 2. Preventative measure. The styles should be reverted before the browser’s
+ // UI thread updates.
+ //
+ // We avoid 'position: absolute' because this causes the element to wrap if
+ // it’s wider than the viewport, regardless of the width of
and .
+ //
+ var tempElementCSS = {
+ display: 'table', /* 1 */
+ visibility: 'hidden', /* 2 */
+ width: 'auto',
+ height: 'auto',
+ maxWidth: 'none',
+ maxHeight: 'none'
+ };
+
+ // Style block applied momentarily to the body in order to ensure the
+ // element’s layout area isn’t constrained.
+ //
+ var tempBodyCSS = {
+ width: '999em',
+ height: '999em'
+ };
+
+ $.fn.intrinsic = function (dimension) {
+ // The measured element may be a plain object or jQuery.
+ var element = this instanceof jQuery ? this[0] : this;
+ var measurement;
+
+ // Use jQuery’s internal swap() method to temporarily apply the styles, then
+ // measure the element’s width() or height().
+ $.swap(document.body, tempBodyCSS, function () {
+ $.swap(element, tempElementCSS, function () {
+ measurement = $(element)[dimension]();
+ });
+ });
+
+ return measurement;
+ };
+})(jQuery);
diff --git a/core/misc/jquery.nav-tabs.js b/core/misc/jquery.nav-tabs.js
new file mode 100644
index 0000000..9d0f21d
--- /dev/null
+++ b/core/misc/jquery.nav-tabs.js
@@ -0,0 +1,70 @@
+/**
+ * @file
+ */
+
+;( function( $, window, document, undefined ) {
+ 'use strict';
+
+ var pluginName = 'navTabs';
+ var defaults = {
+ target: '.js-nav-tabs__target',
+ trigger: '.js-nav-tabs__trigger',
+ collapsible: false
+ };
+
+ function NavTabs( element, dataOptions, options ) {
+ this.options = $.extend( {}, defaults, dataOptions, options );
+ this.element = element;
+ this.$element = $(element);
+
+ this._defaults = defaults;
+ this._name = pluginName;
+
+ this.init();
+ }
+
+ NavTabs.prototype.init = function() {
+
+ if (this.options.collapsible) {
+ this.$element.collapse({
+ target: this.options.target,
+ trigger: this.options.trigger
+ });
+ this.$element.addClass('is-collapse-enabled');
+ }
+
+ $(window).on('resize.navTabs', $.proxy(this, 'refresh'));
+
+ this.$element.addClass('position-container is-horizontal-enabled');
+ this.refreshAll();
+ };
+
+ NavTabs.prototype.refreshAll = function() {
+ this.intrinsicWidth = this.$element.addClass('is-horizontal').intrinsic('width');
+ this.$element.removeClass('is-horizontal');
+ this.refresh();
+ };
+
+ NavTabs.prototype.refresh = function() {
+ if ( this.$element.parent().width() > this.intrinsicWidth ) {
+ this.$element.addClass('is-horizontal');
+ } else {
+ this.$element.removeClass('is-horizontal');
+ }
+ };
+
+ NavTabs.prototype.destroy = function() {
+ window.off('resize.navTabs');
+ this.removeData('plugin_' + pluginName);
+ };
+
+ $.fn[pluginName] = function( options ) {
+ return this.each( function() {
+ if ( ! $.data(this, 'plugin_' + pluginName) ) {
+ var dataOptions = $(this).dataOptions(pluginName, 'drupal');
+ $.data( this, 'plugin_' + pluginName, new NavTabs(this, dataOptions, options) );
+ }
+ });
+ };
+
+})( jQuery, window, document );
diff --git a/core/modules/system/css/system.module.css b/core/modules/system/css/system.module.css
index ef4cfae..f951dc1 100644
--- a/core/modules/system/css/system.module.css
+++ b/core/modules/system/css/system.module.css
@@ -349,3 +349,24 @@ tr .ajax-progress-throbber .throbber {
.align-justify {
text-align: justify;
}
+
+/*
+ * Remove browser styles, especially for and so on.
+ */
+.reset-appearance {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ border: 0 none;
+ background: transparent;
+ padding: 0;
+ margin: 0;
+ line-height: inherit;
+}
+
+/*
+ * Contain positioned elements.
+ */
+.position-container {
+ position: relative;
+}
diff --git a/core/modules/system/css/system.theme.css b/core/modules/system/css/system.theme.css
index 6b34538..0f2b297 100644
--- a/core/modules/system/css/system.theme.css
+++ b/core/modules/system/css/system.theme.css
@@ -438,15 +438,12 @@ ul.inline li {
/**
* Markup generated by theme_menu_local_tasks().
*/
-div.tabs {
- margin: 1em 0;
-}
-ul.tabs {
+.tabs {
list-style: none;
margin: 0 0 0.5em;
padding: 0;
}
-.tabs > li {
+.tabs__tab {
display: inline-block;
margin-right: 0.3em; /* LTR */
}
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index ee3466d..715a61f 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -1179,6 +1179,18 @@ function system_library_info() {
),
);
+ // jQuery Intrinsic Measurements.
+ $libraries['jquery.intrinsic'] = array(
+ 'title' => 'Instric Measurements',
+ 'version' => '1.0',
+ 'js' => array(
+ 'core/misc/jquery.intrinsic.js' => array(),
+ ),
+ 'dependencies' => array(
+ array('system', 'jquery'),
+ ),
+ );
+
// jQuery Form Plugin.
$libraries['jquery.form'] = array(
'title' => 'jQuery Form Plugin',
diff --git a/core/modules/views_ui/css/views_ui.admin.theme.css b/core/modules/views_ui/css/views_ui.admin.theme.css
index 9a71196..6968515 100644
--- a/core/modules/views_ui/css/views_ui.admin.theme.css
+++ b/core/modules/views_ui/css/views_ui.admin.theme.css
@@ -448,20 +448,30 @@ td.group-title {
* The tabs that switch between sections
*/
-ul#views-display-menu-tabs {
+.views-displays .tabs.secondary {
margin-right: 200px;
+ border: 0;
}
-ul#views-display-menu-tabs li {
+.views-displays .tabs.secondary li {
+ background: transparent;
margin-bottom: 5px;
+ border: 0;
+ padding: 0;
+ width: auto;
}
-ul#views-display-menu-tabs li.add ul.action-list li{
+.views-displays .tabs.secondary li.add ul.action-list li{
margin: 0;
}
-.views-displays .secondary a {
+.views-displays .tabs.secondary li {
+ margin: 0 5px 0 6px;
+}
+
+.views-displays .tabs.secondary a {
border: 1px solid #cbcbcb;
+ border-radius: 7px;
display: inline-block;
font-size: small;
line-height: 1.3333;
@@ -471,65 +481,66 @@ ul#views-display-menu-tabs li.add ul.action-list li{
/**
* Display a red border if the display doesn't validate.
*/
-.views-displays ul.secondary li.active a.active.error,
-.views-displays .secondary a.error {
+.views-displays .tabs.secondary li.active a.active.error,
+.views-displays .tabs.secondary a.error {
border: 2px solid #ed541d;
padding: 1px 6px;
}
-.views-displays .secondary a:focus {
+.views-displays .tabs.secondary a:focus {
outline: none;
}
-.views-displays ul.secondary li a {
+.views-displays .tabs.secondary li a {
background-color: #fff;
}
-.views-displays ul.secondary li a:hover,
-.views-displays ul.secondary li.active a,
-.views-displays ul.secondary li.active a.active {
+.views-displays .tabs.secondary li a:hover,
+.views-displays .tabs.secondary li.active a,
+.views-displays .tabs.secondary li.active a.active {
background-color: #555;
color: #fff;
}
-.views-displays .secondary .open > a {
+.views-displays .tabs.secondary .open > a {
background-color: #f1f1f1;
border-bottom: 1px solid transparent;
position: relative;
}
-.views-displays .secondary .open > a:hover {
+.views-displays .tabs.secondary .open > a:hover {
background-color: #f1f1f1;
}
-.views-displays .secondary .action-list li {
+.views-displays .tabs.secondary .action-list li {
background-color: #f1f1f1;
border-color: #cbcbcb;
border-style: solid;
border-width: 0 1px;
padding: 2px 9px;
+
}
-.views-displays .secondary .action-list li:first-child {
+.views-displays .tabs.secondary .action-list li:first-child {
border-width: 1px 1px 0;
}
-.views-displays .secondary .action-list li.last {
+.views-displays .tabs.secondary .action-list li.last {
border-width: 0 1px 1px;
}
-.views-displays .secondary .action-list li:last-child {
+.views-displays .tabs.secondary .action-list li:last-child {
border-width: 0 1px 1px;
}
-.views-displays .secondary .action-list input.form-submit {
+.views-displays .tabs.secondary .action-list input.form-submit {
background: none repeat scroll 0 0 transparent;
border: medium none;
margin: 0;
padding: 0;
}
-.views-displays .secondary .action-list li:hover {
+.views-displays .tabs.secondary .action-list li:hover {
background-color: #ddd;
}
diff --git a/core/themes/seven/install-page.css b/core/themes/seven/install-page.css
index 7533636..b79ebbc 100644
--- a/core/themes/seven/install-page.css
+++ b/core/themes/seven/install-page.css
@@ -46,6 +46,7 @@ body.install-page {
width: 75%;
border-radius: 5px;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
+ padding: 20px 0 40px 0;
}
body.install-page #content {
-webkit-box-sizing: border-box;
diff --git a/core/themes/seven/js/nav-tabs.js b/core/themes/seven/js/nav-tabs.js
new file mode 100644
index 0000000..9d73b37
--- /dev/null
+++ b/core/themes/seven/js/nav-tabs.js
@@ -0,0 +1,50 @@
+/**
+ * @file
+ */
+(function ($, Drupal) {
+
+ "use strict";
+
+ function init (i, tab) {
+ var $tab = $(tab);
+ var $target = $tab.find('[data-drupal-nav-tabs-target]');
+ var isCollapsible = $tab.hasClass('is-collapsible');
+
+ function openMenu (e) {
+ $target.toggleClass('is-open');
+ }
+
+ function handleResize (e) {
+ $tab.addClass('is-horizontal');
+ var isHorizontal = $tab.parent().width() > $tab.intrinsic('width');
+ $tab.toggleClass('is-horizontal', isHorizontal);
+ if(isCollapsible) {
+ $tab.toggleClass('is-collapse-enabled', !isHorizontal);
+ }
+ if (isHorizontal) {
+ $target.removeClass('is-open');
+ }
+ }
+
+ $tab.addClass('position-container is-horizontal-enabled');
+
+ $tab.on('click.tabs', '[data-drupal-nav-tabs-trigger]', openMenu);
+ $(window).on('resize.tabs', Drupal.debounce(handleResize)).trigger('resize.tabs');
+ }
+
+ /**
+ * Initialise the tabs JS.
+ */
+ Drupal.behaviors.navTabs = {
+ attach: function (context, settings) {
+ var $tabs = $(context).find('[data-drupal-nav-tabs]');
+ if ($tabs.length) {
+ var notSmartPhone = window.matchMedia('(min-width: 300px)');
+ if (notSmartPhone.matches) {
+ $tabs.once('nav-tabs').each(init);
+ }
+ }
+ }
+ };
+
+})(jQuery, Drupal);
diff --git a/core/themes/seven/seven.theme b/core/themes/seven/seven.theme
index 7defd49..7718f11 100644
--- a/core/themes/seven/seven.theme
+++ b/core/themes/seven/seven.theme
@@ -6,6 +6,7 @@
*/
use Drupal\Core\Template\RenderWrapper;
+use Drupal\Component\Utility\String;
/**
* Implements hook_library_info().
@@ -27,6 +28,19 @@ function seven_library_info() {
),
);
+ $libraries['drupal.nav-tabs'] = array(
+ 'version' => \Drupal::VERSION,
+ 'js' => array(
+ drupal_get_path('theme', 'seven') . '/js/nav-tabs.js' => array('group' => JS_THEME),
+ ),
+ 'dependencies' => array(
+ array('system', 'jquery'),
+ array('system', 'drupal'),
+ array('system', 'jquery.once'),
+ array('system', 'jquery.intrinsic'),
+ ),
+ );
+
return $libraries;
}
@@ -48,12 +62,82 @@ function seven_preprocess_html(&$variables) {
* Implements hook_preprocess_HOOK() for page templates.
*/
function seven_preprocess_page(&$variables) {
- $variables['primary_local_tasks'] = $variables['tabs'];
- unset($variables['primary_local_tasks']['#secondary']);
- $variables['secondary_local_tasks'] = array(
- '#theme' => 'menu_local_tasks',
- '#secondary' => isset($variables['tabs']['#secondary']) ? $variables['tabs']['#secondary'] : '',
+ if (isset($variables['tabs'])) {
+ $variables['primary_local_tasks'] = $variables['tabs'];
+ unset($variables['primary_local_tasks']['#secondary']);
+ $variables['secondary_local_tasks'] = array(
+ '#theme' => 'menu_local_tasks',
+ '#secondary' => isset($variables['tabs']['#secondary']) ? $variables['tabs']['#secondary'] : '',
+ );
+ }
+}
+
+/**
+ * Overrides theme_menu_local_tasks().
+ *
+ * Returns HTML for primary and secondary local tasks.
+ *
+ **/
+function seven_menu_local_tasks(&$variables) {
+ $output = '';
+
+ if (!empty($variables['primary'])) {
+ drupal_add_library('seven', 'drupal.nav-tabs', FALSE);
+ $variables['primary']['#prefix'] = '' . t('Primary tabs') . '
';
+ $variables['primary']['#prefix'] .= '';
+ $output .= drupal_render($variables['primary']);
+ }
+ if (!empty($variables['secondary'])) {
+ drupal_add_library('seven', 'drupal.nav-tabs', FALSE);
+ $variables['secondary']['#prefix'] = '' . t('Secondary tabs') . '
';
+ $variables['secondary']['#prefix'] .= '';
+ $output .= drupal_render($variables['secondary']);
+ }
+
+ return $output;
+}
+
+/**
+ * Overrides theme_menu_local_task().
+ *
+ * Returns HTML for a local task.
+ *
+ **/
+function seven_menu_local_task($variables) {
+ $link = $variables['element']['#link'];
+ $link += array(
+ 'localized_options' => array(),
);
+ $link_text = $link['title'];
+
+ if (!empty($variables['element']['#active'])) {
+ // Add text to indicate active tab for non-visual users.
+ $active = '' . t('(active tab)') . '';
+
+ // If the link does not contain HTML already, String::checkPlain() it now.
+ // After we set 'html'=TRUE the link will not be sanitized by l().
+ if (empty($link['localized_options']['html'])) {
+ $link['title'] = String::checkPlain($link['title']);
+ }
+ $link['localized_options']['html'] = TRUE;
+ $link_text = t('!local-task-title!active', array('!local-task-title' => $link['title'], '!active' => $active));
+ }
+ if (!empty($link['href'])) {
+ // @todo - remove this once all pages are converted to routes.
+ $a_tag = l($link_text, $link['href'], $link['localized_options']);
+ }
+ else {
+ $a_tag = \Drupal::l($link_text, $link['route_name'], $link['route_parameters'], $link['localized_options']);
+ }
+
+ return '' . $a_tag . '';
}
/**
diff --git a/core/themes/seven/style.css b/core/themes/seven/style.css
index 5fc9df1..81a33dd 100644
--- a/core/themes/seven/style.css
+++ b/core/themes/seven/style.css
@@ -198,7 +198,7 @@ pre {
#branding {
overflow: hidden;
background-color: #e0e0d8;
- padding: 24px 0 12px;
+ padding: 24px 0 0;
}
/* This layout styling is a copy of #page.
* @TODO: Replace with reuseable layout classes.
@@ -219,7 +219,7 @@ pre {
.breadcrumb {
font-size: 0.846em;
line-height: 1em;
- padding: 0 0 10px 0;
+ padding: 20px 0 10px 0;
}
/**
@@ -267,151 +267,284 @@ pre {
/**
* Tabs.
*/
-ul.primary {
- float: right; /* LTR */
- border-bottom: none;
- text-transform: uppercase;
- font-size: 0.923em;
- margin: 0;
- padding-top: 0;
-}
-[dir="rtl"] ul.primary {
- float: left;
+.is-collapse-enabled .tabs,
+.is-horizontal .tabs {
+ position: relative;
}
-ul.primary li {
- float: left; /* LTR */
- list-style: none;
- height: 2.60em;
- margin: 0 2px;
+.is-collapse-enabled .tabs:before,
+.is-horizontal .tabs:before {
+ content: '';
+ display: block;
+ background-color: #A6A6A6;
+ height: 1px;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ z-index: 10;
+ right: 0;
}
-[dir="rtl"] ul.primary li {
- float: right;
+
+/* Span the full width of the viewport */
+.branding__inner .is-horizontal .tabs:before,
+.branding__inner .is-collapse-enabled .tabs:before {
+ left: -2.5em;
+ right: -2.5em;
}
-ul.primary li a:link,
-ul.primary li a.active,
-ul.primary li a:active,
-ul.primary li a:visited,
-ul.primary li a:hover,
-ul.primary li.active a {
+
+/**
+ * Tab
+ *
+ * 1. Required by some elements such as