hook_preprocess_menu
is missing a lot of variables that other preprocessors have so I finally solved my problem using hook_preprocess_block
(which I think would not have been possible in earlier versions of drupal)
New solution since people have been reporting that $vars['configuration']['region']
is empty
function THEMENAME_preprocess_block(&$vars){
if($vars['base_plugin_id'] == "system_menu_block"){
if($vars['derivative_plugin_id'] == "main"){
$block = \Drupal\block\Entity\Block::load($vars["elements"]["#id"]);
if($vars['configuration']['region'] $block->getRegion() == "navbar"){
$vars['content']['#attributes']['class'][] = 'in-navbar';
$vars['content']['#attributes']['class'][] = 'nav';
}
elseif($vars['configuration']['region'] == "footer"){
$vars['content']['#attributes']['class'][] = 'in-footer';
}
}
}
}
NOTE if using in a recursive function/twig MACRO (which probably you are) you should removeClass
all the classes you don't want in inner UL
tags in a way similar to this
{{ menus.menu_links(item.below, attributes.removeClass('nav','in-navbar'), menu_level + 1) }}
old solution
function THEMENAME_preprocess_block(&$vars){
if($vars['base_plugin_id'] == "system_menu_block"){
if($vars['derivative_plugin_id'] == "main"){
if($vars['configuration']['region'] == "navbar"){
$vars['content']['#attributes']['class'][] = 'in-navbar';
$vars['content']['#attributes']['class'][] = 'nav';
}
elseif($vars['configuration']['region'] == "footer"){
$vars['content']['#attributes']['class'][] = 'in-footer';
}
}
}
}