Giter VIP home page Giter VIP logo

details-menu-element's Introduction

<details-menu> element

A menu that's opened with a <details> button.

Installation

$ npm install @github/details-menu-element

Usage

Script

Import as a module:

import '@github/details-menu-element'

With a script tag:

<script type="module" src="./node_modules/@github/details-menu-element/dist/index.js">

Markup

<details>
  <summary>Robots</summary>
  <details-menu role="menu">
    <button type="button" role="menuitem">Hubot</button>
    <button type="button" role="menuitem">Bender</button>
    <button type="button" role="menuitem">BB-8</button>
  </details-menu>
</details>

Use data-menu-button and data-menu-button-text to update the button's text on menu item activation.

<details>
  <summary>Preferred robot: <span data-menu-button>None</span></summary>
  <details-menu role="menu">
    <button type="button" role="menuitem" data-menu-button-text>Hubot</button>
    <button type="button" role="menuitem" data-menu-button-text>Bender</button>
    <button type="button" role="menuitem" data-menu-button-text>BB-8</button>
  </details-menu>
</details>

Use data-menu-button and data-menu-button-contents to update the button's HTML content on menu item activation.

<details>
  <summary>Preferred robot: <span data-menu-button>None</span></summary>
  <details-menu role="menu">
    <button type="button" role="menuitem" data-menu-button-contents><img src="hubot.png"> Hubot</button>
    <button type="button" role="menuitem" data-menu-button-contents><img src="bender.png"> Bender</button>
    <button type="button" role="menuitem" data-menu-button-contents><img src="bb8.png"> BB-8</button>
  </details-menu>
</details>

Use label[tabindex="0"][role=menuitemradio/menuitemcheckbox] when dealing with radio and checkbox inputs menu items. Check states of the input element and the label will be synchronized.

<details>
  <summary>Preferred robot</summary>
  <details-menu role="menu">
    <label tabindex="0" role="menuitemradio">
      <input type="radio" name="robot" value="Hubot"> Hubot
    </label>
    <label tabindex="0" role="menuitemradio">
      <input type="radio" name="robot" value="Bender"> Bender
    </label>
    <label tabindex="0" role="menuitemradio">
      <input type="radio" name="robot" value="BB-8"> BB-8
    </label>
  </details-menu>
</details>

Events

  • details-menu-select (cancelable) - fired on <details-menu> with event.detail.relatedTarget being the item to be selected.
  • details-menu-selected - fired on <details-menu> with event.detail.relatedTarget being the item selected, after label is updated and menu is closed.

Deferred loading

Menu content can be loaded from a server by embedding an <include-fragment> element.

<details>
  <summary>Robots</summary>
  <details-menu src="/robots" preload>
    <include-fragment>Loading…</include-fragment>
  </details-menu>
</details>

The src attribute value is copied to the <include-fragment> the first time the <details> button is toggled open, which starts the server fetch.

If the preload attribute is present, the server fetch will begin on mouse hover over the <details> button, so the content may be loaded by the time the menu is opened.

Browser support

Browsers without native custom element support require a polyfill.

  • Chrome
  • Firefox
  • Safari
  • Microsoft Edge

Development

npm install
npm test

License

Distributed under the MIT license. See LICENSE for details.

details-menu-element's People

Contributors

dependabot[bot] avatar dgraham avatar jonrohan avatar keithamus avatar khiga8 avatar koddsson avatar kyfast avatar manuelpuyol avatar mislav avatar muan avatar pablonete avatar siddharthkp avatar theinterned avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

details-menu-element's Issues

Reference Error when running on Node.js

I am using this package on a React site using Compositor's x0. When building the site to static files, I get the following error:

building static sitewebpack:///./node_modules/@github/details-menu-element/dist/index.esm.js?:15
Object.setPrototypeOf(_CustomElement.prototype, HTMLElement.prototype);
                                                ^

