@springernature/global-dropdown
Advanced tools
Comparing version 1.1.0 to 2.0.0
@@ -1,3 +0,3 @@ | ||
import init from '../js'; | ||
import {dropdown} from '../js'; | ||
init('[data-dropdown]', '[data-dropdown-item]'); | ||
dropdown(); |
# History | ||
## 2.0.0 (2021-11-08) | ||
BREAKING | ||
* Delete custom js implementation in favour of the expander component to handle interactions. | ||
## 1.1.0 (2021-11-04) | ||
@@ -4,0 +8,0 @@ * Add ellipsis in the button text |
101
js/index.js
@@ -1,98 +0,27 @@ | ||
/* eslint no-use-before-define: ["error", { "functions": false, "variables": false }] */ | ||
import {Expander} from '../../global-expander/js/expander'; | ||
const actions = { | ||
ESC: ['Escape', 'Esc', 27], | ||
UP: ['ArrowUp', 38], | ||
DOWN: ['ArrowDown', 40] | ||
}; | ||
const DATA_COMPONENT = 'data-dropdown'; | ||
let dropdownButtons; | ||
let dropdownItems; | ||
const normaliseKeyEvent = event => event.key || event.keyCode; | ||
const keyEventIsInAction = (event, targetAction) => targetAction.includes(normaliseKeyEvent(event)); | ||
const escapekeyCloseDropdown = event => { | ||
if (keyEventIsInAction(event, actions.ESC)) { | ||
dropdownButtons.forEach(button => { | ||
closeDropdown(button); | ||
button.focus(); | ||
}); | ||
} | ||
const attributes = { | ||
targetSelector: `${DATA_COMPONENT}-target` | ||
}; | ||
const closeDropdown = button => { | ||
button.setAttribute('aria-expanded', 'false'); | ||
button.nextElementSibling.style.display = 'none'; | ||
button.querySelector('svg').style.transform = null; | ||
document.removeEventListener('keydown', escapekeyCloseDropdown); | ||
}; | ||
const dropdown = () => { | ||
const trigger = document.querySelector(`[${DATA_COMPONENT}]`); | ||
const target = trigger.getAttribute(attributes.targetSelector); | ||
const openDropdown = button => { | ||
button.setAttribute('aria-expanded', 'true'); | ||
button.nextElementSibling.style.display = null; | ||
button.querySelector('svg').style.transform = 'rotate(180deg)'; | ||
button.nextElementSibling.querySelector('[data-dropdown-item]').focus(); | ||
document.addEventListener('keydown', escapekeyCloseDropdown); | ||
}; | ||
const toggleDropdown = button => { | ||
if (button.getAttribute('aria-expanded') === 'false') { | ||
openDropdown(button); | ||
} else if (button.getAttribute('aria-expanded') === 'true') { | ||
closeDropdown(button); | ||
if (trigger.length === 0 || !target) { | ||
return; | ||
} | ||
}; | ||
const handleUpArrow = (index, event) => { | ||
if (keyEventIsInAction(event, actions.UP)) { | ||
event.preventDefault(); | ||
if (index === 0) { | ||
dropdownItems[dropdownItems.length - 1].focus(); | ||
} else { | ||
dropdownItems[index - 1].focus(); | ||
} | ||
const targetElement = document.querySelector(target); | ||
if (!targetElement) { | ||
return; | ||
} | ||
}; | ||
const handleDownArrow = (index, event) => { | ||
if (keyEventIsInAction(event, actions.DOWN)) { | ||
event.preventDefault(); | ||
if (index === dropdownItems.length - 1) { | ||
dropdownItems[0].focus(); | ||
} else { | ||
dropdownItems[index + 1].focus(); | ||
} | ||
} | ||
}; | ||
const expander = new Expander(trigger, targetElement); | ||
const init = (dropdownSelector = '[data-dropdown]', itemSelector = '[data-dropdown-item]') => { | ||
dropdownButtons = [...document.querySelectorAll(dropdownSelector)]; | ||
dropdownItems = [...document.querySelectorAll(itemSelector)]; | ||
[...document.querySelectorAll('.c-dropdown__menu')].forEach(dropdown => { | ||
dropdown.style.display = 'none'; | ||
}); | ||
dropdownButtons.forEach(button => { | ||
button.addEventListener('click', toggleDropdown.bind(null, button)); | ||
}); | ||
document.addEventListener('keyup', function () { | ||
if (!document.activeElement.matches('[data-dropdown-item]')) { | ||
dropdownButtons.forEach(button => { | ||
closeDropdown(button); | ||
}); | ||
} | ||
}); | ||
dropdownItems.forEach((item, index) => { | ||
item.addEventListener('keydown', event => { | ||
handleUpArrow(index, event); | ||
handleDownArrow(index, event); | ||
}); | ||
}); | ||
expander.init(); | ||
}; | ||
export default init; | ||
export {dropdown}; |
{ | ||
"name": "@springernature/global-dropdown", | ||
"version": "1.1.0", | ||
"version": "2.0.0", | ||
"license": "MIT", | ||
@@ -10,7 +10,8 @@ "description": "Display a contextual list of links controlled by a toggle", | ||
"dependencies": { | ||
"@springernature/global-expander": "^4.0.2", | ||
"@springernature/brand-context": "16.0.0" | ||
}, | ||
"scripts": { | ||
"postinstall": "npm_config_registry=https://registry.npmjs.org/ npx @springernature/util-context-warning@0.0.5 -p @springernature/global-dropdown@1.1.0 -v 16.0.0" | ||
"postinstall": "npm_config_registry=https://registry.npmjs.org/ npx @springernature/util-context-warning@0.0.5 -p @springernature/global-dropdown@2.0.0 -v 16.0.0" | ||
} | ||
} |
@@ -25,3 +25,3 @@ # Global Dropdown | ||
<span class="c-dropdown__label">dropdown</span> | ||
<button class="c-dropdown__button" aria-expanded="false" data-dropdown>Dropdown | ||
<button class="c-dropdown__button" aria-expanded="false" data-dropdown data-dropdown-target="#dropdown">Dropdown | ||
<svg aria-hidden="true" width="10" height="10" aria-hidden="true" focusable="false"> | ||
@@ -31,3 +31,3 @@ <use xlink:href="i-chevron-more"></use> | ||
</button> | ||
<ul class="c-dropdown__menu"> | ||
<ul class="c-dropdown__menu" id="#dropdown"> | ||
<li><a href="#" class="c-dropdown__link" data-dropdown-item>Option 1</a></li> | ||
@@ -42,7 +42,13 @@ <li><a href="#" class="c-dropdown__link" data-dropdown-item>Option 2</a></li> | ||
```javascript | ||
import {dropdown} from 'global-dropdown/js'; | ||
dropdown(); | ||
``` | ||
init(dropdownSelector = '[data-dropdown]', itemSelector = '[data-dropdown-item]') | ||
``` | ||
By default the component relies on a data-dropdown and data-dropdown-item HTML attributes. These can be overwritten in the init function. | ||
The first argument is a CSS selector to target the dropdown button. The second argument is a CSS selector to target items inside the list. | ||
The component uses the Expander from the global toolkit to handle the events. | ||
You can get a quick implementation by adding these two attributes `data-dropdown` and `data-dropdown-target` in your HTML as shown at the example above. | ||
If you need more flexibility, use the expander component directly following its [documentation](https://github.com/springernature/frontend-toolkits/tree/master/toolkits/global/packages/global-expander). | ||
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
21541
52
1
2
58
+ Added@springernature/global-expander@4.2.2(transitive)
+ Added@springernature/global-javascript@3.0.4(transitive)