-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Experiment: Replicate Navigation block using directives (Alpinejs) #44289
Experiment: Replicate Navigation block using directives (Alpinejs) #44289
Conversation
Size Change: -2.97 kB (0%) Total Size: 1.25 MB
ℹ️ View Unchanged
|
So far, I just replaced the
In the beginning, I was using the Apart from replacing micromodal, I want to review the rest of interactivity and code and check if there is anything else to consider. cc: @luisherranz |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking great so far!
Your plan is to get rid of the code on the view.js
file as well, is that correct?
<div class="wp-block-navigation__responsive-close" tabindex="-1" data-micromodal-close> | ||
<div class="wp-block-navigation__responsive-dialog" aria-label="%8$s"> | ||
<button %4$s data-micromodal-close class="wp-block-navigation__responsive-container-close">%10$s</button> | ||
'<button x-on:click="open = true; $focus.within($refs.items).first()" aria-haspopup="true" %3$s class="%6$s">%9$s</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few things here with the $focus.within($refs.items)
:
-
The
$focus.within($refs.items).first()
part is not triggered when you focus on the hamburguer menu and useEnter
to open the menu.I wonder what directive/pattern we could use here to take into account both the click and the keyboard. Maybe a simple
x-effect
that reacts toopen === true
to make it more declarative? -
$focus.within($refs.items).first()
is focusing the last element to me! I have no idea why.ezgif-4-d303afd612.mp4
-
On close, the
micromodal
version focus the hamburguer menu (shown in video above). We should include that. -
What do you think about the
$focus.within()
API. Was it easy to understand? Would it be an easier way to deal with the focus?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The $focus.within($refs.items).first() part is not triggered when you focus on the hamburguer menu and use Enter to open the menu.
I wonder what directive/pattern we could use here to take into account both the click and the keyboard. Maybe a simple x-effect that reacts to open === true to make it more declarative?
- $focus.within($refs.items).first() is focusing the last element to me! I have no idea why.
I'm not sure about these two points. It seems to be working for me. Or am I doing something wrong?
https://www.loom.com/share/a144d46e28e6403ca77e2fa7674c87f2
On close, the micromodal version focus the hamburguer menu (shown in video above). We should include that.
Regarding this, I believed it was working 🤷 I have just pushed a commit fixing it using x-ref
and $focus
again. Not sure if it is the best way though, maybe we could use just something like document.querySelector(".hamburger").focus()
.
What do you think about the $focus.within() API. Was it easy to understand? Would it be an easier way to deal with the focus?
For me, it was easy to understand but maybe it was just because there is an example really similar to this use case in the docs. If that wasn't the case, I would have probably struggled to understand it.
Regarding if there is a better way to handle the focus, maybe for these cases using the directives is not 100% necessary and we could use just document.querySelector(".hamburger").focus()
as mentioned above.
Anyway, the functions of the $focus
seem easy to use to me and cover many use cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about these two points. It seems to be working for me. Or am I doing something wrong?
Oh, you're right. Alpine uses tappable
, and the list of focusable elements is not the same as the one in micromodal, so maybe that's why. Don't worry about it. It's not important.
I wonder what directive/pattern we could use here to take into account both the click and the keyboard. Maybe a simple x-effect that reacts to open === true to make it more declarative?
I've moved the focus to an x-effect
directive (which is similar to React's useEffect
) in 0a0598f to make it more declarative. It seems to work fine, but could you please check it out?
x-effect="open === true ? $focus.within($refs.items).first() : $focus.focus($refs.hamburger)
I couldn't use if ... else
inside the x-effect
. I'm not sure if I was doing something wrong.
Not sure if it is the best way though, maybe we could use just something like document.querySelector(".hamburger").focus().
Good point!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved the focus to an x-effect directive (which is similar to React's useEffect) in 0a0598f to make it more declarative. It seems to work fine, but could you please check it out?
Oh, I missed the x-effect
comment sorry. It seems clearer this way. However, if I am not mistaken when the page is loaded open = false
so it leads to focusing on the hamburger even if the user hasn't interacted with the menu. I assume this shouldn't be the case right? The only thing I can think of to solve it is to change the initial state of open to undefined or an empty string and change the conditional to only focus on true /false:
x-effect="if (open === true) { $focus.within($refs.items).first() } else if (open === false) { $focus.focus($refs.hamburger) }"
This way it seems to work for me.
And using the if ... else
is working for me 🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, if I am not mistaken when the page is loaded open = false so it leads to focusing on the hamburger even if the user hasn't interacted with the menu
Oh, true. That's a bummer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$focus.within($refs.items).first() is focusing the last element to me! I have no idea why.
I think I've discovered why. One of the items has tabindex="0"
in the HTML. I don't know where did it come from.
<a
class="wp-block-navigation-item__content"
href="http://localhost:8888/eius-magnam-sed-laboriosam-reprehenderit-exercitationem/"
tabindex="0"
>
<span class="wp-block-navigation-item__label">Eius magnam</span>
</a>
So it is not a problem for this experiment, don't worry 🙂
Yes, I am reviewing the |
I have just added the directives to replicate the submenu functionalities. To open the submenu hovering over the link css is used, so it doesn't apply here. However, you can open the submenu by clicking the arrow button. I just replicated the basic use cases, I am still working on some of them and I have to review the settings. So far, the directives used:
I was trying to close the submenu when the focus is outside it, but I haven't been able to do it yet. I hoped that something like Moreover, we can't use Apart from that, I was checking the navigation-submenu block view.js file because I'm not sure what it is doing. It isn't defined in the block.json (there is no viewScript field) and it doesn't seem to load in the browser. Furthermore, it seems the navigation block view.js file is doing mostly the same. This is the one loaded in the browser. I will keep researching to check if we have to replicate more functionalities. |
The only way I could think of to make this work, which is far far from perfect, has been:
It works in my case, but it doesn't seem reliable. Any ideas how this could be handled? |
Why not use |
I didn't think about that option, it could work as well. However, there is more CSS added to the classes (these lines for example), so toggling the class would be needed anyway. Having said that, the purpose was to find which directives were needed. From there, the developers could use whatever they prefer I guess. |
Now that the |
Yeah, I think we can consider this finished, at least for now. Let's focus on replicating the Alpine directives with our own 🙂 |
What?
This is an experiment to replicate the functionalities of the navigations block but using directives. In this case we are using Alpinejs. This is part of the directives hydration experiment.
Why?
In the directives hydration experiment we have started using directives, and we want to understand which ones would be needed for this use case.
It is worth mentioning that this is just an experiment with learning purposes. We want to understand better the directives that are needed and I am not suggesting we should use
AlpineJS
instead ofmicromodal
.How?
I removed the
micromodal
library and added AlpineJS (with the@alpine/focus
plugin) instead. From there, I am just adding the directives needed to replicate the behaviour.Testing Instructions
Just open a site with the navigation block and check everything is working as expected.