It's even simpler if, like the OP, you only want to move Menus and Widgets out of Appearance and to the top level. That's what I needed too.
Since we're just moving WP core menu items around, we don't need to use add_menu_page
to add the menu items back in - we're not adding any new menu items. Just unset them from the $submenu array and re-set them elsewhere in the $menu array.
function re_sort_menu() {
global $menu;
global $submenu;
// Note: find the position of every submenu in Appearance by uncommenting the following:
// print_r($submenu['themes.php'];
unset($submenu['themes.php'][10]); // Unsets Appearance -> Menu (position 10)
unset($submenu['themes.php'][7]); // Unsets Appearance -> Widgets
// Add Menu and Widgets back at top level with some dashicons
// Be careful not to give menu positions (array keys) that conflict with other menu items
// TIP: print_r($menu); to see existing menu positions and also to check out the proper order of these array values. WP docu seems to list them in the incorrect order.
$menu[31] = array( __( 'Menus', 'theme-slug' ), 'edit_themes', 'nav-menus.php', __( 'Menus', 'theme-slug' ), 'menu-top menu-nav', 'menu-nav', 'dashicons-menu');
$menu[32] = array( __( 'Widgets', 'theme-slug' ), 'edit_themes', 'widgets.php', __( 'Widgets', 'theme-slug' ), 'menu-top menu-nav', 'menu-nav', 'dashicons-admin-generic');
}
add_action( 'admin_menu', 're_sort_menu' );
Norcross's answer above put me on the right track, but for whatever reason using add_menu_item
did not regenerate a working "Nav Menu" section as a top level menu item in the admin for me in WP 4.1. The problem seemed to lie in the order of the array values passed to that function, but no matter how I reordered things, working straight off the new WP Developer API article, i never got it working.