Due to recent changes to the keyboard accessibility of the RadMenu (i.e. it is now only accessible using the arrow keys instead of moving around using tabs), mega menus are no longer keyboard accessible. We have designed a mega menu using a telerik RadSiteMap embedded in a RadMenu control, as suggested in the Telerik Demo site: http://demos.telerik.com/aspnet-ajax/menu/examples/megadropdown/defaultcs.aspx However, this is no longer accessible. Previously, you could open the dropdown by pressing the down button, then move around in the dropdown using tab. Now, however, pressing tab just closes the dropdown. We need the menu to be accessible in one way or another.
Hello Karen,
My name is Vasko and I am part of the Telerik UI for ASP.NET AJAX team. I have investigated the scenario mentioned in this thread after reviewing internally the behavior, I have found that the problem actually stemmed from two separate limitations in the existing controls.
Previously, the SiteMap inside the mega Menu (or on its own) relied only on the browser’s native Tab navigation. It did not implement true keyboard navigation (arrow keys, programmatic focusing of nodes, etc.). Because of that, the Menu could open its template, but it couldn’t actively “move” focus into the RadSiteMap.
This part of the issue has now been addressed. RadSiteMap will include built-in keyboard navigation starting in the upcoming update (scheduled for release this week).
Now here is the tricky part. When a control is placed inside the Menu’s ContentTemplate, the Menu does not know what kind of controls you may place there (inputs, grids, custom markup, etc.). Because of that, there was no generic or reliable way for RadMenu to automatically “focus the first intera
ctive element” inside the template.
This means that even with keyboard navigation enabled, the Menu could not automatically redirect focus into the SiteMap. To support this specific mega-menu scenario, once SiteMap’s keyboard update is live, I have created a safe override of the focusFirstChild method for RadMenuItem. This allows the Menu to correctly focus the first SiteMap node when a ContentTemplate contains a RadSiteMap.
Below you can find the override code, as well as a "Mega Menu" with SiteMap. Once the 2025 Q4 SP1 Update is live, please test with them.
JavaScript override:
let $T = Telerik.Web.UI;
if ($T && $T.RadMenu && $T.RadMenuItem) {
let originalFocusFirstChild = $T.RadMenuItem.prototype.focusFirstChild;
$T.RadMenuItem.prototype.focusFirstChild = function (e) {
let items = this.get_items();
if (items.get_count() === 0) {
if (this.get_hasContentTemplate()) {
if (this._state != $T.RadMenuItemState.Open) {
this._open(e);
}
let contentTemplateContainer = this._getContentTemplateContainer();
if (contentTemplateContainer) {
let siteMapElement = contentTemplateContainer.querySelector('.RadSiteMap');
if (siteMapElement) {
let siteMap = siteMapElement.control;
siteMap.focusNodeByIndex(0);
return;
}
}
}
return;
}
let item = items.getItem(0);
let firstItem = item;
while (!item._canFocus()) {
item = item._getNextItem();
if (item == firstItem) {
return; // no items to focus
}
}
item._transferFocus(e || null);
}
}<telerik:RadMenu RenderMode="Lightweight" runat="server" ID="RadMenu1" Skin="Default"
Width="880" Height="60" EnableShadows="true">
<Items>
<telerik:RadMenuItem Text="Products" PostBack="false">
<ContentTemplate>
<div id="CatWrapper" class="Wrapper" style="width: 435px;">
<h3>Categories</h3>
<telerik:RadSiteMap ID="RadSiteMap2" runat="server" Skin="Telerik" EnableTextHTMLEncoding="true">
<LevelSettings>
<telerik:SiteMapLevelSetting Level="0">
<ListLayout RepeatColumns="3" RepeatDirection="Vertical" />
</telerik:SiteMapLevelSetting>
</LevelSettings>
<Nodes>
<telerik:RadSiteMapNode NavigateUrl="#" Text="Furniture">
<Nodes>
<telerik:RadSiteMapNode NavigateUrl="#" Text="Tables & Chairs" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Sofas" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Occasional Furniture" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Childerns Furniture" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Beds" />
</Nodes>
</telerik:RadSiteMapNode>
<telerik:RadSiteMapNode NavigateUrl="#" Text="Decor">
<Nodes>
<telerik:RadSiteMapNode NavigateUrl="#" Text="Bed Linen" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Throws" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Curtains & Blinds" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Rugs" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Carpets" />
</Nodes>
</telerik:RadSiteMapNode>
<telerik:RadSiteMapNode NavigateUrl="#" Text="Storage">
<Nodes>
<telerik:RadSiteMapNode NavigateUrl="#" Text="Wall Shelving" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Kids Storage" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Baskets" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Multimedia Storage" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Floor Shelving" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Toilet Roll Holders" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Storage Jars" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Drawers" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Boxes" />
</Nodes>
</telerik:RadSiteMapNode>
<telerik:RadSiteMapNode NavigateUrl="#" Text="Lights">
<Nodes>
<telerik:RadSiteMapNode NavigateUrl="#" Text="Ceiling" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Table" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Floor" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Shades" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Wall Lights" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Spotlights" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="Push Light" />
<telerik:RadSiteMapNode NavigateUrl="#" Text="String Lights" />
</Nodes>
</telerik:RadSiteMapNode>
</Nodes>
</telerik:RadSiteMap>
</div>
<div id="FeatProduct">
<h3>Featured</h3>
<p>
Deco Mirror Table Lamp
<br />
<span class="price">$ 24.99</span>
</p>
</div>
</ContentTemplate>
</telerik:RadMenuItem>
<telerik:RadMenuItem Text="Stores" PostBack="false">
<Items>
<telerik:RadMenuItem Text="Store Locator" NavigateUrl="#" />
<telerik:RadMenuItem Text="Opening Times" NavigateUrl="#" />
<telerik:RadMenuItem Text="Events" NavigateUrl="#" />
</Items>
</telerik:RadMenuItem>
<telerik:RadMenuItem Text="News" PostBack="false" />
</Items>
</telerik:RadMenu>
Because ContentTemplates can contain anything, this override will not be added to RadMenu as a built-in feature, as we cannot safely assume what the “first focusable element” should be in arbitrary templates. However, for your mega menu scenario with RadSiteMap, this override will work once the new SiteMap keyboard navigation is released.
I hope this information helps clear thing up.
Regards,
Vasko
Progress Telerik
Hi Karen,
Due to the architectural complexities surrounding the current keyboard navigation, implementing support for ContentTemplates is not straightforward. The difference in rendering and the DOM structure when templates are used poses additional challenges. Specifically, handling focus within template items and determining the next selectable element outside the template upon focus exit are aspects that require a thorough solution to ensure a seamless user experience.
Regards,
Rumen
Progress Telerik
Rumen,
I'm wondering if you have any idea what release this fix might be included in? Thank you.
Karen
Hello Rumen,
That is wonderful news that you were able to reproduce and raised the priority. Thank you very much.
Karen
Hi Karen,
I was able to reproduce the issue that you experienced and after a discussion with the dev team, it appeared that the menu control does not offer keyboard support for its ContentTemplate feature. I raised the priority of this item in our backlog and we will try to implement it in one of the upcoming major releases of the suite.
Please bear with us.
Best Regards,
Rumen
Progress Telerik
Hi Rumen,
Sorry for the long delay in response, I was not able to work on this for a while. I am still having the issue. I added the RadMenu settings you mentioned. That works fine Ctrl + M opens the Menu. However, you said "You can still use the Tab key to go through the items" I cannot do that. When I hit tab, it just moves to the next item in the RadMenu - not the items in the RadSiteMap. Any other suggestions to try, at this point I cannot get this to be 508 Compliant. Thank you.
Karen
Hi Karen,
RadMenu offers WAI-ARIA and keyaboard support, which you can enable by setting:
menu.KeyboardNavigationSettings.CommandKey = KeyboardNavigationModifier.Ctrl;
menu.KeyboardNavigationSettings.FocusKey= KeyboardNavigationKey.M;
menu.EnableAriaSupport = true;Once the menu gets selected, you can press the bottom arrow key or tab to navigate to the menu item. Using the arrow keys you can navigate through the whole menu structure as explained in the description of the Keyboard Support demo.
Yes, RadSiteMap is a basic component and it does not offer a built-in way to select its first item and keyboard navigation. You can still use the Tab key to go through its items.
Regards,
Rumen
Progress Telerik
Hi Karen,
If the menu is created dynamically in the code-behind, you can use the following code as an example to import the JavaScript code from the server with the help of the ScriptManager.RegisterStartupScript method:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Create the RadMenu control
RadMenu menu = new RadMenu();
menu.ID = "RadMenu1";
menu.Skin = "Default";
menu.OnClientItemFocus = "OnClientItemFocus";
menu.OnClientItemClosing = "OnClientItemClosing";
// Create menu items
RadMenuItem item1 = new RadMenuItem("Item 1");
RadMenuItem item2 = new RadMenuItem("Item 2");
RadMenuItem item3 = new RadMenuItem("Item 3");
// Add sub-items to Item 1
RadMenuItem subItem1 = new RadMenuItem("Sub Item 1");
RadMenuItem subItem2 = new RadMenuItem("Sub Item 2");
item1.Items.Add(subItem1);
item1.Items.Add(subItem2);
// Add items to the menu
menu.Items.Add(item1);
menu.Items.Add(item2);
menu.Items.Add(item3);
// Add the menu to the page
// Assuming you have a placeholder control named "menuPlaceholder" in your markup
menuPlaceholder.Controls.Add(menu);
// Register the startup script
string script = @"
function OnClientItemFocus(sender, eventArgs) {
var item = eventArgs.get_item();
if (item) {
item.open();
// document.getElementById('textbox1').focus();
$telerik.cancelRawEvent(eventArgs);
return false;
}
}
function OnClientItemClosing(sender, args) {
args.set_cancel(true);
}
";
ScriptManager.RegisterStartupScript(this, this.GetType(), "CustomScript", script, true);
}
}
Regards,
Rumen
Progress Telerik
Hi there,
While there isn't yet a universal solution, you can try to implement it based on the OnClientItemFocus and OnClientItemClosing events of the menu:
<script>
function OnClientItemFocus(sender, eventArgs) {
var item = eventArgs.get_item();
if (item) {
item.open();
// document.getElementById("textbox1").focus();
$telerik.cancelRawEvent(eventArgs);
return false;
}
}
function OnClientItemClosing(sender, args) {
args.set_cancel(true);
}
</script>
<telerik:RadMenu runat="server" ID="RadMenu1" Skin="Default" OnClientItemFocus="OnClientItemFocus" OnClientItemClosing="OnClientItemClosing" ...
Regards,
Rumen
Progress Telerik
Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.