primitives icon indicating copy to clipboard operation
primitives copied to clipboard

[NavigationMenu] Expose position of active <NavigationMenu.Item />

Open janhoogeveen opened this issue 2 years ago • 40 comments

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.

Screenshot_10_06_2022__13_02

However, if you add (much) more NavigationMenu.Item components the layout will start to look awkward.

image

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.

janhoogeveen avatar Jun 10 '22 11:06 janhoogeveen

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

janhoogeveen avatar Jun 10 '22 11:06 janhoogeveen

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

andy-hook avatar Jun 14 '22 10:06 andy-hook

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

janhoogeveen avatar Jun 15 '22 09:06 janhoogeveen

@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?

elisehein avatar Sep 28 '22 13:09 elisehein

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!

andy-hook avatar Sep 29 '22 11:09 andy-hook

any news in this issue?

jailsonpaca avatar Dec 20 '22 13:12 jailsonpaca

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

christian-reichart avatar Jan 18 '23 15:01 christian-reichart

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

Capture d’écran du 2023-02-03 15-45-44

heymath avatar Feb 03 '23 14:02 heymath

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?

andy-hook avatar Feb 03 '23 14:02 andy-hook

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 avatar Feb 03 '23 15:02 heymath

@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 avatar Feb 03 '23 16:02 andy-hook

@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!

heymath avatar Feb 03 '23 17:02 heymath

@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?

heymath avatar Feb 07 '23 14:02 heymath

Any updates on this?

joepetrillo avatar Feb 21 '23 21:02 joepetrillo

up

jailsonpaca avatar Mar 31 '23 18:03 jailsonpaca

Ah facing the same issue, thought initially it was a bug in the shadcn/ui package.

ReangeloJ avatar May 22 '23 12:05 ReangeloJ

still not resolved?

jailsonpaca avatar May 25 '23 03:05 jailsonpaca

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:

thejprice avatar Jun 30 '23 20:06 thejprice

UP

Josevictor2 avatar Aug 24 '23 02:08 Josevictor2

Would really appreciate an easy prop to achieve this

sgup avatar Oct 05 '23 19:10 sgup

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.

alexander-densley avatar Oct 09 '23 17:10 alexander-densley

+1

recallwei avatar Oct 17 '23 07:10 recallwei

+1

Fahl-Design avatar Oct 18 '23 14:10 Fahl-Design

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.

mspangl5 avatar Nov 11 '23 04:11 mspangl5

How to make the menubar active color when clicked

FalaseNoemdek avatar Nov 27 '23 07:11 FalaseNoemdek

Any updates on this? Would love to be able to override and choose the position of the dropdowns :)

JoshuaBellew avatar Dec 11 '23 20:12 JoshuaBellew

Ran into the same issue as everyone else, would love to have some props to control some of the behaviour.

damyco avatar Dec 12 '23 10:12 damyco

+1

awelrisak avatar Dec 15 '23 19:12 awelrisak

+1

akram19-setif avatar Jan 26 '24 01:01 akram19-setif

Up!

SalahAdDin avatar Feb 12 '24 15:02 SalahAdDin