ReferenceError: HTMLElement is not defined
    at eval (webpack:///./node_modules/@github/details-menu-element/dist/index.esm.js?:15:49)
    at Module../node_modules/@github/details-menu-element/dist/index.esm.js (/Users/chasemccoy/Repositories/playground/dist/TEMP/App.js:323:1)
    at __webpack_require__ (/Users/chasemccoy/Repositories/playground/dist/TEMP/App.js:30:30)
    at eval (webpack:///./src/details/index.mdx?:14:1)
    at Object../src/details/index.mdx (/Users/chasemccoy/Repositories/playground/dist/TEMP/App.js:5981:1)
    at __webpack_require__ (/Users/chasemccoy/Repositories/playground/dist/TEMP/App.js:30:30)
    at webpackContext (webpack:///./src_sync_\.(js%7Cmd%7Cmdx%7Cjsx)$?:18:9)
    at eval (webpack:///./node_modules/@compositor/x0/src/entry.js?:116:15)
    at Array.map (<anonymous>)
    at getComponents (webpack:///./node_modules/@compositor/x0/src/entry.js?:112:6)

From what I can tell, this has to do with the HTMLElement object not being present outside of the browser. Is there anything that can be done to this package to support server rendering? If not, is there a way I can work around this?

set default value data-menu-button with checked input

before:

<details>
    <summary>Best robot: <span data-menu-button>Unknown</span></summary>
    <details-menu>
      <label tabindex="0" role="menuitemradio" data-menu-button-text><input type="radio" name="robot"> Hubot</label>
      <label tabindex="0" role="menuitemradio" data-menu-button-text><input type="radio" name="robot"> Bender</label>
      <label tabindex="0" role="menuitemradio" data-menu-button-text><input type="radio" name="robot"> BB-8</label>
    </details-menu>
  </details>

after:

<details>
    <summary>Best robot: <span data-menu-button> ( set text of checked input without click on labels ) [Hubot] </span></summary>
    <details-menu>
====> <label tabindex="0" role="menuitemradio" data-menu-button-text><input type="radio" name="robot" class="selected" aria-selected="true" aria-checked="true" checked> Hubot</label>
      <label tabindex="0" role="menuitemradio" data-menu-button-text><input type="radio" name="robot"> Bender</label>
      <label tabindex="0" role="menuitemradio" data-menu-button-text><input type="radio" name="robot"> BB-8</label>
    </details-menu>
  </details> 

Distinguish selected state and hover state

Currently hovered/focused items and selected items both have the aria-selected=true, which makes it hard to tell which is already selected, and which is to be selected.

Perhaps aria-current? https://www.w3.org/TR/wai-aria-1.1/#h-note-38

In some use cases for widgets that support aria-selected, current and selected can have different meanings and can both be used within the same set of elements. For example, aria-current="page" can be used in a navigation tree to indicate which page is currently displayed, while aria-selected="true" indicates which page will be displayed if the user activates the treeitem.

Notes:

  • We might need to consider if there's a difference in semantics when the menu is not used in a navigation context.
  • Do not apply when item is menuitemcheckbox (when multiple selection is possible).

cc @github/web-systems

Escape key hijack

Escape event.preventDefault() even when the menu is not opened.

Demonstrated here: https://html-is.glitch.me/throwaway/dialog-and-menu.html

With details[open] > details-dialog > details[open] > details-menu user is not able to escape all the way out when focusing on the summary for the details-menu.

With details[open] > details-menu > details[open] > details-dialog user is able to escape all the way out when focusing on the summary for the details-dialog.

Live demo

Would be great to have the example file served as a live demo, e.g. using gh-pages

Autofocus first item when open menu

Hi,

Will it be possible to focus the first menu item when it opens without it being an input element necessarily? This is how it is currently defined.

For accessibility, in most dropdowns, when pressing the button, the focus is expected to go to the first menu item, that doesn't happen currently.

I can try to make a pr to fix this if you agree.

Thanks!

The events are emitted 3 times using `menuitemradio`

The events are emitted 3 times using role="menuitemradio", when using other roles only single event is emitted.

Captura de pantalla 2019-05-09 a las 13 00 47

I think the problem is in this line:

: target.closest('[role="menuitem"], [role="menuitemradio"]')

[role="menuitemradio"] is interacting with both change and click events from <details>.

This is a problem since the first time details-menu-selected is fired, the radio button is still unchecked.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.