primitives
primitives copied to clipboard
[NavigationMenu] Expose position of active <NavigationMenu.Item />
Feature request
Can we expose the position of the active <NavigationMenu.Item />
, and maybe it's bounding box so we can position the <NavigationMenu.Viewport />
directly below the active item?
It could be exposed through CSS custom properties as --radix-navigation-menu-indicator-position
, which should work for both horizontal and vertical menu's.
Even better would be a hook or render prop so we can wait until the indicator knows its position before we show the <NavigationMenu.Viewport />
Overview
The NavigationMenu works really well if your foldout content is wider than your list of navigation menu items.
However, if you add (much) more NavigationMenu.Item
components the layout will start to look awkward.
Example on codesandbox: https://02xv7f.csb.app/
Who does this impact? Who is this for?
Everyone who wants to use NavigationMenu with a wide list of items.
I realize another solution is to wrap <NavigationMenu.Viewport />
in <NavigationMenu.Indicator />
but I'm not sure if that's frowned upon? 🤔
One significant downside of this approach is that you get a short window of time where the CSS custom property indicating the position of the indicator is not set yet, so the ViewportPosition jumps around.
const StyledIndicatorWithArrow = React.forwardRef((props, forwardedRef) => (
<StyledIndicator {...props} ref={forwardedRef}>
<StyledArrow />
<ViewportPosition>
<NavigationMenuViewport />
</ViewportPosition>
</StyledIndicator>
));
Example: https://codesandbox.io/s/cocky-heisenberg-biwho8?file=/App.js
Hey @janhoogeveen , I agree this is a bit of a pain point at the moment, providing some way to track the content against the active trigger would be very useful for folks 👍
I realize another solution is to wrap <NavigationMenu.Viewport /> in <NavigationMenu.Indicator /> but I'm not sure if that's frowned upon?
As you noted, the indicator wasn’t designed for this purpose. In addition to the visual glitch there is also an accessibility problem as aria-hidden
is set on the indicator part by default so it would effectively hide all menu content from screen readers.
Thanks for raising, I'm going to mark it for improvement. In the meantime it is possible to implement your own tracking logic fairly easily depending on your design requirements, here is a (really) rough example of how it could work with a centrally aligned navigation:
https://codesandbox.io/s/navigation-menu-track-position-fhh9so
Hey @andy-hook, great to hear! Curious to see what kind of API you're going to end up! 👍🏻
I really appreciate your example, it looks solid and easy enough to use in the meantime! Thanks so much
@andy-hook Thanks for the example!
I'll be looking forward to this feature as well.
Would you mind explaining why you set the list ref with setState
rather than useRef
in your example?
Would you mind explaining why you set the list ref with setState rather than useRef in your example?
@elisehein It ensures the ref callbacks are updated with the list node when it’s available, there are likely more efficient ways to build this but I wanted to provide a quick example to show that this is possible in user code with some additional measurement.
Another approach might be to get and sync the currently active trigger via effect and update the positioning accordingly:
https://codesandbox.io/s/navigation-menu-track-position-effect-sync-q20tjd?file=/src/App.js
It depends on your design and the types of animation effects you’re trying to achieve, this example is dependent on central alignment so a different approach or more generic implementation might be necessary depending on the need.
It also doesn't account for responsive changes in element dimensions, for that you'd need to observe for element resize etc.
Hope this helps!
any news in this issue?
What's the best way to center the content below the item, but keeping it "contained" in the viewport, so the content will stick to the left or right screen edge, instead of going off-screen?
I'm trying to build a Main navigation menu, it is aligned to the right inside the header. For the right-most navigation items the content goes off-screen currently.
Thanks for any hints
Hello :wave:
Is it OK to use a Dropdown in a NavigationMenu? Or can we use a Menubar as Navigation? I guess both answers are "no", but in cas I am wrong :smile:
Because what I want is a submenu displayed like a dropdown just below the NavigationMenu.Item (see screenshot below).
I don't want a common view port to display links on the middle of the Navigation ... the example for NavigationMenu looks nice, but it does not look like the most common design for a Navigation. In my opinion, most navigations look like the MenuBar actually or a NavigationMenu + Dropdowns.
And sticking to NavigationMenu seems to add a lot of complexity to position it below the NavigationMenu.Item and handle screen edges... It is the kind of things I am expecting Radix to handle for me. What Dropdown seems to do already by the way.
Moving from Reakit v1 to RadixUI was easy until I started migrating the last component of my todo list (MainNav), and now I am hard stuck on my migration Pull Request :sweat_smile:
Thanks for any help! :pray:
Screenshot of desired design
Or can we use a Menubar as Navigation?
Nope, as you say, Menubar shouldn't be used as navigation
@heymath how many levels deep is your nav? is it only one level per your screenshot?
Or can we use a Menubar as Navigation?
Nope, as you say, Menubar shouldn't be used as navigation
@heymath how many levels deep is your nav? is it only one level per your screenshot?
Yes it is only one level :wink:
Thanks!
@heymath I don't think it's much complexity to use the NavigationMenu
and position the content as you require, you are correct that it doesn't provide collision handling but it's typically not necessary in the majority of cases.
Website navigation typically sits at the head of a page by convention so collisions are unlikely, and as horizontal width becomes limited it's typical to switch to a separate collapsed drawer / accordion style anyway.
Here's a simple example: https://codesandbox.io/s/simple-navigation-menu-em1qrc?file=/src/App.js
Using NavigationMenu
like this provides the appropriate accessibility patterns and keyboard handling specifically designed for website navigation. A list of dropdown menus is an option, but that primitive was not intended for that purpose and unless you really need the collision handling I would recommend the above instead.
Hope this helps.
@andy-hook well actually you can see on the screenshot that the "Plus" dropdown is at the end of the nav, and the nav is large (very often it that takes the whole screen width or more on small screens with a horizontal scroll). So we have that case where the drop-down is out of screen and creates a horizontal scroll etc. I am on mobile right now, I will have a look at the code you provided layer, to see if it can be adapted easily or not.
Anyway, I have to say that I like very much migrating other components from Reakit to Radix. It was clear and simple. But this NavigationMenu component was the opposite. A lot of things not handle by default and a default behavior that does not seems natural/the most common case to me. I was skeptical if it was the good one or if I had to merge it with other components etc. 😅
By the way I am very new to this, I only spent one day exploring this migration, maybe I don't see how things can be done yet and it is not that difficult to achieve what we want...
Thanks again for your answers!
@andy-hook maybe there is another way to achieve it, but staying close to the current Reakit implementation, and my work in progress of the migration, I am stuck at this:
https://codesandbox.io/s/simple-navigation-menu-forked-v5d6qp?file=/src/App.js
My problem here is that Radix does not auto position the Content to be aligned with the Trigger or does not Provide any thing to help to do it (unless I missed it). And I do not see how to achieve it :thinking:
Is it normal to not have this kind of feature included in NavigationMenu while it is in DropdownMenu & Menubar components?
Any updates on this?
up
Ah facing the same issue, thought initially it was a bug in the shadcn/ui package.
still not resolved?
I was going to implement this navigation menu into our website, but ran into this very issue. Seems like it would be a nice feature to include? The example conveniently uses only 3 menu items to hide this issue. :thinking:
UP
Would really appreciate an easy prop to achieve this
I've been using shadcn/ui alot recently, and I have to say this navigation menu seems like a poorly created component. Very little customizability, and no prop to get rid of the open on hover. Seems like a lot of functionality that is pretty standard in well developed ui libraries are not present in this radix nav menu comp. I'm currently using the sheet component now to create a my nav menu since it allows me to do what I need.
+1
+1
Any updates on this? It is shocking to me that a component library that is designed to be style-less has something this unorthodox built into it by default without a simple way of disabling it. Basically every website has a navbar and most of them are wider than their example in the docs.
How to make the menubar active color when clicked
Any updates on this? Would love to be able to override and choose the position of the dropdowns :)
Ran into the same issue as everyone else, would love to have some props to control some of the behaviour.
+1
+1
Up!