facebookincubator / infima

A UI framework that provides websites with the minimal CSS and JS needed to get started with building a modern responsive beautiful website
https://infima.dev
MIT License
408 stars 55 forks source link

Unability to navigate collapsed menu without JS #36

Closed slorber closed 3 years ago

slorber commented 4 years ago

Currently on D2 it's not possible to "navigate" to a collapsed menu without JS enabled.

This is probably not the most impactful enhancement we could make, but I think I read it's a goal to make the site usable without JS (or before js hydration).

image

We could probably expand a collapsed menu item on :focus / :focus-within

yangshun commented 4 years ago

How would you implement this behavior without JS though? In that case maybe the current behavior where nothing is collapsed on initial load (when JS is disabled) isn't too bad? 😂

I don't see how we can address this, D1's sidebar needs JS as well for collapsing and expanding.

slorber commented 4 years ago

It is likely possible to implement a tree structure with foldable nodes by expanding them on :focus / :focus-within

https://blogs.igalia.com/mrego/2017/05/03/adding-focus-within-selector-to-chromium/

https://blogs.igalia.com/mrego/files/2017/05/focus-within-menu.html

If you press tab, you'll see the menu values just by using tab and focusing the items. And clicking on a collapsed category gives it focus so... I think it's definitively possible without JS :)

kimbaudi commented 3 years ago

Hi, I discovered Docusaurus v2 a week ago and also discovered this project as well. I couldn't help but to comment on this. I also don't think it is possible to implement tree view collapsible menu without JS. Please take a look at https://www.w3.org/TR/wai-aria-practices-1.1/#TreeView where they need JS. I think it would be better to just display an expanded tree view if JS is disabled. The user will not be able to expand/collapse menus, but they can still navigate the menu.

slorber commented 3 years ago

Related to https://github.com/facebook/docusaurus/issues/3030

I made a demo without js, using focus-within here: https://github.com/facebook/docusaurus/pull/3642#issuecomment-717184325

I think it would be better to just display an expanded tree view if JS is disabled.

We don't want to force the user to have all users with an expanded tree view by default. This should rather only affect users that were not able to load our JS properly (network error, disabled js, older browser...)

kimbaudi commented 3 years ago

There are tradeoffs to either displaying an expanded tree view or using :focus-within. It really depends on the # of menu items and how deeply nested the submenus are. The problem I have with :focus-within is that it collapses previous menu items that I have focused on as soon as I focus on a different menu item. When I'm navigating the sidebar of a documentation, it really helps to see all the menu items (not just the one that I am focused on). This is especially true when I am looking at new documentation and am still unfamiliar with the menu. But I do understand why you also don't want to force users to have an expanded tree view.

m-allanson commented 3 years ago

I'd like to see this handled too. A pattern I've used is to default to all expanded, and then collapse the menus only when JS is available.

One way to do this is with a script tag straight after the opening tag of the menu. e.g.

<ul id="nav">
  <script>
    document.getElementById("nav").classList.add("collapsed");
  </script>
  <!-- the rest of the menu markup follows here... -->

This prevents a flash of changing styles, because the browser applies the collapsed styles very early in the rendering process. Here's a full example on CodeSandbox.

Another alternative might be using <noscript> tags to render a full expanded menu when JS is disabled.

The downside to both of these approaches - they do nothing to help against network errors or JS errors in the app code.

slorber commented 3 years ago

@m-allanson the goal for me is not really to handle the case for users having disabled the JS, but rather being able to have a decent UI even before JS loads and React hydrates. I want to somehow make the React hydration process a progressive enhancement of the experience instead of being a hard requirement, maybe deferring the JS loading to a lower priority, leverage progressive hydration, and obtain a better perf profile.

My goal is in the same way a Gatsby link can be clicked even before the React hydration and can still navigate.

So I don't think your solution would work apart for users with JS disabled.

Related: https://kryogenix.org/code/browser/everyonehasjs.html

m-allanson commented 3 years ago

@slorber That's a fair point.

Related: kryogenix.org/code/browser/everyonehasjs.html

This is great, bookmarked!

m-allanson commented 3 years ago

What if the .menu__link--sublist element linked to the first item in the sublist?

That would make all parts of the site navigable without JS, and wouldn't change any functionality once the JS is running.

Once you've navigated to a sublist page, the sidebar already displays other pages in that category.

<ul class="menu__list">
  <li class="menu__list-item">
-    <a class="menu__link menu__link--sublist menu__link--active" href="#!"
+    <a class="menu__link menu__link--sublist menu__link--active" href="/docs/next/api/plugins"
      >Plugins</a
    >
    <ul class="menu__list">
      <li class="menu__list-item">
        <a
          aria-current="page"
          class="menu__link menu__link--active active"
          tabindex="0"
          href="/docs/next/api/plugins"
          >Plugins overview</a
        >
      </li>
      <li class="menu__list-item">
        <a
          class="menu__link"
          tabindex="0"
          href="/docs/next/api/plugins/@docusaurus/plugin-content-docs"
          >📦 plugin-content-docs</a
        >
      </li>
    </ul>
  </li>
</ul>
Screenshot showing suggested changes on the Docusaurus site

For example try browsing the Docusaurus Plugins pages without JS. That part works well, but you can't get to the Themes section. This change would enable navigating through to a different category.

slorber commented 3 years ago

That's definitively a behavior that would allow navigating to category subitems.

We have an issue to support that: https://github.com/facebook/docusaurus/issues/2643

Let's figure if this issue is still useful after we support that feature. But I think we may still want to allow keeping the existing category behavior (no link), so it can still be useful in such case to allow browsing subitems.

This is a different sidebar behavior UX, and I think we could support both it possible.

m-allanson commented 3 years ago

My thought was to make the clientside JS restore the href=#! link when hydrating.

So the proposed change would only apply when JS failed to load.

slorber commented 3 years ago

That looks like a nice trick, didn't think of that, worth giving it a try ;)

slorber commented 3 years ago

As we now render "lazy/partial sidebars" on Docusaurus SSR, I think this will never be implemented in Infima so I'm closing

See my comment here https://github.com/facebook/docusaurus/issues/3030#issuecomment-879952374

slorber commented 2 years ago

I implemented your suggestion as part of https://github.com/facebook/docusaurus/pull/5830 @m-allanson Now the sidebar is partially rendered on the server and we can still navigate it entirely with JS disabled. Test URL: https://deploy-preview-5830--docusaurus-2.netlify.app/docs/next/category/guides/ The only edge-case where we can't navigate with JS disabled is when a category has no subitems (which is a weird use-case anyway) Let me know if you see any issue

m-allanson commented 2 years ago

Lovely stuff, thank you 🙏 It works great from this side.