diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index 8677c72..42c049b 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -734,24 +734,25 @@ function shortcut_toolbar() { ); } - $links_tray = array( - '#heading' => t('User-defined shortcuts'), - 'shortcuts' => $links, - 'configure' => $configure_link, - ); - $items['shortcuts'] = array( - 'tab' => array( - 'title' => t('Shortcuts'), - 'href' => 'admin/config/user-interface/shortcut', + "#theme_wrappers" => array('toolbar_tab_wrapper'), + '#theme' => 'toolbar_tray_toggle', + '#text' => t('Shortcuts'), + '#path' => 'admin/config/user-interface/shortcut', + '#options' => array( 'html' => FALSE, 'attributes' => array( 'title' => t('Shortcuts'), 'class' => array('icon', 'icon-shortcut'), ), ), - 'tray' => $links_tray, - 'weight' => -10, + '#tray' => array( + '#theme_wrappers' => array('toolbar_tray_wrapper'), + '#heading' => t('User-defined shortcuts'), + 'shortcuts' => $links, + 'configure' => $configure_link, + ), + '#weight' => -10, ); return $items; } diff --git a/core/modules/toolbar/css/toolbar.base.css b/core/modules/toolbar/css/toolbar.base.css index cbdf153..1dc640b 100644 --- a/core/modules/toolbar/css/toolbar.base.css +++ b/core/modules/toolbar/css/toolbar.base.css @@ -43,8 +43,8 @@ html.js .toolbar { .js .toolbar .menu li { display: block; } -.js .toolbar .bar li, -.js .toolbar .horizontal li { +.js .toolbar .bar .tab, +.js .toolbar .horizontal .tab { float: left; /* LTR */ } .js .toolbar a { diff --git a/core/modules/toolbar/js/toolbar.js b/core/modules/toolbar/js/toolbar.js index 08a68d2..cd97b1d 100644 --- a/core/modules/toolbar/js/toolbar.js +++ b/core/modules/toolbar/js/toolbar.js @@ -78,7 +78,7 @@ Drupal.behaviors.toolbar = { // query application decide the orientation. changeOrientation((locked) ? 'vertical' : ((mql.wide.matches) ? 'horizontal' : 'vertical'), locked); // Render the main menu as a nested, collapsible accordion. - $toolbar.find('.administration.tray .toolbar-menu > .menu').toolbarMenu(); + $toolbar.find('.tray-administration .toolbar-menu > .menu').toolbarMenu(); // Call setHeight on screen resize. Wrap it in debounce to prevent // setHeight from being called too frequently. var setHeight = Drupal.debounce(Drupal.toolbar.setHeight, 200); diff --git a/core/modules/toolbar/templates/toolbar.twig b/core/modules/toolbar/templates/toolbar.twig index c2181df..2e52bd2 100644 --- a/core/modules/toolbar/templates/toolbar.twig +++ b/core/modules/toolbar/templates/toolbar.twig @@ -5,16 +5,15 @@ * * Available variables: * - * - tabs: Themed links for the top level tabs. - * - trays: An array of trays. It contains: - * - content: The themed tray content. - * - attributes: HTML attributes for the surrounding element. It includes: - * - id: The unique id of the tray. This corresponds to the module name - * registered the tray. - * - class: A list of classes to target the trays for styling. * - attributes: HTML attributes for the surrounding element. It includes: * - id: The unique id of the toolbar. * - class: A list of classes to target the toolbar for styling. + * - bar: Administration bar meta data and renderable content. It includes: + * - attributes: HTML attributes for the surrounding element. It includes: + * - id: The unique id of the bar. + * - class: A list of classes to target the bar for styling. + * - items: An array of renderable content. + * - trays: An array of renderable content. * * @see template_preprocess() * @see template_preprocess_toolbar() @@ -24,16 +23,11 @@ #} diff --git a/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module b/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module index cadddc9..63497c5 100644 --- a/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module +++ b/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module @@ -6,34 +6,36 @@ */ /** - * Um + * Implements hook_toolbar(). */ function toolbar_test_toolbar() { - $tray_items = array( - l('link 1', ''), - l('link 2', ''), - l('link 3', ''), - ); $items['testing'] = array( - 'tab' => array( - 'title' => t('Test tab'), - 'href' => '', + "#theme_wrappers" => array('toolbar_tab_wrapper'), + '#theme' => 'toolbar_tray_toggle', + '#text' => t('Test tab'), + '#path' => '', + '#options' => array( 'html' => FALSE, 'attributes' => array( 'title' => t('Test tab'), ), ), - 'tray' => array( + '#tray' => array( '#heading' => t('Test tray'), + '#theme_wrappers' => array('toolbar_tray_wrapper'), 'content' => array( '#theme' => 'item_list', - '#items' => $tray_items, + '#items' => array( + l(t('link 1'), ''), + l(t('link 2'), ''), + l(t('link 3'), ''), + ), '#attributes' => array( 'class' => array('menu'), ), ), ), - 'weight' => 50, + '#weight' => 50, ); return $items; diff --git a/core/modules/toolbar/toolbar.api.php b/core/modules/toolbar/toolbar.api.php index 42ca3fe..4abbdb2 100644 --- a/core/modules/toolbar/toolbar.api.php +++ b/core/modules/toolbar/toolbar.api.php @@ -2,7 +2,7 @@ /** * @file - * Hooks provided by the Toolbar module. + * Hooks provided by the toolbar module. */ /** @@ -11,30 +11,42 @@ */ /** - * Add items to the Toolbar menu. + * Add items to the toolbar menu. * - * The Toolbar has two parts. The tabs are menu links, rendered by - * theme_links(), that are displayed if the module is enabled and the user has - * the 'access toolbar' permission. The trays are render elements, usually lists - * of links, and each tray corresponds to a tab. When a tab is activated, the - * corresponding tray is displayed; only one tab can be activated at a time. If - * a tab does not have a corresponding tray, or if javascript is disabled, then - * the tab is simply a link. + * The toolbar is a container for adminstrative and site-global interactive + * components. + * + * The toolbar provides a common styling for items denoted by the .tab class. + * The theme wrapper toolbar_tab_wrapper is provided to wrap a toolbar item + * with the appropriate markup to apply the styling. + * + * The toolbar provides a construct called a 'tray'. The tray is a container + * for content. The tray may be associated with a toggle in the adminstration + * bar. The toggle shows or hides the tray and is optimized for small and + * large screens. To create this association, theme the toolbar item with + * toolbar_tray_toggle and apply the toolbar_tray_wrapper theme wrapper to + * the content in the tray. + * + * The following properties are available: + * - '#tray': Optional. A render element. Apply the theme wrapper + * toolbar_tray_wrapper for standard toolbar tray markup if needed. + * - '#weight': Optional. Integer weight used for sorting toolbar items in + * adminstration bar area. + * + * The following theme functions are available: + * - theme_toolbar_tab_wrapper: Apply for default administration bar styling. + * - theme_toolbar_tray_toggle: Use to create a link element with an + * association to a toolbar tray. + * - theme_toolbar_tray_wrapper: Apply for default toolbar tray styling. When + * the toolbar item is themed with toolbar_tray_toggle, that item will + * control the visibility of the tray. * * This hook is invoked in toolbar_view(). * * @return * An array of toolbar items, keyed by unique identifiers such as 'home' or * 'administration', or the short name of the module implementing the hook. - * The corresponding value is an associative array that may contain the - * following key-value pairs: - * - 'tab': Required, unless the item is adding links to an existing tab. An - * array with keys 'title', 'href', 'html', and 'attributes', as used by - * theme_links(). The 'href' value is ignored unless 'tray' (below) is - * omitted, or if javascript is disabled. - * - 'tray': Optional. A render element that is displayed when the tab is - * activated. - * - 'weight': Optional. Integer weight used for sorting tabs. + * The corresponding value is an associative array of renderable content. * * @see toolbar_view() * @ingroup toolbar_tabs @@ -42,51 +54,105 @@ function hook_toolbar() { $items = array(); - // The 'Home' tab is a simple link, with no corresponding tray. + // Add a search field to the toolbar. The search field employs no toolbar + // module themeing functions. + $items['global_search'] = array( + '#type' => 'search', + '#attributes' => array( + 'placeholder' => t('Search the site'), + 'class' => array('search-global'), + ), + '#weight' => 200, + // Custom CSS, JS or a library can be associated with the toolbar item. + '#attached' => array( + 'css' => array( + drupal_get_path('module', 'search') . '/css/search.base.css', + ), + ), + ); + + /** + * The 'Home' tab is a simple link, that is wrapped in markup associated + * with a visual tab styling. + */ $items['home'] = array( - 'tab' => array( - 'title' => t('Home'), - 'href' => '', + '#theme_wrappers' => array('toolbar_tab_wrapper'), + '#theme' => 'link', + '#text' => t('Home'), + '#path' => '', + '#options' => array( 'html' => FALSE, 'attributes' => array( 'title' => t('Home page'), + 'class' => array('icon', 'icon-home'), ), ), - 'weight' => -10, + '#weight' => -20, ); /** - * A tab may be associated with a tray. + * A tray may be associated with a tab. + * + * When the tab is activated, the tray will become visible, either in a + * horizontal or vertical orientation on the screen. * * The tray should contain a renderable array. An option #heading property * can be passed. The text is written to a heading tag in the tray as a - * landmark for accessibility. A default heading will be created if one is not - * passed. + * landmark for accessibility. */ $items['commerce'] = array( - 'tab' => array( - 'title' => t('Shopping cart'), - 'href' => '', + "#theme_wrappers" => array('toolbar_tab_wrapper'), + '#theme' => 'toolbar_tray_toggle', + '#text' => t('Shopping cart'), + '#path' => '/cart', + '#options' => array( 'html' => FALSE, 'attributes' => array( 'title' => t('Shopping cart'), ), ), - 'tray' => array( + '#tray' => array( + '#theme_wrappers' => array('toolbar_tray_wrapper'), '#heading' => t('Shopping cart actions'), - 'content' => array( + 'shopping_cart' => array( '#theme' => 'item_list', '#items' => array( /* An item list renderable array */ ), ), ), - 'weight' => 50, + '#weight' => 150, + ); + + /** + * The #tray can be used to render arbritrary content. + * + * A renderable array passed to the #tray property will be rendered outside + * the administration bar but within the containing toolbar element. + * + * If the default behavior and styling of a toolbar tray is not desired, one + * can render content to the toolbar element and apply custom themeing and + * behaviors. + */ + $items['user_messages'] = array( + // Include the toolbar_tab_wrapper to style the link like a toolbar tab. + // Exclude the theme wrapper if custom styling is desired. + "#theme_wrappers" => array('toolbar_tab_wrapper'), + '#text' => t('Messages'), + '#path' => '/user/messages', + '#options' => array( + 'html' => FALSE, + 'attributes' => array( + 'title' => t('Messages'), + ), + ), + '#tray' => array(/* renderable content */), + '#weight' => 125, ); return $items; } /** - * Alter the Toolbar menu after hook_toolbar() is invoked. + * Alter the toolbar menu after hook_toolbar() is invoked. * * This hook is invoked by toolbar_view() immediately after hook_toolbar(). The * toolbar definitions are passed in by reference. Each element of the $items @@ -94,11 +160,11 @@ function hook_toolbar() { * may be added, or existing items altered. * * @param $items - * Associative array of Toolbar menu definitions returned from hook_toolbar(). + * Associative array of toolbar menu definitions returned from hook_toolbar(). */ function hook_toolbar_alter(&$items) { // Move the User tab to the right. - $items['commerce']['weight'] = 5; + $items['commerce']['#weight'] = 5; } /** diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index e543326..5c497b0 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -41,9 +41,18 @@ function toolbar_permission() { */ function toolbar_theme($existing, $type, $theme, $path) { $items['toolbar'] = array( - 'render element' => 'toolbar', + 'render element' => 'elements', 'template' => 'toolbar', ); + $items['toolbar_tab_wrapper'] = array( + 'render element' => 'element', + ); + $items['toolbar_tray_toggle'] = array( + 'variables' => array('text' => NULL, 'path' => NULL, 'options' => array(), 'toolbar_identifier' => NULL), + ); + $items['toolbar_tray_wrapper'] = array( + 'render element' => 'element', + ); return $items; } @@ -150,6 +159,10 @@ function toolbar_pre_render($toolbar) { /** * Implements template_preprocess_HOOK(). + * + * The toolbar render array is built from hook_toolbar() as an array of items; + * each item has a tab and an optional tray. We need to separate the tabs from + * the trays to get the positioning to work. */ function template_preprocess_toolbar(&$variables) { // Metadata for the toolbar wrapping element. @@ -160,30 +173,130 @@ function template_preprocess_toolbar(&$variables) { // The 'overlay-displace-top' class pushes the overlay down, so it appears // below the toolbar. 'class' => array('toolbar', 'overlay-displace-top'), - 'role' => 'navigation' + 'role' => 'navigation', )); + // Provide a convenience variable for the bar. + $variables['bar'] = array( + 'items' => array(), + 'attributes' => new Attribute( + array( + 'id' => 'toolbar-bar', + 'class' => array('bar', 'overlay-displace-top', 'clearfix'), + ) + ), + ); + // Provide a convenience variable for the trays. + $variables['trays'] = array(); + // Loop through the items. Pull out trays if defined under the #tray key. + foreach($variables['elements']['#items'] as $key => $item) { + if (isset($item['#tray'])) { + $variables['trays'][$key] = $item['#tray']; + unset($item['#tray']); + } + $variables['bar']['items'][$key] = $item; + } + unset($variables['elements']['#items']); +} - // Provide a convenience variable for the themed tabs. - $variables['toolbar']['tabs']['#attributes']['class'][] = 'overlay-displace-top'; - $variables['tabs'] = $variables['toolbar']['tabs']; - - // Place the tabs in a top-level variable so that attribute information - // can be associated with each one. - foreach ($variables['toolbar']['trays'] as $key => $tray) { - // Create tray heading text. Prefer the provided heading text if it exists. - $heading = isset($tray['#heading']) ? $tray['#heading'] : t('@group actions', array('@group' => $key)); - - $variables['trays'][$key] = array( - 'heading' => $heading, - 'content' => $variables['toolbar']['trays'][$key], - 'attributes' => new Attribute(array( - 'id' => 'toolbar-tray-' . $key, - 'class' => array('tray', 'overlay-displace-top', $key), - 'data-toolbar-tray' => $key, - 'aria-owned-by' => 'toolbar-tab-' . $key, - ) - ), +/** + * Implements template_preprocess_HOOK(). + */ +function template_preprocess_toolbar_tab_wrapper(&$variables) { + if (!isset($variables['element']['#attributes'])) { + $variables['element']['#attributes'] = array(); + } + $variables['element']['#attributes']['class'][] = 'tab'; +} + +/** + * Returns HTML for wrapping a toolbar tab. + * + * Toolbar tabs have a common styling and placement with the toolbar's bar area. + * + * @param array $variables + * An associative array containing: + * - element: An associative array containing the properties and children of + * the tray. Properties used: #children and #attributes. + */ +function theme_toolbar_tab_wrapper(&$variables) { + if (!empty($variables['element']['#children'])) { + return '' . $variables['element']['#children'] . ''; + } +} + +/** + * Implements template_preprocess_HOOK(). + */ +function template_preprocess_toolbar_tray_toggle(&$variables) { + // Provide an id, a data attribute linking each tab to the corresponding + // tray and ARIA information. + if (!isset($variables['options']['attributes'])) { + $variables['options']['attributes'] = array(); + } + if (!empty($variables['toolbar_identifier'])) { + $variables['options']['attributes']['id'] = 'toolbar-tab-' . $variables['toolbar_identifier']; + $variables['options']['attributes']['data-toolbar-tray'] = $variables['toolbar_identifier']; + $variables['options']['attributes']['aria-owns'] = 'toolbar-tray-' . $variables['toolbar_identifier']; + } + $variables['options']['attributes']['role'] = 'button'; + $variables['options']['attributes']['class'][] = 'trigger'; + $variables['options']['attributes']['aria-pressed'] = 'false'; +} + +/** + * Returns HTML for toolbar tab that opens and closes a tray. + * + * Use in combination with theme_toolbar_tray_wrapper to create an + * association between a link tag in the administration bar and a tray. + * + * @param $variables + * An associative array containing the keys 'text', 'path', and 'options'. See + * the l() function for information about these variables. + * + * @see l() + */ +function theme_toolbar_tray_toggle(&$variables) { + return l($variables['text'], $variables['path'], $variables['options']); +} + +/** + * Implements template_preprocess_HOOK(). + */ +function template_preprocess_toolbar_tray_wrapper(&$variables) { + if (!isset($variables['element']['#attributes'])) { + $variables['element']['#attributes'] = array(); + } + if (!empty($variables['element']['#toolbar_identifier'])) { + $group = $variables['element']['#toolbar_identifier']; + $variables['element']['#attributes'] += array( + 'id' => 'toolbar-tray-' . $group, + 'data-toolbar-tray' => $group, + 'aria-owned-by' => 'toolbar-tab-' . $group, ); + $variables['element']['#attributes']['class'][] = 'tray-' . $group; + } + $variables['element']['#attributes']['class'][] = 'tray'; + $variables['element']['#attributes']['class'][] = 'overlay-displace-top'; +} + +/** + * Returns HTML for wrapping a toolbar tray. + * + * Used in combination with theme_toolbar_tray_toggle() to create an + * association between a link tag in the administration bar and a tray. + * + * @param array $variables + * An associative array containing: + * - element: An associative array containing the properties and children of + * the tray. Properties used: #children, #toolbar_identifier, #attributes + * and #heading. + */ +function theme_toolbar_tray_wrapper(&$variables) { + if (!empty($variables['element']['#children'])) { + $element = $variables['element']; + // Print a heading in the tray if one exists. + $heading = (isset($element['#heading'])) ? '

' . $element['#heading'] . '

' : ''; + return '
' . $heading . $element['#children'] . '
'; } } @@ -211,16 +324,18 @@ function toolbar_toolbar() { // The 'Home' tab is a simple link, with no corresponding tray. $items['home'] = array( - 'tab' => array( - 'title' => t('Home'), - 'href' => '', + '#theme_wrappers' => array('toolbar_tab_wrapper'), + '#theme' => 'link', + '#text' => t('Home'), + '#path' => '', + '#options' => array( 'html' => FALSE, 'attributes' => array( 'title' => t('Home page'), 'class' => array('icon', 'icon-home'), ), ), - 'weight' => -20, + '#weight' => -20, ); // Retrieve the administration menu from the database. @@ -230,6 +345,8 @@ function toolbar_toolbar() { toolbar_menu_navigation_links($tree); $menu = array( + '#theme_wrappers' => array('toolbar_tray_wrapper'), + '#heading' => t('Administration menu'), 'toolbar_administration' => array( '#type' => 'container', '#attributes' => array( @@ -237,7 +354,6 @@ function toolbar_toolbar() { ), 'administration_menu' => menu_tree_output($tree), ), - '#heading' => t('Administration menu'), ); // To conserve bandwidth, we only include the top-level links in the HTML. @@ -247,18 +363,22 @@ function toolbar_toolbar() { // @see toolbar_subtrees_jsonp() $menu['toolbar_administration']['#attached']['js'][url('toolbar/subtrees/' . _toolbar_get_subtree_hash())] = array('type' => 'external'); + // The administration element has a link that is themed to correspond to + // a toolbar tray. The tray contains the full administrative menu of the site. $items['administration'] = array( - 'tab' => array( - 'title' => t('Menu'), - 'href' => 'admin', + "#theme_wrappers" => array('toolbar_tab_wrapper'), + '#theme' => 'toolbar_tray_toggle', + '#text' => t('Menu'), + '#path' => 'admin', + '#options' => array( 'html' => FALSE, 'attributes' => array( 'title' => t('Admin menu'), 'class' => array('icon', 'icon-menu'), ), ), - 'tray' => $menu, - 'weight' => -15, + '#tray' => $menu, + '#weight' => -15, ); return $items; @@ -267,9 +387,10 @@ function toolbar_toolbar() { /** * Builds the Toolbar as a structured array ready for drupal_render(). * + * @todo: Update this doc block. * @return * A renderable arrray, with two children: - * - 'tabs': an array of links, rendered by theme('links'). + * - 'tabs': an array of render elements, with default type 'link'. * - 'trays': an array of render elements displayed when the corresponding tab * is activated. */ @@ -278,74 +399,41 @@ function toolbar_view() { $build = array('#theme' => 'toolbar'); $build['#attached']['library'][] = array('toolbar', 'toolbar'); - // Get the configured breakpoint to switch from vertical to horizontal + // Get the configured breakpoints to switch from vertical to horizontal // toolbar presentation. $breakpoints = entity_load('breakpoint_group', 'module.toolbar.toolbar'); if (!empty($breakpoints)) { $media_queries = array(); $media_queries['toolbar']['breakpoints'] = array_map( - function($object) {return $object->mediaQuery;}, - $breakpoints->breakpoints); + function ($object) { + return $object->mediaQuery; + }, + $breakpoints->breakpoints + ); $build['#attached']['js'][] = array( 'data' => $media_queries, 'type' => 'setting', ); - // // Load the breakpoints for toolbar. - foreach ($breakpoints->breakpoints as $key => $breakpoint) { - $build['#attached']['js'][0]['data']['toolbar']['breakpoints'][$key] = $breakpoint->mediaQuery; - } } - // Get toolbar items from all modules that implement hook_toolbar() or - // hook_toolbar_alter(). - $toolbar_groups = module_invoke_all('toolbar'); - drupal_alter('toolbar', $toolbar_groups); - uasort($toolbar_groups, 'drupal_sort_weight'); - - // Build the tabs and trays from the toolbar groups. - $build['trays'] = array(); - $build['tabs'] = array( - '#theme' => 'links', - '#links' => array(), - '#attributes' => array( - 'class' => array('bar', 'clearfix'), - ), - '#heading' => array('text' => t('Toolbar'), 'level' => 'h2', 'class' => 'element-invisible'), - ); - $tab_defaults = array( - 'title' => '', - 'href' => '', - 'html' => FALSE, - 'attributes' => new Attribute(), - ); + // Get toolbar items from all modules that implement hook_toolbar(). + $toolbar_items = module_invoke_all('toolbar'); - foreach ($toolbar_groups as $group => $items) { - if ($tab = $items['tab']) { - // Merge in the defaults. - $tab += $tab_defaults; + // Add properties to associate each tab with its (optional) tray. + foreach ($toolbar_items as $key => &$item) { + $id = drupal_html_class($key); + $item['#toolbar_identifier'] = $id; + if (isset($item['#tray'])) { + $item['#tray']['#toolbar_identifier'] = $id; } - // Register a tray if one is associated with this tab. - if (!empty($items['tray'])) { - // Provide an id, a data attribute linking each tab to the corresponding - // tray and aria information. - $tab['attributes']['id'] = 'toolbar-tab-' . $group; - $tab['attributes']['data-toolbar-tray'] = $group; - $tab['attributes']['aria-owns'] = 'toolbar-tray-' . $group; - $tab['attributes']['role'] = 'button'; - $tab['attributes']['aria-pressed'] = 'false'; - - if (array_key_exists($group, $build['trays'])) { - array_merge($build['trays'][$group], $items['tray']); - } - else { - // Assign the tray to the build. - $build['trays'][$group] = $items['tray']; - } - } - // Assign the tabs to the build. - $build['tabs']['#links'][$group] = $tab; } + unset($item); + + // Allow for altering of hook_toolbar(). + drupal_alter('toolbar', $toolbar_items); + + $build['#items'] = $toolbar_items; return $build; } diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 285b9a7..ec34bf4 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -2931,29 +2931,30 @@ function user_toolbar() { ); } - $user_tray = array( - '#heading' => t('User account actions'), - 'content' => array( - '#theme' => 'links__toolbar_user', - '#links' => $links, - '#attributes' => array( - 'class' => array('menu',), - ), - ), - ); - $items['user'] = array( - 'tab' => array( - 'title' => user_format_name($user), - 'href' => 'user', + "#theme_wrappers" => array('toolbar_tab_wrapper'), + '#theme' => 'toolbar_tray_toggle', + '#text' => user_format_name($user), + '#path' => 'user', + '#options' => array( 'html' => FALSE, 'attributes' => array( 'title' => t('My account'), 'class' => array('icon', 'icon-user'), ), ), - 'tray' => $user_tray, - 'weight' => 100, + '#tray' => array( + '#theme_wrappers' => array('toolbar_tray_wrapper'), + '#heading' => t('User account actions'), + 'user_links' => array( + '#theme' => 'links__toolbar_user', + '#links' => $links, + '#attributes' => array( + 'class' => array('menu',), + ), + ), + ), + '#weight' => 100, ); return $items;