Dropdown

stablev1.0.0

Display the options of a select or nav element as a expandable list box.

Overview

Dropdowns can be used to display nav lists or the options of a select element, in a more compact fashion.

Select example:


Nav example:

Usage

Dependencies

To get the dropdown component working, include the dependencies in your project in the following order:

  1. npm
  2. Sass
  3. JS
"design-system": "git+ssh://git@github.com/Selectra-Dev/design-system.git"
@import 'design-system/src/scss/01-atoms/dropdown';
import initAllDropdowns from 'design-system/src/js/01-atoms/dropdown/DropdownManager';

Basic code

Both dropdown types are built upon standard HTML structures, need some specific CSS classes, and require initialization . Javascript will take care of generating the extra needed elements, and will manage the functionality of all dropdowns in the page.

The initialization can be done executing the initAllDropdowns() function, which must be imported from the DropdownManager.js file. We have some more options which will be covered on the in depth section.

Select based

  • A parent select element, with the class dropdown.
  • Any number of children option elements.

The initialization of this dropdown type, hides the select element and generates the button and the list elements for the user to interact with them.
The script takes care of updating the select options to match the item selected in the list box.

  1. HTML
  2. Pug
  3. JS
<select class="dropdown dropdown--block" name="select-dropdown-example">
  <option value="none" disabled="disabled" selected="selected">Choose wisely...</option>
  <option value="poorlyChoosed0">A burnished cup made of pure gold</option>
  <option value="poorlyChoosed1">An intricately engraved silver chalice</option>
  <option value="Now THIS is a cup of a carpenter">A simple, wooden cup</option>
  <option value="poorlyChoosed2">A grail made of white ivory</option>
  <option value="poorlyChoosed3">A worn out steel cup</option>
  <option value="poorlyChoosed4">A rusty iron noggin</option>
  <option value="poorlyChoosed5">A beautiful copper chalice</option>
</select>
select.dropdown.dropdown--block(name="select-dropdown-example")
  option(value="none", disabled, selected) Choose wisely...
  option(value="poorlyChoosed0") A burnished cup made of pure gold
  option(value="poorlyChoosed1") An intricately engraved silver chalice
  option(value="Now THIS is a cup of a carpenter") A simple, wooden cup
  option(value="poorlyChoosed2") A grail made of white ivory
  option(value="poorlyChoosed3") A worn out steel cup
  option(value="poorlyChoosed4") A rusty iron noggin
  option(value="poorlyChoosed5") A beautiful copper chalice
initAllDropdowns();

Nav based

The NAV dropdown is composed of the following elements:

  • A parent nav element with the class dropdown.
  • A button element with the class dropdown__trigger.
  • A ul element with the class dropdown__content.
  • Any number of li children that must carry the class dropdown__item , each one of them containing an a element the class dropdown__link.
  1. HTML
  2. Pug
  3. JS
<nav class="dropdown dropdown--block">
  <button class="dropdown__trigger">Decide your fate...</button>
  <ul class="dropdown__content">
    <li class="dropdown__item" data-image-left="icon-check-mark">
      <a class="dropdown__link" href="https://www.kernel.org/" target="_blank" rel="nofollow noopener">Linux</a>
    </li>
    <li class="dropdown__item" data-image-left="icon-circle-interrogation-filled">
      <a class="dropdown__link" href="https://www.apple.com" target="_blank" rel="nofollow noopener">Apple</a>
    </li>
    <li class="dropdown__item" data-image-left="icon-cross">
      <a class="dropdown__link" href="https://www.microsoft.com" target="_blank" rel="nofollow noopener">Microsoft</a>
    </li>
  </ul>
</nav>
nav.dropdown.dropdown--block
  button.dropdown__trigger Decide your fate...
  ul.dropdown__content
    li.dropdown__item( data-image-left="icon-check-mark" )
      a.dropdown__link(href='https://www.kernel.org/', target="_blank" rel="nofollow noopener")
        | Linux
    li.dropdown__item( data-image-left="icon-circle-interrogation-filled" )
      a.dropdown__link(href='https://www.apple.com', target="_blank" rel="nofollow noopener" )
        | Apple
    li.dropdown__item( data-image-left="icon-cross" )
      a.dropdown__link(href='https://www.microsoft.com', target="_blank" rel="nofollow noopener" )
        | Microsoft
initAllDropdowns();

In depth

The dropdown component is defined in the following files:

/src/js/01-atoms/dropdown/dropdownManager.js
A manager class to generate dropdowns and keep track of them.
/src/js/01-atoms/dropdown/dropdownBase.js
An incomplete, base dropdown class.
/src/js/01-atoms/dropdown/dropdownList.js
A class representing the nav type dropdowns.
/src/js/01-atoms/dropdown/dropdownSelect.js
A class representing the select type dropdowns.
/src/scss/01-atoms/_dropdown.scss
Component stylesheet.

Example

// Import the manager class from DropdownManager.js
import DropdownManager from '/design-system/src/js/01-atoms/dropdown/DropdownManager.js';

const
  // Get a new manager instance and the target element reference
  manager = new DropdownManager(),
  target = document.getElementById( 'mySelectDropdownId' ),
  // Set a options object
  options = {
    sortList: false,
    createWaypoints: false,
  };

// Initialize the target element
manager.createDropdown( target, options );

// This is just a stupid variable to make super evident
// `manager.dropdowns[ 0 ]` is the *first* dropdown in the page!
const myFirstDropdown = manager.dropdowns[ 0 ];

// Nonsense dropdown manipulation.
myFirstDropdown.showList();
myFirstDropdown.toggleList();

// We disable the third option of our dropdown and rebuild it.
myFirstDropdown.select.el[ 2 ].setAttribute( 'disabled', '' );
myFirstDropdown.rebuild();

