Dropdown

<div id="" class="hide " hidden>
    <li class="" style="">

        <a class="">
    
</a>

    </li>

    <li class="" style="">

        <a class="">
    
</a>

    </li>

    <li class="" style="">

        <a class="">
    
</a>

    </li>

</div>
{{#if list}}
  <ul id="{{id}}" class="hide {{modifier}}" {{#if hidden}}hidden{{/if}}>
    {{> @children}}
  </ul>
{{else}}
  <div id="{{id}}" class="hide {{modifier}}" {{#if hidden}}hidden{{/if}}>
    {{> @children}}
  </div>
{{/if}}
{
  "id": null,
  "modifier": null,
  "list": null,
  "hidden": "false",
  "children": [
    {
      "component": "li",
      "context": {
        "children": [
          {
            "component": "link",
            "href": "#"
          }
        ]
      }
    },
    {
      "component": "li",
      "context": {
        "children": [
          {
            "component": "link",
            "href": "#"
          }
        ]
      }
    },
    {
      "component": "li",
      "context": {
        "children": [
          {
            "component": "link",
            "href": "#"
          }
        ]
      }
    }
  ]
}
  • Content:
    import each from '../../../modules/util/each';
    
    export function toggleHidden(control, target) {
        // reverse hidden on dropdown and control
        target.hidden = !target.hidden;
        control.setAttribute('aria-expanded', !target.hidden);
    }
    
    export default function dropdownBehavior(control) {
        const dropdown = document.getElementById(control.getAttribute('aria-controls'));
        const links = dropdown.querySelectorAll('a, button');
    
        //initial attribute setup
        control.setAttribute('aria-expanded', !dropdown.hidden);
    
        //control behavior
        control.addEventListener('click', event => {
            // Clicks and enter open/close dropdown
            event.preventDefault();
            toggleHidden(control, dropdown);
        });
        control.addEventListener('keydown', event => {
            // Space will open and close dropdown, escape will close the dropdown if the menu is not hidden
            if (event.keyCode === 32 || (event.keyCode === 27 && !dropdown.hidden)) {
                event.preventDefault();
                toggleHidden(control, dropdown);
            }
        });
    
        //if dropdown is open, losing focus of control and not entering dropdown will close it.
        control.addEventListener('focusout', event => {
            if (event.relatedTarget && !dropdown.hidden) {
                let isInThisDropdown = false;
                each(links, link => {
                    if (event.relatedTarget === link) isInThisDropdown = true;
                });
                if (event.relatedTarget === control) isInThisDropdown = true;
                if (!isInThisDropdown) toggleHidden(control, dropdown);
            } else if (!event.relatedTarget && !dropdown.hidden) {
                toggleHidden(control, dropdown);
            }
        });
    
        each(links, link => {
            link.addEventListener('keydown', event => {
                // Escape inside the dropdown will close the dropdown and focus the control
                if (event.keyCode === 27) {
                    //we prevent default, so we don't exit maximized screens on safari
                    event.preventDefault();
                    toggleHidden(control, dropdown);
                    control.focus();
                }
            });
    
            link.addEventListener('focusout', event => {
                if (event.relatedTarget) {
                    let isInThisDropdown = false;
                    each(links, link => {
                        if (event.relatedTarget === link) isInThisDropdown = true;
                    });
                    if (event.relatedTarget === control) isInThisDropdown = true;
                    if (!isInThisDropdown) toggleHidden(control, dropdown);
                } else if (!event.relatedTarget && !dropdown.hidden) {
                    toggleHidden(control, dropdown);
                }
            });
        });
    }
    
  • URL: /components/raw/dropdown/Dropdown.js
  • Filesystem Path: components/molecules/Dropdown/Dropdown.js
  • Size: 2.7 KB

Dropdown

Creates container that can appear & dissappear with a control

  • Add a <a> or <button> as a control.
  • Add the js-dropdown-control class to the control.
  • Add the id of the dropdown to the aria-controls attribute.
  • Make sure to have a fallback link if javascript doesn’t load.
<a 
    class="js-dropdown-control" 
    aria-controls="menu1" 
    href="https://upload.wikimedia.org/wikipedia/commons/c/c7/Gary_Busey_%281976%29.jpg"
>
    link-text
</a>
  • Make any sort of container you’d like that contains links or buttons.
  • Add hidden if you want the dropdown hidden on pageload, and the dh class, to make sure that hidden works.
<div>
    <a 
        class="js-dropdown-control" 
        aria-controls="menu1" 
        href="https://upload.wikimedia.org/wikipedia/commons/c/c7/Gary_Busey_%281976%29.jpg"
    >
        Open Menu
    </a>
    <ul id="menu1" class="dh" hidden>
        <li>
            <a href="https://www.youtube.com/watch?v=k4KKD_SuLRY">Wild in the Streets</a>
        </li>
        <li>
            <a href="https://www.youtube.com/watch?v=ebW8YA-jq5A">Angels Hard as They Come</a>
        </li>
        <li>
            <a href="https://www.youtube.com/watch?v=nB95pK8TgYw">The Magnificent Seven Ride!</a>
        </li>
        <li>
            <a href="https://www.youtube.com/watch?v=VcCjU3fZTis">The Last American Hero</a>
        </li>
    </ul>
</div>