The Dropdown Manager

dropdownManager.js exports a initAllDropdowns function, and the DropdownManager class.

initAllDropdowns

A call to this function will initialize all dropdowns on the page, returning a reference to the DropdownManager object used for this task.

It takes an Array of options objects as it's single argument.

const dropdownsOptions = [];

// Define the options object for the third dropdown of the page
dropdownConfigs[ 2 ] = {
  sortList: false,
  createWaypoints: false,
};

// Initialize all dropdowns and keep a reference to the manager
// for later dropdown manipulation
const dropdownManager = initAllDropdowns( dropdownsOptions );

🔍 Note: If you are not planning to use the manager object, you can just call the function and ignore the return value (do not assign it to a variable).

DropdownManager

The DropdownManager serves several purposes:

  1. It's used for dropdown initialization.
  2. It keeps track of all the dropdown it has initialized.
  3. Manages logic concerning all the dropdowns in the page.
Methods
createDropdown( element, options )
Initializes a new dropdown.
Takes two parameters:
  • element : A reference to the node of the base element with the dropdown class.
  • options : An options object.

Dropdown Classes

We have two types of dropdowns and hence two classes to represent them: the DropdownList and the DropdownSelect.

đŸ˜Ŧ I'm lying to you, OK? : We really have three classes... But, the DropdownBase class is a partial dropdown representation and only exists to derivate sub-classes, not to use it directly.

Dropdowns must be initialized using a DropdownManager, simply instantiating a dropdown object using the new keyword, will not work as intended as some global functionality is implemented directly by the manager itself.

You can access the dropdown objects using the manager's dropdowns property.

Options Object
Name Type Default Required Description
sortList bool true No Sort the list of options alphabetically.
createWaypoints bool true No Enables alphabetical navigation of the list through keyboard presses.
spritePath string '/img/sprite.svg' No The path to the svg sprite.
Methods
Shared
remove()
Remove the dropdown from the DOM and its references from the DropdownManager.
All subsequent dropdown objects will have their index property value adjusted accordingly.
showList()
Opens the dropdown list box.
hideList()
Close the dropdown list box.
toggleList()
Change the state of the dropdown list box to the opposite one (Open/Close).
Select only
rebuild()
Rebuild all the elements that are generated during the dropdown initialization.
You can manipulate the select element, and then rebuild the dropdown to make the changes show in the button and/or list.

Check the example.

Modifiers

block

Add the class dropdown--block to the select or nav element and the Dropdown will expand horizontally to occupy all available space.

  1. HTML
  2. Pug
<select class="dropdown dropdown--block">
  <option value="lol0" disabled="disabled" selected="selected">Hey, Listen! I'm a block Dropdown !</option>
  <option value="lol1">Alas, there's nothing to see here 😀</option>
</select>
select.dropdown.dropdown--block
  option(value="lol0", disabled, selected) Hey, Listen! I'm a block Dropdown !
  option(value="lol1") Alas, there's nothing to see here 😀

no-scroll

Add the class .dropdown--no-scroll to the select or nav element to disable the vertical scroll on the Dropdown list box. The option list will be then shown in full.

  1. HTML
  2. Pug
<select class="dropdown dropdown--block dropdown--no-scroll">
  <option value="lol0" disabled="disabled" selected="selected">No vertical scroll allowed !</option>
  <option value="lol1">This is</option>
  <option value="lol2">a very,</option>
  <option value="lol3">very,</option>
  <option value="lol4">very big list</option>
  <option value="lol5">of meaningless options.</option>
  <option value="lol6">It's a good way</option>
  <option value="lol7">to demonstrate</option>
  <option value="lol8">what happens</option>
  <option value="lol9">when we disable</option>
  <option value="lol10">the vertical scroll</option>
  <option value="lol11">functionality.</option>
</select>
select.dropdown.dropdown--block.dropdown--no-scroll
  option(value="lol0", disabled, selected) No vertical scroll allowed !
  option(value="lol1") This is
  option(value="lol2") a very,
  option(value="lol3") very,
  option(value="lol4") very big list
  option(value="lol5") of meaningless options.
  option(value="lol6") It's a good way
  option(value="lol7") to  demonstrate
  option(value="lol8") what happens
  option(value="lol9") when we disable
  option(value="lol10") the vertical scroll
  option(value="lol11") functionality.

HTML attributes

disabled

Set the disabled attribute on the select or nav element to initialize the Dropdown on a disabled state.

  1. HTML
  2. Pug
<select class="dropdown" disabled="disabled">
  <option value="lol0" disabled="disabled" selected="selected">I'm a disabled dropdown... ☚ī¸</option>
  <option value="lol1">What a pity...</option>
</select>
select.dropdown(disabled)
  option(value="lol0", disabled, selected) I'm a disabled dropdown... ☚ī¸
  option(value="lol1") What a pity...

data-image

The data-image-left and data-image-right attributes can be set to a string descriptor of an available design system icon on any option or li element to insert an icon positioned at the left or right side of the text content.

  1. HTML
  2. Pug
<select class="dropdown dropdown--block">
  <option value="lol0" disabled="disabled" selected="selected">Hey! Check my options!</option>
  <option value="lol1" data-image-left="icon-star-filled">It's better to have an icon on the left side.</option>
  <option value="lol2" data-image-right="icon-star-filled">Nope. It's way nicer on the right.</option>
</select>
select.dropdown.dropdown--block
  option(value="lol0", disabled, selected) Hey! Check my options!
  option(value="lol1", data-image-left='icon-star-filled') It's better to have an icon on the left side.
  option(value="lol2", data-image-right='icon-star-filled') Nope. It's way nicer on the  right.